From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25542 invoked by alias); 10 Jun 2011 07:45:47 -0000 Received: (qmail 25511 invoked by uid 22791); 10 Jun 2011 07:45:43 -0000 X-SWARE-Spam-Status: No, hits=-6.4 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_OV,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 10 Jun 2011 07:45:26 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p5A7jPjQ015804 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 10 Jun 2011 03:45:25 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (tyan-ft48-01.lab.bos.redhat.com [10.16.42.4]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p5A7jO9e007936 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 10 Jun 2011 03:45:25 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (localhost.localdomain [127.0.0.1]) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4) with ESMTP id p5A7jOQ8029276; Fri, 10 Jun 2011 09:45:24 +0200 Received: (from jakub@localhost) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4/Submit) id p5A7jOxB029275; Fri, 10 Jun 2011 09:45:24 +0200 Date: Fri, 10 Jun 2011 07:45:00 -0000 From: Jakub Jelinek To: libc-alpha@sourceware.org, binutils@sourceware.org, gdb@sourceware.org Cc: Mark Wielaard , Frank Eigler Subject: RFC: Unwind info for PLT Message-ID: <20110610074524.GR17079@tyan-ft48-01.lab.bos.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2011-06/txt/msg00064.txt.bz2 Hi! Sorry for the wide posting, but this is something that isn't limited to one particular component. Frank yesterday raised on IRC a problem that PLT doesn't have unwind info. So, when a debugger or systemtap stops in PLT or if an async signal is sent to the process while inside of PLT and e.g. calls backtrace or attempts to unwind through, it will stop in the PLT slot. Example testcase: cat > lib1.c <<\EOF #define A(n) void n (void) {} #define B(n) A(n##0) A(n##1) A(n##2) A(n##3) A(n##4) A(n##5) A(n##6) A(n##7) A(n##8) A(n##9) #define C(n) B(n##0) B(n##1) B(n##2) B(n##3) B(n##4) B(n##5) B(n##6) B(n##7) B(n##8) B(n##9) #define D(n) C(n##0) C(n##1) C(n##2) C(n##3) C(n##4) C(n##5) C(n##6) C(n##7) C(n##8) C(n##9) #define E(n) D(n##0) D(n##1) D(n##2) D(n##3) D(n##4) D(n##5) D(n##6) D(n##7) D(n##8) D(n##9) E(f) EOF cat > prg1.c <<\EOF #include #include #include #define A(n) extern void n (void); #define B(n) A(n##0) A(n##1) A(n##2) A(n##3) A(n##4) A(n##5) A(n##6) A(n##7) A(n##8) A(n##9) #define C(n) B(n##0) B(n##1) B(n##2) B(n##3) B(n##4) B(n##5) B(n##6) B(n##7) B(n##8) B(n##9) #define D(n) C(n##0) C(n##1) C(n##2) C(n##3) C(n##4) C(n##5) C(n##6) C(n##7) C(n##8) C(n##9) #define E(n) D(n##0) D(n##1) D(n##2) D(n##3) D(n##4) D(n##5) D(n##6) D(n##7) D(n##8) D(n##9) E(f) static void handler (int sig, siginfo_t *info, void *ctx) { void *buf[256]; int n = backtrace (buf, 256); backtrace_symbols_fd (buf, n, 2); } int main () { struct sigaction s; sigemptyset (&s.sa_mask); s.sa_sigaction = handler; s.sa_flags = SA_RESETHAND | SA_ONSTACK; sigaction (SIGUSR1, &s, NULL); #undef A #define A(n) n (); E(f) return 0; } EOF gcc -shared -fpic -O2 -o lib1.so lib1.c -g gcc -O2 -g -o prg1 prg1.c ./lib1.so gdb apparently has some code to default to a certain unwind info if no FDE is found, as b 'f0001@plt'; c; bt; works and stepi; bt; works too, but next stepi; bt; already gives #0 0x0000000000494f73 in f0001@plt () #1 0x0000000000000be7 in ?? () #2 0x00000000004b03d8 in main () at prg1.c:29 instead of #0 0x0000000000494f73 in f0001@plt () #1 0x00000000004b03d8 in main () at prg1.c:29 But when doing b 'f0002@plt'; c; then kill -USR1 `pidof prg1` from another terminal and then continuing, the backtrace shown stops in the plt and doesn't go back. I wonder whether ld couldn't synthetize unwind info for the .plt section (perhaps with some option), or alternatively if it couldn't just provide hidden __PLT_START__/__PLT_END__ or similar symbols and the unwind info couldn't be written in glibc crtfiles linked into it. For x86_64 which has .plt like: Disassembly of section .plt: 00000035e7a1ec50 : 35e7a1ec50: ff 35 9a 33 37 00 pushq 0x37339a(%rip) # 35e7d91ff0 <_GLOBAL_OFFSET_TABLE_+0x8> 35e7a1ec56: ff 25 9c 33 37 00 jmpq *0x37339c(%rip) # 35e7d91ff8 <_GLOBAL_OFFSET_TABLE_+0x10> 35e7a1ec5c: 0f 1f 40 00 nopl 0x0(%rax) 00000035e7a1ec60 : 35e7a1ec60: ff 25 9a 33 37 00 jmpq *0x37339a(%rip) # 35e7d92000 <_GLOBAL_OFFSET_TABLE_+0x18> 35e7a1ec66: 68 00 00 00 00 pushq $0x0 35e7a1ec6b: e9 e0 ff ff ff jmpq 35e7a1ec50 00000035e7a1ec70 : 35e7a1ec70: ff 25 92 33 37 00 jmpq *0x373392(%rip) # 35e7d92008 <_GLOBAL_OFFSET_TABLE_+0x20> 35e7a1ec76: 68 01 00 00 00 pushq $0x1 35e7a1ec7b: e9 d0 ff ff ff jmpq 35e7a1ec50 ... I think unwind info could look roughly like untested following if we raised .plt alignment to 16 bytes instead of 4, i.e. have explicit unwind info for the first 16 bytes and then for the rest compute CFA expression as %rsp + 8 + ((%rip & 15) >= 11) * 8 00000000 00000014 00000000 CIE Version: 1 Augmentation: "zR" Code alignment factor: 1 Data alignment factor: -8 Return address column: 16 Augmentation data: 1b DW_CFA_def_cfa: r7 (rsp) ofs 8 DW_CFA_offset: r16 (rip) at cfa-8 DW_CFA_nop DW_CFA_nop 00000018 00000024 0000001c FDE cie=00000000 pc=__PLT_START__..__PLT_END__ DW_CFA_def_cfa_offset: 16 DW_CFA_advance_loc: 6 to __PLT_START__+6 DW_CFA_def_cfa_offset: 24 DW_CFA_advance_loc: 10 to __PLT_START__+16 DW_CFA_def_cfa_expression: (DW_OP_breg7 (rsp): 8; DW_OP_breg16 (rip): 0; DW_OP_lit15; DW_OP_and; DW_OP_lit11; DW_OP_ge; DW_OP_lit3; DW_OP_shl; DW_OP_plus;) DW_OP_nop DW_OP_nop DW_OP_nop DW_OP_nop If .plt is kept just 4 bytes aligned it would be slightly harder. If we could rely on %rip being just xxx@plt, xxx@plt+6 or xxx@plt+11, we could just dereference the byte at %rip and decide based on it, somathing like %rsp + 8 + (*(char*)%rip == 0xe9) * 8 DW_CFA_def_cfa_expression: (DW_OP_breg7 (rsp): 8 DW_OP_breg16 (rip): 0; DW_OP_deref_size: 1; DW_OP_const1u: 233; DW_OP_eq; DW_OP_lit3; DW_OP_shl; DW_OP_plus;) but can we rely on it (i.e. won't something give us %rip-1 instead)? I think for at least the libgcc unwinder it shouldn't, because the only way to see a PLT slot is through an async signal handler that stops inside of PLT and the sigreturn pad should be using S. Anyway, I think hardcoding this in the linker would be problematic, we couldn't tweak it, so providing some special hidden symbols around the .plt section and let glibc crtfiles provide it sounds like the best option to me. What do you think? For other architectures of course the unwind info would need to be different, i?86 32-bit would look quite similar if we use the insn decoding version, as there the only jump after one push (disregarding first 16 bytes of .plt section which would be explicit) has also 0xe9 opcode, just the register numbers would be different, offset 4 instead of 8 and shl by 2 instead of 3. BTW, the unwind info for _dl_runtime_resolve on x86_64 is wrong on the first instruction as well: (gdb) bt #0 0x00000035e7613840 in _dl_runtime_resolve () from /lib64/ld-linux-x86-64.so.2 #1 0x00000035e78202a8 in _r_debug () #2 0x0000000000000be7 in ?? () #3 0x00000000004b03d8 in main () at prg1.c:29 (gdb) stepi 0x00000035e7613844 in _dl_runtime_resolve () from /lib64/ld-linux-x86-64.so.2 (gdb) bt #0 0x00000035e7613844 in _dl_runtime_resolve () from /lib64/ld-linux-x86-64.so.2 #1 0x00000000004b03d8 in main () at prg1.c:29 Untested fix below: 2011-06-10 Jakub Jelinek * sysdeps/x86_64/dl-trampoline.S (_dl_runtime_resolve): Fix CFA offset on the first insn. --- libc/sysdeps/x86_64/dl-trampoline.S.jj 2009-08-29 03:34:52.000000000 +0200 +++ libc/sysdeps/x86_64/dl-trampoline.S 2011-06-10 09:34:16.000000000 +0200 @@ -1,5 +1,5 @@ /* PLT trampolines. x86-64 version. - Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2007, 2009, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -27,8 +27,9 @@ .align 16 cfi_startproc _dl_runtime_resolve: + cfi_adjust_cfa_offset(16) # Incorporate PLT subq $56,%rsp - cfi_adjust_cfa_offset(72) # Incorporate PLT + cfi_adjust_cfa_offset(56) movq %rax,(%rsp) # Preserve registers otherwise clobbered. movq %rcx, 8(%rsp) movq %rdx, 16(%rsp) Jakub