This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
On 2018-01-03 16:53, 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, asif 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 0x40056bGDB 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 putour 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 stackprotection (-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 0x4004e8We 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 reallythe 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.
Ahh ok, amd64_skip_prologue calls skip_prologue_using_sal, but I didn't see the result was only used for clang! So I was stepping in skip_prologue_using_sal all this time for nothing :)
(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 projectioninstructions on amd64.
Thanks for the pointers, I'll take a look. Simon
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |