From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 121886 invoked by alias); 3 Jan 2018 22:39:22 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 121858 invoked by uid 89); 3 Jan 2018 22:39:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS,SPF_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy= X-HELO: smtp.polymtl.ca Received: from smtp.polymtl.ca (HELO smtp.polymtl.ca) (132.207.4.11) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 03 Jan 2018 22:39:20 +0000 Received: from simark.ca (simark.ca [158.69.221.121]) (authenticated bits=0) by smtp.polymtl.ca (8.14.7/8.14.7) with ESMTP id w03MdDmx023640 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 3 Jan 2018 17:39:18 -0500 Received: by simark.ca (Postfix, from userid 112) id C0BE81E5A6; Wed, 3 Jan 2018 17:39:13 -0500 (EST) Received: from simark.ca (localhost [127.0.0.1]) by simark.ca (Postfix) with ESMTP id 2B6FD1E02D; Wed, 3 Jan 2018 17:39:02 -0500 (EST) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit Date: Wed, 03 Jan 2018 22:39:00 -0000 From: Simon Marchi To: Yao Qi Cc: GDB Patches Subject: Re: [PATCH 2/2] Fix gdb.mi/mi-stack.exp when gcc generates a stack protector In-Reply-To: References: <20171216145651.13936-1-simon.marchi@polymtl.ca> <20171216145651.13936-2-simon.marchi@polymtl.ca> <9860ca45c4896a0e42190f4c34c68c4a@polymtl.ca> Message-ID: <9d03aaad5c96a6682253c689190cb680@polymtl.ca> X-Sender: simon.marchi@polymtl.ca User-Agent: Roundcube Webmail/1.3.2 X-Poly-FromMTA: (simark.ca [158.69.221.121]) at Wed, 3 Jan 2018 22:39:13 +0000 X-IsSubscribed: yes X-SW-Source: 2018-01/txt/msg00041.txt.bz2 On 2018-01-03 16:53, Yao Qi wrote: > On Tue, Jan 2, 2018 at 6:14 PM, Simon Marchi > 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 >> 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. 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=, > 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