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: Thu, 04 Jan 2018 20:10:00 -0000	[thread overview]
Message-ID: <cd2f5e9747e3b659283844e90c9a00a0@polymtl.ca> (raw)
In-Reply-To: <9d03aaad5c96a6682253c689190cb680@polymtl.ca>

On 2018-01-03 17:39, Simon Marchi wrote:
>> 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.
> 
> Thanks for the pointers, I'll take a look.
> 
> Simon

Hi Yao,

The instructions to put the stack check guard seem recognizable enough, 
it's always

    0x000000000040057a <+52>:    mov    %fs:0x28,%rax
    0x0000000000400583 <+61>:    mov    %rax,-0x8(%rbp)
    0x0000000000400587 <+65>:    xor    %eax,%eax

with maybe the offset in the second mov changing.  The problem is that 
there is all kinds of things we currently don't recognize that could be 
in the prologue before that.  For example, a function with many 
parameters will have this (when built with -O0):

    0x0000000000400546 <+0>:     push   %rbp
    0x0000000000400547 <+1>:     mov    %rsp,%rbp
    0x000000000040054a <+4>:     sub    $0x40,%rsp
    0x000000000040054e <+8>:     mov    %edi,-0x14(%rbp)
    0x0000000000400551 <+11>:    mov    %esi,-0x18(%rbp)
    0x0000000000400554 <+14>:    mov    %edx,-0x1c(%rbp)
    0x0000000000400557 <+17>:    mov    %ecx,-0x20(%rbp)
    0x000000000040055a <+20>:    mov    %r8d,-0x24(%rbp)
    0x000000000040055e <+24>:    mov    %r9d,-0x28(%rbp)
    0x0000000000400562 <+28>:    mov    0x10(%rbp),%eax
    0x0000000000400565 <+31>:    mov    %eax,-0x2c(%rbp)
    0x0000000000400568 <+34>:    mov    0x18(%rbp),%eax
    0x000000000040056b <+37>:    mov    %eax,-0x30(%rbp)
    0x000000000040056e <+40>:    mov    0x20(%rbp),%eax
    0x0000000000400571 <+43>:    mov    %eax,-0x34(%rbp)
    0x0000000000400574 <+46>:    mov    0x28(%rbp),%eax
    0x0000000000400577 <+49>:    mov    %eax,-0x38(%rbp)
    --- end of prologue currently ---
    0x000000000040057a <+52>:    mov    %fs:0x28,%rax
    0x0000000000400583 <+61>:    mov    %rax,-0x8(%rbp)
    0x0000000000400587 <+65>:    xor    %eax,%eax
    --- end of prologue ideally ---
    0x0000000000400589 <+67>:    mov    -0x14(%rbp),%edx
    0x000000000040058c <+70>:    mov    -0x18(%rbp),%eax
    0x000000000040058f <+73>:    add    %eax,%edx
    0x0000000000400591 <+75>:    mov    -0x1c(%rbp),%eax
    0x0000000000400594 <+78>:    add    %eax,%edx

Currently, everything in [0x400546,0x40057a[ covered by a single line 
statement (it's what we consider as the prologue today).  In 
amd64_skip_prologue, we move the PC past the "push %rbp" and "mov 
%rsp,%rbp".  The generic code then notices that we left pc in the middle 
of a line, so it moves it to the start of the next line, at 0x40057a, 
effectively moving past the prologue.  If we wanted to skip the stack 
check as well, we would have to recognize all the movs that copy the 
arguments on the stack, and then recognize the stack check guard setup.  
But even if we do it, we'll have a problem when the first line of code 
is on the same line as the opening curly bracket like this:

int foo(int i, int j, int k, int l, int m, int n, int o, int p, int q, 
int r)
{       int x = i + j + k + l + m + n + o + p + q + r;
         x++;
         return x;
}

The line statements are:

CU: ./test.c:
File name                            Line number    Starting address
test.c                                         2            0x400546
test.c                                         2            0x40057a
test.c                                         3            0x4005bc
test.c                                         4            0x4005c0
test.c                                         5            0x4005c3
test.c                                         8            0x4005d9
test.c                                         8            0x4005e1
test.c                                         9            0x4005f7
test.c                                        10            0x400626

If we manage to recognize instructions and push the PC to after the 
stack check guard setup (0x400589), the generic code will notice that we 
are in the middle of a line, and skip to 0x4005bc, which is then too 
far, as it would skip some user code.  The problem is really that there 
is a single line statement covering both the stack check guard and the 
user code.

So I think that gcc should do one of these:

1. Include the stack check guard setup code in the prologue line 
statement:

test.c                                         2            0x400546
test.c                                         2            0x400589
test.c                                         3            0x4005bc
...

GDB wouldn't have to do anything more than it does today.

2. Have a line statement only for the stack check guard setup, separate 
from the user code:

test.c                                         2            0x400546
test.c                                         2            0x40057a
test.c                                         2            0x400589
test.c                                         3            0x4005bc

In that case, GDB would have to do a bit more than it does today, but at 
least we would be able to find the stack "check guard -> user code" 
transition.

Idea #1 seems better to me, because it's easier for us :) and existing 
GDBs would do the right thing with newer GCCs.

Does that make sense, or am I missing something?

Thanks,

Simon


  reply	other threads:[~2018-01-04 20:10 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 [this message]
2018-04-07 18:14         ` Simon Marchi

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=cd2f5e9747e3b659283844e90c9a00a0@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