From 084303b8c636944564d7be3b85dde55e8c371e91 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Wed, 28 Sep 2016 17:54:06 +0200 Subject: [PATCH] Add .cfi_val_offset GAS command. 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 * 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 * dwarf.c (display_debug_frames): Adjust output line. --- binutils/dwarf.c | 4 +-- gas/doc/as.texinfo | 3 ++ gas/dw2gencfi.c | 42 ++++++++++++++++++++++++++++ gas/dw2gencfi.h | 1 + gas/testsuite/gas/cfi/cfi-common-8.d | 23 +++++++++++++++ gas/testsuite/gas/cfi/cfi-common-8.s | 6 ++++ gas/testsuite/gas/cfi/cfi.exp | 1 + 7 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 gas/testsuite/gas/cfi/cfi-common-8.d create mode 100644 gas/testsuite/gas/cfi/cfi-common-8.s diff --git a/binutils/dwarf.c b/binutils/dwarf.c index e07f6614201..95b33a8723e 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -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') diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo index cdaeb6b010b..82cc72dd2b2 100644 --- a/gas/doc/as.texinfo +++ b/gas/doc/as.texinfo @@ -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} diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c index fb3e302a438..4fbdf4248e2 100644 --- a/gas/dw2gencfi.c +++ b/gas/dw2gencfi.c @@ -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 } }; diff --git a/gas/dw2gencfi.h b/gas/dw2gencfi.h index 9ef102080f8..cbc4233aae6 100644 --- a/gas/dw2gencfi.h +++ b/gas/dw2gencfi.h @@ -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 index 00000000000..61556909e20 --- /dev/null +++ b/gas/testsuite/gas/cfi/cfi-common-8.d @@ -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 index 00000000000..8477ff0f3b2 --- /dev/null +++ b/gas/testsuite/gas/cfi/cfi-common-8.s @@ -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 diff --git a/gas/testsuite/gas/cfi/cfi.exp b/gas/testsuite/gas/cfi/cfi.exp index 9b6012e1031..30568564b25 100644 --- a/gas/testsuite/gas/cfi/cfi.exp +++ b/gas/testsuite/gas/cfi/cfi.exp @@ -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" } -- 2.30.2