Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Simon Marchi <simon.marchi@polymtl.ca>
To: Yao Qi <qiyaoltc@gmail.com>
Cc: GDB Patches <gdb-patches@sourceware.org>
Subject: Re: [PATCH 2/2] Fix gdb.mi/mi-stack.exp when gcc generates a stack protector
Date: Sat, 07 Apr 2018 18:14:00 -0000	[thread overview]
Message-ID: <b81db7ce-2a04-7e7a-60db-e0b61358e888@polymtl.ca> (raw)
In-Reply-To: <CAH=s-POy7MWgXub=vFEa9SvNBp14S3=A-_TWASOcF_gBw7Euhw@mail.gmail.com>

On 2018-01-03 04:53 PM, Yao Qi wrote:
> On Tue, Jan 2, 2018 at 6:14 PM, Simon Marchi <simon.marchi@polymtl.ca> wrote:
>> On 2018-01-02 05:38, Yao Qi wrote:
>>> Can't we fix GDB to skip these stack protection code?
>>
>>
>> I think it would be desirable to consider the stack protection code as part
>> of the prologue, since it's compiler-generated and of little interest to the
>> user.  But I don't know how to do it without breaking existing behavior.
>>
> 
> Yes, we can skip them as part of skipping prologue.
> 
>> Our heuristic, when using SaL to skip prologue, is to consider the first
>> linetable entry to represent the prologue.  If we find a consecutive entry
>> with the same line number, we assume it's the prologue -> body transition
>> (because otherwise there would be no point in having a separate entry).
>> When adding a stack protector, gcc puts it in a separate linetable entry, as
>> if it was user code, so GDB thinks it's the beginning of the body.
>>
>> Let's take this small example:
>>
>> 1  int main()
>> 2  {
>> 3    int n = 0;
>> 4    n++;
>> 5    return n;
>> 6  }
>>
>> Which compiles to this with -fstack-protector-all:
>>
>>    0x0000000000400546 <+0>:     push   %rbp
>>    0x0000000000400547 <+1>:     mov    %rsp,%rbp
>>    0x000000000040054a <+4>:     sub    $0x10,%rsp
>>    0x000000000040054e <+8>:     mov    %fs:0x28,%rax
>>    0x0000000000400557 <+17>:    mov    %rax,-0x8(%rbp)
>>    0x000000000040055b <+21>:    xor    %eax,%eax
>>    0x000000000040055d <+23>:    movl   $0x0,-0xc(%rbp)
>>    0x0000000000400564 <+30>:    addl   $0x1,-0xc(%rbp)
>>    0x0000000000400568 <+34>:    mov    -0xc(%rbp),%eax
>>    0x000000000040056b <+37>:    mov    -0x8(%rbp),%rdx
>>    0x000000000040056f <+41>:    xor    %fs:0x28,%rdx
>>    0x0000000000400578 <+50>:    je     0x40057f <main+57>
>>    0x000000000040057a <+52>:    callq  0x400420 <__stack_chk_fail@plt>
>>    0x000000000040057f <+57>:    leaveq
>>    0x0000000000400580 <+58>:    retq
>>
>> test.c                                         2            0x400546
>> test.c                                         2            0x40054e
>> test.c                                         3            0x40055d
>> test.c                                         4            0x400564
>> test.c                                         5            0x400568
>> test.c                                         6            0x40056b
>>
>> GDB currently assumes that the second entry is the beginning of the body.
>> But ideally we would treat the first two entries as the prologue, and put
>> our breakpoint on line 3/0x40055d.
>>
>> And then let's look at this modified example, where the first line of code
>> is on the same line as the opening curly bracket, and compiled without stack
>> protection (-fno-stack-protector):
>>
>> 1  int main()
>> 2  { int n = 0;
>> 3    n++;
>> 4    return n;
>> 5  }
>>
>>
>>    0x00000000004004d6 <+0>:     push   %rbp
>>    0x00000000004004d7 <+1>:     mov    %rsp,%rbp
>>    0x00000000004004da <+4>:     movl   $0x0,-0x4(%rbp)
>>    0x00000000004004e1 <+11>:    addl   $0x1,-0x4(%rbp)
>>    0x00000000004004e5 <+15>:    mov    -0x4(%rbp),%eax
>>    0x00000000004004e8 <+18>:    pop    %rbp
>>    0x00000000004004e9 <+19>:    retq
>>
>> test.c                                         2            0x4004d6
>> test.c                                         2            0x4004da
>> test.c                                         3            0x4004e1
>> test.c                                         4            0x4004e5
>> test.c                                         5            0x4004e8
>>
>> We have a similar line table as the previous example (same source line,
>> different address), but in this case the second entry at line 2 is really
>> the start of user code.  We would want to put our breakpoint at line
>> 2/0x4004da.  So, how do we differentiate these two cases?
>>
> 
> When GDB sets breakpoint, it calls gdbarch_skip_prologue_noexcept
> to skip prologue, amd64 backend doesn't use SAL to identify the end
> of prologue unless compiler is clang (see amd64_skip_prologue).
> Instead, GDB scans prologue to find the end of prologue, so we can
> extend amd64 prologue analyzer to understand these instructions
> for stack protection.
> 
> (gdb) b callee4
> 
> Thread 1 "gdb" hit Breakpoint 1, amd64_analyze_prologue
> (gdbarch=gdbarch@entry=0x154ef60, pc=pc@entry=4195734,
> current_pc=current_pc@entry=18446744073709551615,
>     cache=cache@entry=0x7fffffffd1e0) at
> ../../binutils-gdb/gdb/amd64-tdep.c:2319
> 2319    {
> (gdb) bt 10
> #0  amd64_analyze_prologue (gdbarch=gdbarch@entry=0x154ef60,
> pc=pc@entry=4195734, current_pc=current_pc@entry=18446744073709551615,
> cache=cache@entry=0x7fffffffd1e0)
>     at ../../binutils-gdb/gdb/amd64-tdep.c:2319
> #1  0x0000000000428b8c in amd64_skip_prologue (gdbarch=0x154ef60,
> start_pc=4195734) at ../../binutils-gdb/gdb/amd64-tdep.c:2488
> #2  0x0000000000515363 in gdbarch_skip_prologue_noexcept
> (gdbarch=gdbarch@entry=0x154ef60, pc=pc@entry=4195734) at
> ../../binutils-gdb/gdb/arch-utils.c:970
> #3  0x0000000000692b03 in skip_prologue_sal
> (sal=sal@entry=0x7fffffffd4d0) at ../../binutils-gdb/gdb/symtab.c:3721
> #4  0x0000000000692e02 in find_function_start_sal
> (sym=sym@entry=0x158e8b0, funfirstline=1) at
> ../../binutils-gdb/gdb/symtab.c:3594
> #5  0x00000000005fe0dd in symbol_to_sal
> (result=result@entry=0x7fffffffd6d0, funfirstline=<optimized out>,
> sym=sym@entry=0x158e8b0)
>     at ../../binutils-gdb/gdb/linespec.c:4611
> 
> We did something similar in arm-tdep.c, search "__stack_chk_guard".
> However, I am not sure we can find a "fingerprint" of these stack projection
> instructions on amd64.
> 

I ended up pushing these patches.  Since this issue of skipping the stack check
instructions is relatively low priority, I don't think the behavior will change
any time soon, and I'd rather fix that test now.

Simon


      parent reply	other threads:[~2018-04-07 18:14 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-16 14:57 [PATCH 1/2] Fix indentation in gdb.mi/mi-stack.exp Simon Marchi
2017-12-16 14:57 ` [PATCH 2/2] Fix gdb.mi/mi-stack.exp when gcc generates a stack protector Simon Marchi
2018-01-02 10:38   ` Yao Qi
2018-01-02 18:14     ` Simon Marchi
2018-01-03 21:53       ` Yao Qi
2018-01-03 22:39         ` Simon Marchi
2018-01-04 20:10           ` Simon Marchi
2018-04-07 18:14         ` Simon Marchi [this message]

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=b81db7ce-2a04-7e7a-60db-e0b61358e888@polymtl.ca \
    --to=simon.marchi@polymtl.ca \
    --cc=gdb-patches@sourceware.org \
    --cc=qiyaoltc@gmail.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