From: Andrew Burgess <aburgess@redhat.com>
To: Guinevere Larsen <guinevere@redhat.com>,
Pawel Kupczak <pawel.kupczak@intel.com>,
gdb-patches@sourceware.org
Subject: Re: [PATCH 1/3] gdb, amd64: extend the amd64 prologue analyzer to skip register pushes
Date: Fri, 18 Jul 2025 16:23:58 +0100 [thread overview]
Message-ID: <8734atldyp.fsf@redhat.com> (raw)
In-Reply-To: <91a1e38e-2978-4e81-a168-762ed55d3811@redhat.com>
Guinevere Larsen <guinevere@redhat.com> writes:
> Hello! Thanks for working on this!
>
> I am not an authority on i386, but I did notice a few things that gave
> me pause so I'd like to ask them to make sure I understand the changes.
>
> Skipping the commit message:
> On 7/1/25 7:47 AM, Pawel Kupczak wrote:
>> ---
>> gdb/amd64-tdep.c | 53 +++++++++++-
>> .../amd64-extended-prologue-analysis.c | 49 +++++++++++
>> .../amd64-extended-prologue-analysis.exp | 86 +++++++++++++++++++
>> 3 files changed, 187 insertions(+), 1 deletion(-)
>> mode change 100644 => 100755 gdb/amd64-tdep.c
>> create mode 100644 gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.c
>> create mode 100644 gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.exp
>>
>> diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
>> old mode 100644
>> new mode 100755
>> index 82dd1e07cf3..863b29a8c27
>> --- a/gdb/amd64-tdep.c
>> +++ b/gdb/amd64-tdep.c
>> @@ -2553,6 +2553,56 @@ amd64_analyze_frame_setup (gdbarch *gdbarch, CORE_ADDR pc,
>> return pc;
>> }
>>
>> +/* Check whether PC points at code pushing registers onto the stack. If so,
>> + update CACHE and return pc after those pushes or CURRENT_PC, whichever is
>> + smaller. Otherwise, return PC passed to this function. */
>> +
>> +static CORE_ADDR
>> +amd64_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
>> + amd64_frame_cache *cache)
>> +{
>> + gdb_byte op;
>> + int offset = 0;
>> +
>> + /* There are at most 16 registers that would be pushed in the prologue. */
>> + for (int i = 0; i < 16 && pc < current_pc; i++)
>> + {
>> + int reg = 0;
>> + int pc_offset = 0;
>> +
>> + if (target_read_code (pc, &op, 1) == -1)
>> + return pc;
>> +
>> + /* %r8 - %r15 prefix. */
>> + if (op == 0x41)
>
> Looking over on the disassembler for record-full, I see that all 0x4-
> are considered prefixes, and (in 64 bit targets) they all have this effect.
>
> Is this something that could affect this prologue analyzer? ie, that
> some prefix like 0x40 is used to mean "push a register larger than 7",
> which would cause us to not skip that instruction?
>
>> + {
>> + reg += 8;
>> + pc_offset = 1;
>> +
>> + if (target_read_code (pc + 1, &op, 1) == -1)
>> + return pc;
>> + }
>> +
>> + /* push %rax|%rcx|%rdx|%rbx|%rsp|%rbp|%rsi|%rdi
>> +
>> + or with 0x41 prefix:
>> + push %r8|%r9|%r10|%r11|%r12|%r13|%r14|%r15. */
>> + if (op < 0x50 || op > 0x57)
>> + break;
>
> This code also ignores the "push lz" and "push lb" instructions. Could
> they be used as prologue instructions? (again, this comes from the
> recording disassembler)
>
> If so, I would think this is worth explicity saying it in the comment at
> the top of the function, otherwise it could confuse us in the future.
>
>> +
>> + reg += op - 0x50;
>> + offset -= 8;
>> +
>> + int regnum = amd64_arch_reg_to_regnum (reg);
>> + cache->saved_regs[regnum] = offset;
>> + cache->sp_offset += 8;
>> +
>> + pc += 1 + pc_offset;
>> + }
>> +
>> + return pc;
>> +}
>> +
>> /* Do a limited analysis of the prologue at PC and update CACHE
>> accordingly. Bail out early if CURRENT_PC is reached. Return the
>> address where the analysis stopped.
>> @@ -2594,7 +2644,8 @@ amd64_analyze_prologue (gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR current_pc,
>> if (current_pc <= pc)
>> return current_pc;
>>
>> - return amd64_analyze_frame_setup (gdbarch, pc, current_pc, cache);
>> + pc = amd64_analyze_frame_setup (gdbarch, pc, current_pc, cache);
>> + return amd64_analyze_register_saves (pc, current_pc, cache);
>> }
>>
>> /* Work around false termination of prologue - GCC PR debug/48827.
>> diff --git a/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.c b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.c
>> new file mode 100644
>> index 00000000000..7d777d23236
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.arch/amd64-extended-prologue-analysis.c
>> @@ -0,0 +1,49 @@
>> +/* This testcase is part of GDB, the GNU debugger.
>> +
>> + Copyright 2025 Free Software Foundation, Inc.
>> +
>> + This program is free software; you can redistribute it and/or modify
>> + it under the terms of the GNU General Public License as published by
>> + the Free Software Foundation; either version 3 of the License, or
>> + (at your option) any later version.
>> +
>> + This program is distributed in the hope that it will be useful,
>> + but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + GNU General Public License for more details.
>> +
>> + You should have received a copy of the GNU General Public License
>> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
>> +
>> +int __attribute__ ((noinline))
>> +bar (int x)
>> +{
>> + return x + x;
>> +}
>> +
>> +/* This function should generate a prologue in shape of:
>> + push %rbp
>> + .cfi_def_cfa_offset 16
>> + .cfi_offset %rbp, -16
>> + mov %rsp, %rbp
>> + .cfi_def_cfa_register %rbp
>> + push %reg1
>> + push %reg2
>> + .cfi_offset %reg2, 32
>> + .cfi_offset %reg1, 24
>> +
>> + So to be able to unwind a register, GDB needs to skip prologue past
>> + register pushes (to access .cfi directives). */
>
> In general, if possible, I think it's preferred that we actually use
> assembly instead of relying on compiler behavior. You should be able to
> use asm statements to create a fake function, and either the dwarf
> assembler to actually label it as such... Maybe even using global labels
> to do that more easily (not sure if GDB would use the prologue skip in
> that case, though).
I think there's definitely scope for both types of test in cases like
this. On the one hand, we are interested in debugging actual code, so
if a future compiler does something unexpected, then it would be nice to
see a test break.
But as Gwen says, having tests that use fixed assembler sequences does
mean that GDB is guaranteed to always support a particular series of
instructions.
The good thing in this case is that the test is 100% amd64 specific, so
it should be easy enough to just grab the disassembly from the current
test binary, and build a test around that. You might even be able to
fold the two tests into one, something like:
standard_testfile .c .S
then you can compile $srcfile and $srcfile2 in turn and run the exact
same test proc against the compiled binary. Though this isn't a hard
requirement, if its easier to do it some other way, then that's fine.
Thanks,
Andrew
next prev parent reply other threads:[~2025-07-18 15:25 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-01 10:47 [PATCH 0/3] extending the amd64 prologue analyzer Pawel Kupczak
2025-07-01 10:47 ` [PATCH 1/3] gdb, amd64: extend the amd64 prologue analyzer to skip register pushes Pawel Kupczak
2025-07-18 13:43 ` Guinevere Larsen
2025-07-18 15:15 ` Kupczak, Pawel
2025-07-23 10:34 ` Kupczak, Pawel
2025-07-23 16:07 ` Guinevere Larsen
2025-07-18 15:23 ` Andrew Burgess [this message]
2025-07-18 16:04 ` Schimpe, Christina
2025-07-01 10:47 ` [PATCH 2/3] gdb, amd64: return after amd64_analyze_frame_setup if current_pc reached Pawel Kupczak
2025-07-18 13:46 ` Guinevere Larsen
2025-07-18 15:19 ` Kupczak, Pawel
2025-07-18 14:46 ` Andrew Burgess
2025-07-18 15:21 ` Kupczak, Pawel
2025-07-01 10:47 ` [PATCH 3/3] gdb, amd64: extend the amd64 prologue analyzer to skip stack alloc Pawel Kupczak
2025-07-15 7:37 ` [PING] [PATCH 0/3] extending the amd64 prologue analyzer Kupczak, Pawel
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=8734atldyp.fsf@redhat.com \
--to=aburgess@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=guinevere@redhat.com \
--cc=pawel.kupczak@intel.com \
/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