From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id E73ED3858430; Fri, 20 Jan 2023 14:06:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E73ED3858430 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1674223597; bh=AC4RVPNeeRy2qkL8wm33tuU9TTBB+sotka2I3JzrlWk=; h=From:To:Subject:Date:From; b=pBotfUn5kL6qKgYCPDAQ4+jSPqqOqlvbeigKAhX8/uyLwrse4tjkF8hBFZKzJR3YH zcy11tyP1hJa4ixjse6ViarogPOslN6tsiZEGXEU1E26E2BHpYohRCu5ov7ya7DyHp nvasOrLN9J5W7cXVp+PaJwC8ZJFAyDjfXd2wxS1c= From: "vries at gcc dot gnu.org" To: gdb-prs@sourceware.org Subject: [Bug tdep/30028] New: [gdb/tdep, x86_64] Epilogue unwinder preferred over dwarf unwinder based on gcc 4.4 Date: Fri, 20 Jan 2023 14:06:37 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gdb X-Bugzilla-Component: tdep X-Bugzilla-Version: HEAD X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: vries at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Resolution: X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: unassigned at sourceware dot org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://sourceware.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://sourceware.org/bugzilla/show_bug.cgi?id=3D30028 Bug ID: 30028 Summary: [gdb/tdep, x86_64] Epilogue unwinder preferred over dwarf unwinder based on gcc 4.4 Product: gdb Version: HEAD Status: NEW Severity: normal Priority: P2 Component: tdep Assignee: unassigned at sourceware dot org Reporter: vries at gcc dot gnu.org Target Milestone: --- Consider test-case gdb.base/unwind-on-each-insn.exp. On x86_64-linux, it passes. Now, let's revert the fix in commit 49d7cd733a7 ("Change calculation of frame_id by amd64 epilogue unwinder"): ... $ git show 49d7cd733a7f1b87aa1d40318b3d7c2b65aca5ac gdb/amd64-tdep.c > tmp.patch $ patch -p1 -R < tmp.patch=20 patching file gdb/amd64-tdep.c Hunk #1 succeeded at 2945 (offset 8 lines). Hunk #2 succeeded at 2994 (offset 8 lines). ... Now we have: ... FAIL: gdb.base/unwind-on-each-insn.exp: instruction 5: $fba_value =3D=3D $f= oo_fba FAIL: gdb.base/unwind-on-each-insn.exp: instruction 5: check frame-id match= es ... OK, so the test-case acts as regression test for this commit, that seems as intended. For context, let's look at the foo insns: ... 00000000004004bc : 4004bc: 55 push %rbp 4004bd: 48 89 e5 mov %rsp,%rbp 4004c0: 90 nop 4004c1: 5d pop %rbp 4004c2: c3 ret ... This is a minimal version of the failure: ... $ gdb -q -batch outputs/gdb.base/unwind-on-each-insn/unwind-on-each-insn \ -ex "b *foo" \ -ex run \ -ex "si 3" \ -ex "info frame" \ -ex si \ -ex "info frame" Breakpoint 1 at 0x4004bc Breakpoint 1, 0x00000000004004bc in foo () 0x00000000004004c1 in foo () Stack level 0, frame at 0x7fffffffdae0: rip =3D 0x4004c1 in foo; saved rip =3D 0x4004b5 called by frame at 0x7fffffffdaf0 Arglist at 0x7fffffffdad0, args:=20 Locals at 0x7fffffffdad0, Previous frame's sp is 0x7fffffffdae0 Saved registers: rbp at 0x7fffffffdad0, rip at 0x7fffffffdad8 0x00000000004004c2 in foo () Stack level 0, frame at 0x7fffffffdad8: rip =3D 0x4004c2 in foo; saved rip =3D 0x4004b5 called by frame at 0x7fffffffdaf0 Arglist at 0x7fffffffdae0, args:=20 Locals at 0x7fffffffdae0, Previous frame's sp is 0x7fffffffdae0 Saved registers: rip at 0x7fffffffdad8 ... The problem is that the "frame at" lists a different address at the last in= sn. However, we also have this information available: ... 00000068 000000000000001c 0000003c FDE cie=3D00000030 pc=3D00000000004004bc..00000000004004c3=20=20=20=20=20 LOC CFA rbp ra 00000000004004bc rsp+8 u c-8 00000000004004bd rsp+16 c-16 c-8 00000000004004c0 rbp+16 c-16 c-8 00000000004004c2 rsp+8 c-16 c-8 ... Let's see if it is correct. At 0x00000000004004c1 we have: ... (gdb) p $rbp+16 $1 =3D (void *) 0x7fffffffdae0 ... At 0x00000000004004c2 we have: ... (gdb) p $rsp+8 $2 =3D (void *) 0x7fffffffdae0 ... Well, that looks correct. So, why is this info not used? The amd64 epilogue unwinder (the one containing the bug), has the highest priority: ... /* Hook the function epilogue frame unwinder. This unwinder is=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20 appended to the list first, so that it supercedes the other=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20 unwinders in function epilogues. */=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20 frame_unwind_prepend_unwinder (gdbarch, &amd64_epilogue_frame_unwind);=20= =20=20=20=20=20=20=20 ... Let's try to see what happens if we disable it: ... 0x00000000004004c2 in foo () Stack level 0, frame at 0x7fffffffdbcc: ... Hmm, that's also no good, it seems that the i386_epilogue_frame_unwind kick= ed in. I don't under stand why this would be active for x86_64 code, maybe that is= a bug in itself. Anyway, why does this one have this high priority? Well, the code says: ... /* Hook the function epilogue frame unwinder. This unwinder is=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20 appended to the list first, so that it supercedes the DWARF=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20 unwinder in function epilogues (where the DWARF unwinder=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 currently fails). */ frame_unwind_append_unwinder (gdbarch, &i386_epilogue_frame_unwind); ... Hmm, so the "currently" refers to July 2009. In the submission discussion I find this ( https://sourceware.org/pipermail/gdb-patches/2009-July/066792.html ): ... > I also think you should add a comment about the specific ordering of > this unwinder. It has to come before the dwarf2 unwinder because GCC > doesn't provide proper CFI for the epilogue, right? Right - I would like to have a way to suppress this unwinder, maybe based on the producer string like other recognized dwarf2-frame quirks, but we can worry about that later. I hope it will be unnecessary with GCC 4.5. ... So, if I understand correctly, the priority decision was done based on gcc = 4.4. So maybe it's time to revisit this. I suppose the producer test is doable, but we'll need to decide about trust= ed vs untrusted versions, which atm I have no clue about. A minor benefit of preferring dwarf is that behaviour will be more similar = to targets that do not have epilogue unwinders. Anyway, disabling i386_epilogue_frame_unwind gives me the desired: ... 0x00000000004004c2 in foo () Stack level 0, frame at 0x7fffffffdad0: ... and indeed, the test-case passes again. At the very least, I would like a maintenance command that tells gdb to pre= fer dwarf over the epilogue unwinder, in order to be able to test the actual dw= arf. That could also be used to proactively spot bugs in the epilogue unwinder. --=20 You are receiving this mail because: You are on the CC list for the bug.=