From: Alan Modra <amodra@gmail.com>
To: binutils@sourceware.org
Subject: PR29250, readelf erases CIE initial register state
Date: Thu, 16 Jun 2022 09:55:27 +0930 [thread overview]
Message-ID: <Yqp4d0ZJvuy0PcbK@squeak.grove.modra.org> (raw)
PR 29250
binutils/
* dwarf.c (display_debug_frames): Set col_type[reg] on sizing
pass over FDE to cie->col_type[reg] if CIE specifies reg.
Handle DW_CFA_restore and DW_CFA_restore_extended on second
pass using the same logic. Remove unnecessary casts. Don't
call frame_need_space on second pass over FDE.
gas/
* testsuite/gas/i386/ehinterp.d,
* testsuite/gas/i386/ehinterp.s: New test.
* testsuite/gas/i386/i386.exp: Run it.
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index c16f5a891b7..f11eeaa24ce 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -9306,18 +9306,17 @@ display_debug_frames (struct dwarf_section *section,
/* Warning: if you add any more cases to this switch, be
sure to add them to the corresponding switch below. */
+ reg = -1u;
switch (op)
{
case DW_CFA_advance_loc:
break;
case DW_CFA_offset:
SKIP_ULEB (start, block_end);
- if (frame_need_space (fc, opa) >= 0)
- fc->col_type[opa] = DW_CFA_undefined;
+ reg = opa;
break;
case DW_CFA_restore:
- if (frame_need_space (fc, opa) >= 0)
- fc->col_type[opa] = DW_CFA_undefined;
+ reg = opa;
break;
case DW_CFA_set_loc:
if ((size_t) (block_end - start) < encoded_ptr_size)
@@ -9347,29 +9346,19 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_val_offset:
READ_ULEB (reg, start, block_end);
SKIP_ULEB (start, block_end);
- if (frame_need_space (fc, reg) >= 0)
- fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_restore_extended:
READ_ULEB (reg, start, block_end);
- if (frame_need_space (fc, reg) >= 0)
- fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_undefined:
READ_ULEB (reg, start, block_end);
- if (frame_need_space (fc, reg) >= 0)
- fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_same_value:
READ_ULEB (reg, start, block_end);
- if (frame_need_space (fc, reg) >= 0)
- fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_register:
READ_ULEB (reg, start, block_end);
SKIP_ULEB (start, block_end);
- if (frame_need_space (fc, reg) >= 0)
- fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_def_cfa:
SKIP_ULEB (start, block_end);
@@ -9396,15 +9385,11 @@ display_debug_frames (struct dwarf_section *section,
start = block_end;
else
start += temp;
- if (frame_need_space (fc, reg) >= 0)
- fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_offset_extended_sf:
case DW_CFA_val_offset_sf:
READ_ULEB (reg, start, block_end);
SKIP_SLEB (start, block_end);
- if (frame_need_space (fc, reg) >= 0)
- fc->col_type[reg] = DW_CFA_undefined;
break;
case DW_CFA_def_cfa_sf:
SKIP_ULEB (start, block_end);
@@ -9425,12 +9410,21 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_GNU_negative_offset_extended:
READ_ULEB (reg, start, block_end);
SKIP_ULEB (start, block_end);
- if (frame_need_space (fc, reg) >= 0)
- fc->col_type[reg] = DW_CFA_undefined;
break;
default:
break;
}
+ if (reg != -1u && frame_need_space (fc, reg) >= 0)
+ {
+ /* Don't leave any reg as DW_CFA_unreferenced so
+ that frame_display_row prints name of regs in
+ header, and all referenced regs in each line. */
+ if (reg >= cie->ncols
+ || cie->col_type[reg] == DW_CFA_unreferenced)
+ fc->col_type[reg] = DW_CFA_undefined;
+ else
+ fc->col_type[reg] = cie->col_type[reg];
+ }
}
start = tmp;
}
@@ -9480,7 +9474,7 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_offset:
READ_ULEB (roffs, start, block_end);
- if (opa >= (unsigned int) fc->ncols)
+ if (opa >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_offset: %s%s at cfa%+ld\n",
@@ -9494,7 +9488,7 @@ display_debug_frames (struct dwarf_section *section,
break;
case DW_CFA_restore:
- if (opa >= (unsigned int) fc->ncols)
+ if (opa >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_restore: %s%s\n",
@@ -9502,9 +9496,8 @@ display_debug_frames (struct dwarf_section *section,
if (*reg_prefix != '\0')
break;
- if (opa >= (unsigned int) cie->ncols
- || (do_debug_frames_interp
- && cie->col_type[opa] == DW_CFA_unreferenced))
+ if (opa >= cie->ncols
+ || cie->col_type[opa] == DW_CFA_unreferenced)
{
fc->col_type[opa] = DW_CFA_undefined;
fc->col_offset[opa] = 0;
@@ -9569,7 +9562,7 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_offset_extended:
READ_ULEB (reg, start, block_end);
READ_ULEB (roffs, start, block_end);
- if (reg >= (unsigned int) fc->ncols)
+ if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_offset_extended: %s%s at cfa%+ld\n",
@@ -9585,7 +9578,7 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_val_offset:
READ_ULEB (reg, start, block_end);
READ_ULEB (roffs, start, block_end);
- if (reg >= (unsigned int) fc->ncols)
+ if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_val_offset: %s%s is cfa%+ld\n",
@@ -9600,7 +9593,7 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_restore_extended:
READ_ULEB (reg, start, block_end);
- if (reg >= (unsigned int) fc->ncols)
+ if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_restore_extended: %s%s\n",
@@ -9608,7 +9601,8 @@ display_debug_frames (struct dwarf_section *section,
if (*reg_prefix != '\0')
break;
- if (reg >= (unsigned int) cie->ncols)
+ if (reg >= cie->ncols
+ || cie->col_type[reg] == DW_CFA_unreferenced)
{
fc->col_type[reg] = DW_CFA_undefined;
fc->col_offset[reg] = 0;
@@ -9622,7 +9616,7 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_undefined:
READ_ULEB (reg, start, block_end);
- if (reg >= (unsigned int) fc->ncols)
+ if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_undefined: %s%s\n",
@@ -9636,7 +9630,7 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_same_value:
READ_ULEB (reg, start, block_end);
- if (reg >= (unsigned int) fc->ncols)
+ if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_same_value: %s%s\n",
@@ -9651,7 +9645,7 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_register:
READ_ULEB (reg, start, block_end);
READ_ULEB (roffs, start, block_end);
- if (reg >= (unsigned int) fc->ncols)
+ if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
{
@@ -9761,7 +9755,7 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_expression:
READ_ULEB (reg, start, block_end);
READ_ULEB (ul, start, block_end);
- if (reg >= (unsigned int) fc->ncols)
+ if (reg >= fc->ncols)
reg_prefix = bad_reg;
/* PR 17512: file: 069-133014-0.006. */
/* PR 17512: file: 98c02eb4. */
@@ -9786,7 +9780,7 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_val_expression:
READ_ULEB (reg, start, block_end);
READ_ULEB (ul, start, block_end);
- if (reg >= (unsigned int) fc->ncols)
+ if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (ul > (size_t) (block_end - start))
{
@@ -9809,7 +9803,7 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_offset_extended_sf:
READ_ULEB (reg, start, block_end);
READ_SLEB (l, start, block_end);
- if (frame_need_space (fc, reg) < 0)
+ if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_offset_extended_sf: %s%s at cfa%+ld\n",
@@ -9825,7 +9819,7 @@ display_debug_frames (struct dwarf_section *section,
case DW_CFA_val_offset_sf:
READ_ULEB (reg, start, block_end);
READ_SLEB (l, start, block_end);
- if (frame_need_space (fc, reg) < 0)
+ if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_val_offset_sf: %s%s is cfa%+ld\n",
@@ -9885,7 +9879,7 @@ display_debug_frames (struct dwarf_section *section,
READ_ULEB (reg, start, block_end);
READ_SLEB (l, start, block_end);
l = - l;
- if (frame_need_space (fc, reg) < 0)
+ if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_GNU_negative_offset_extended: %s%s at cfa%+ld\n",
diff --git a/gas/testsuite/gas/i386/ehinterp.d b/gas/testsuite/gas/i386/ehinterp.d
new file mode 100644
index 00000000000..5b6ac858709
--- /dev/null
+++ b/gas/testsuite/gas/i386/ehinterp.d
@@ -0,0 +1,20 @@
+#readelf: --debug-dump=frames-interp
+
+Contents of the \.eh_frame section:
+
+0+ 0+14 0+ CIE "zR" cf=1 df=-8 ra=16
+ +LOC +CFA +ra *
+0+ rsp\+8 +c-8 *
+
+0+18 0+10 0+1c FDE cie=0+ pc=0+..0+6
+ +LOC +CFA +ra *
+0+ rsp\+8 +c-8 *
+0+4 rsp\+8 +u *
+
+0+2c 0+20 0+30 FDE cie=0+ pc=0+6..0+24
+ +LOC +CFA +rbp +ra *
+0+6 rsp\+8 +u +c-8 *
+0+b rsp\+16 +c-16 +c-8 *
+0+e rbp\+16 +c-16 +c-8 *
+0+23 rsp\+8 +c-16 +c-8 *
+
diff --git a/gas/testsuite/gas/i386/ehinterp.s b/gas/testsuite/gas/i386/ehinterp.s
new file mode 100644
index 00000000000..634cef1aab3
--- /dev/null
+++ b/gas/testsuite/gas/i386/ehinterp.s
@@ -0,0 +1,35 @@
+ .file "hello.c"
+ .text
+ .section .rodata
+.LC0:
+ .string "Hello"
+ .text
+ .globl dummy
+ .type dummy, @function
+dummy:
+ .cfi_startproc
+ endbr64
+ .cfi_undefined rip
+ jmp .
+ .cfi_endproc
+ .size dummy, .-dummy
+
+ .globl main
+ .type main, @function
+main:
+ .cfi_startproc
+ endbr64
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ leaq .LC0(%rip), %rax
+ movq %rax, %rdi
+ call puts@PLT
+ movl $0, %eax
+ popq %rbp
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+ .size main, .-main
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 99a11ebde78..a4fc5b4096b 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -1339,7 +1339,7 @@ if [gas_64_check] then {
if {[istarget "*-*-linux*"]} then {
run_dump_test "x86-64-align-branch-3"
}
-
+ run_dump_test ehinterp
}
run_dump_test pr27198
--
Alan Modra
Australia Development Lab, IBM
reply other threads:[~2022-06-16 0:25 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Yqp4d0ZJvuy0PcbK@squeak.grove.modra.org \
--to=amodra@gmail.com \
--cc=binutils@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).