From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 125208 invoked by alias); 4 Jan 2018 20:10:12 -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 125198 invoked by uid 89); 4 Jan 2018 20:10:11 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-7.0 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_2,SPF_HELO_PASS,SPF_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=notices 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; Thu, 04 Jan 2018 20:10:10 +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 w04KA3Or024803 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Thu, 4 Jan 2018 15:10:08 -0500 Received: by simark.ca (Postfix, from userid 112) id 890191E5A6; Thu, 4 Jan 2018 15:10:03 -0500 (EST) Received: from simark.ca (localhost [127.0.0.1]) by simark.ca (Postfix) with ESMTP id E3F741E51D; Thu, 4 Jan 2018 15:09:56 -0500 (EST) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit Date: Thu, 04 Jan 2018 20:10: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: <9d03aaad5c96a6682253c689190cb680@polymtl.ca> References: <20171216145651.13936-1-simon.marchi@polymtl.ca> <20171216145651.13936-2-simon.marchi@polymtl.ca> <9860ca45c4896a0e42190f4c34c68c4a@polymtl.ca> <9d03aaad5c96a6682253c689190cb680@polymtl.ca> Message-ID: X-Sender: simon.marchi@polymtl.ca User-Agent: Roundcube Webmail/1.3.2 X-Poly-FromMTA: (simark.ca [158.69.221.121]) at Thu, 4 Jan 2018 20:10:03 +0000 X-IsSubscribed: yes X-SW-Source: 2018-01/txt/msg00060.txt.bz2 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=, >> 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