Add .cfi_val_offset GAS command.
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Wed, 28 Sep 2016 15:54:06 +0000 (17:54 +0200)
committerAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Thu, 29 Sep 2016 14:33:25 +0000 (16:33 +0200)
This patch adds support for .cfi_val_offset GAS pseudo command which
maps to DW_CFA_val_offset and DW_CFA_val_offset_sf.

gas/ChangeLog:

2016-09-29  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

* doc/as.texinfo: Add docu for .cfi_val_offset.
* dw2gencfi.c (cfi_add_CFA_val_offset): New function.
(dot_cfi): Add case for DW_CFA_val_offset.
(output_cfi_insn): Likewise.
(cfi_pseudo_table): Add entry for cfi_val_offset.
* dw2gencfi.h: Add prototype for cfi_add_CFA_val_offset.
* testsuite/gas/cfi/cfi-common-8.d: New test.
* testsuite/gas/cfi/cfi-common-8.s: New test.
* testsuite/gas/cfi/cfi.exp: Run cfi-common-8 testcase.

binutils/ChangeLog:

2016-09-29  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

* dwarf.c (display_debug_frames): Adjust output line.

binutils/dwarf.c
gas/doc/as.texinfo
gas/dw2gencfi.c
gas/dw2gencfi.h
gas/testsuite/gas/cfi/cfi-common-8.d [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi-common-8.s [new file with mode: 0644]
gas/testsuite/gas/cfi/cfi.exp

index e07f66142016bec3cb65b7a10c89b0767342bf51..95b33a8723ec4d3f8a41ac58c3339782b035d771 100644 (file)
@@ -6418,7 +6418,7 @@ display_debug_frames (struct dwarf_section *section,
              if (reg >= (unsigned int) fc->ncols)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
-               printf ("  DW_CFA_val_offset: %s%s at cfa%+ld\n",
+               printf ("  DW_CFA_val_offset: %s%s is cfa%+ld\n",
                        reg_prefix, regname (reg, 0),
                        roffs * fc->data_factor);
              if (*reg_prefix == '\0')
@@ -6653,7 +6653,7 @@ display_debug_frames (struct dwarf_section *section,
              if (frame_need_space (fc, reg) < 0)
                reg_prefix = bad_reg;
              if (! do_debug_frames_interp || *reg_prefix != '\0')
-               printf ("  DW_CFA_val_offset_sf: %s%s at cfa%+ld\n",
+               printf ("  DW_CFA_val_offset_sf: %s%s is cfa%+ld\n",
                        reg_prefix, regname (reg, 0),
                        (long)(l * fc->data_factor));
              if (*reg_prefix == '\0')
index cdaeb6b010b9d75e5009b2263a454a99c8542d78..82cc72dd2b2a69f453eff0ec44d12386d8fce8eb 100644 (file)
@@ -4831,6 +4831,9 @@ value that is added/substracted from the previous offset.
 Previous value of @var{register} is saved at offset @var{offset} from
 CFA.
 
+@subsection @code{.cfi_val_offset @var{register}, @var{offset}}
+Previous value of @var{register} is CFA + @var{offset}.
+
 @subsection @code{.cfi_rel_offset @var{register}, @var{offset}}
 Previous value of @var{register} is saved at offset @var{offset} from
 the current CFA register.  This is transformed to @code{.cfi_offset}
index fb3e302a43839e20704fbac07aecda73e2117b0b..4fbdf4248e2e38a00bb8f0fc5bd3e9addc0b52a0 100644 (file)
@@ -600,6 +600,22 @@ cfi_add_CFA_offset (unsigned regno, offsetT offset)
     as_bad (_("register save offset not a multiple of %u"), abs_data_align);
 }
 
+/* Add a DW_CFA_val_offset record to the CFI data.  */
+
+void
+cfi_add_CFA_val_offset (unsigned regno, offsetT offset)
+{
+  unsigned int abs_data_align;
+
+  gas_assert (DWARF2_CIE_DATA_ALIGNMENT != 0);
+  cfi_add_CFA_insn_reg_offset (DW_CFA_val_offset, regno, offset);
+
+  abs_data_align = (DWARF2_CIE_DATA_ALIGNMENT < 0
+                   ? -DWARF2_CIE_DATA_ALIGNMENT : DWARF2_CIE_DATA_ALIGNMENT);
+  if (offset % abs_data_align)
+    as_bad (_("register save offset not a multiple of %u"), abs_data_align);
+}
+
 /* Add a DW_CFA_def_cfa record to the CFI data.  */
 
 void
@@ -727,6 +743,7 @@ const pseudo_typeS cfi_pseudo_table[] =
     { "cfi_val_encoded_addr", dot_cfi_val_encoded_addr, 0 },
     { "cfi_inline_lsda", dot_cfi_inline_lsda, 0 },
     { "cfi_label", dot_cfi_label, 0 },
+    { "cfi_val_offset", dot_cfi, DW_CFA_val_offset },
     { NULL, NULL, 0 }
   };
 
@@ -827,6 +844,13 @@ dot_cfi (int arg)
       cfi_add_CFA_offset (reg1, offset);
       break;
 
+    case DW_CFA_val_offset:
+      reg1 = cfi_parse_reg ();
+      cfi_parse_separator ();
+      offset = cfi_parse_const ();
+      cfi_add_CFA_val_offset (reg1, offset);
+      break;
+
     case CFI_rel_offset:
       reg1 = cfi_parse_reg ();
       cfi_parse_separator ();
@@ -1680,6 +1704,23 @@ output_cfi_insn (struct cfi_insn_data *insn)
        }
       break;
 
+    case DW_CFA_val_offset:
+      regno = insn->u.ri.reg;
+      offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
+      if (offset < 0)
+       {
+         out_one (DW_CFA_val_offset_sf);
+         out_uleb128 (regno);
+         out_sleb128 (offset);
+       }
+      else
+       {
+         out_one (DW_CFA_val_offset);
+         out_uleb128 (regno);
+         out_uleb128 (offset);
+       }
+      break;
+
     case DW_CFA_register:
       out_one (DW_CFA_register);
       out_uleb128 (insn->u.rr.reg1);
@@ -2516,6 +2557,7 @@ const pseudo_typeS cfi_pseudo_table[] =
     { "cfi_val_encoded_addr", dot_cfi_dummy, 0 },
     { "cfi_label", dot_cfi_dummy, 0 },
     { "cfi_inline_lsda", dot_cfi_dummy, 0 },
+    { "cfi_val_offset", dot_cfi_dummy, 0 },
     { NULL, NULL, 0 }
   };
 
index 9ef102080f85fccde3e156d47b3dc45e2cecec74..cbc4233aae6b9cc0b12387a00fd6a8b5315f4a41 100644 (file)
@@ -41,6 +41,7 @@ extern void cfi_add_advance_loc (struct symbol *);
 extern void cfi_add_label (const char *);
 
 extern void cfi_add_CFA_offset (unsigned, offsetT);
+extern void cfi_add_CFA_val_offset (unsigned, offsetT);
 extern void cfi_add_CFA_def_cfa (unsigned, offsetT);
 extern void cfi_add_CFA_register (unsigned, unsigned);
 extern void cfi_add_CFA_def_cfa_register (unsigned);
diff --git a/gas/testsuite/gas/cfi/cfi-common-8.d b/gas/testsuite/gas/cfi/cfi-common-8.d
new file mode 100644 (file)
index 0000000..6155690
--- /dev/null
@@ -0,0 +1,23 @@
+#objdump: -Wf
+#name: CFI common 8
+#...
+Contents of the .eh_frame section:
+
+00000000 0+0010 0+0000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: .*
+  Data alignment factor: .*
+  Return address column: .*
+  Augmentation data:     [01]b
+
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000014 0+00(18|1c|20) 0+0018 FDE cie=0+0000 pc=.*
+  DW_CFA_advance_loc: 4 to .*
+  DW_CFA_def_cfa: r0( \([er]ax\)|) ofs 16
+  DW_CFA_val_offset(_sf|): r1( \((rdx|ecx)\)|) is cfa\+8
+  DW_CFA_val_offset(_sf|): r2( \((rcx|edx)\)|) is cfa-32
+#...
diff --git a/gas/testsuite/gas/cfi/cfi-common-8.s b/gas/testsuite/gas/cfi/cfi-common-8.s
new file mode 100644 (file)
index 0000000..8477ff0
--- /dev/null
@@ -0,0 +1,6 @@
+       .cfi_startproc simple
+       .long 0
+       .cfi_def_cfa 0, 16
+       .cfi_val_offset 1, 8
+       .cfi_val_offset 2, -32
+       .cfi_endproc
index 9b6012e1031ee6e0067e7332ef0ab27639753303..30568564b25f5ecb8a409d882c5563df34139de5 100644 (file)
@@ -135,4 +135,5 @@ if { ![istarget "hppa64*-*"] } then {
     run_dump_test "cfi-common-6"
   }
   run_dump_test "cfi-common-7"
+  run_dump_test "cfi-common-8"
 }