From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2308 invoked by alias); 16 Apr 2008 19:22:04 -0000 Received: (qmail 2284 invoked by uid 22791); 16 Apr 2008 19:22:02 -0000 X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.33.17) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 16 Apr 2008 19:21:04 +0000 Received: from zps78.corp.google.com (zps78.corp.google.com [172.25.146.78]) by smtp-out.google.com with ESMTP id m3GJKqPf014119 for ; Wed, 16 Apr 2008 20:20:53 +0100 Received: from localhost (ruffy.corp.google.com [172.18.118.116]) by zps78.corp.google.com with ESMTP id m3GJKne1011865; Wed, 16 Apr 2008 12:20:49 -0700 Received: by localhost (Postfix, from userid 67641) id 984F91C75AD; Wed, 16 Apr 2008 12:20:47 -0700 (PDT) To: gdb@sourceware.org cc: ppluzhnikov@google.com Subject: determining whether page 0 (or low addresses in general) is executable Message-Id: <20080416192047.984F91C75AD@localhost> Date: Wed, 16 Apr 2008 22:20:00 -0000 From: dje@google.com (Doug Evans) X-IsSubscribed: yes 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: 2008-04/txt/msg00158.txt.bz2 Hi. We're trying to come up with a workaround for an apparent gcc/linker issue where debug info can be left behind that messes up backtraces. The erroneous debug info shouldn't be generated, but gdb could do a better job when faced with it. foo.h: struct Foo { Foo() { } }; foo.cc: #include "foo.h" typedef void (*FN)(void); void crash() { FN f = (FN)1; f(); } int main() { Foo f; crash(); return 0; } bar.cc: #include "foo.h" int bar() { Foo f; return 0; } bash$ x86_64-linux-g++ --version x86_64-linux-g++ (GCC) 4.2.1 [...] bash$ x86_64-linux-g++ -g foo.cc bar.cc bash$ readelf -wf a.out | grep -A5 pc=0000 00000090 0000001c 00000078 FDE cie=00000078 pc=00000000..0000000a DW_CFA_advance_loc: 1 to 00000001 DW_CFA_def_cfa_offset: 16 DW_CFA_offset: r6 at cfa-16 DW_CFA_advance_loc: 3 to 00000004 DW_CFA_def_cfa_reg: r6 The constructor for Foo is emitted in both foo.o and bar.o, but the duplicate is only partially removed. bash$ gdb a.out GNU gdb 6.8 [...] (gdb) r Starting program: /tmp/a.out Program received signal SIGSEGV, Segmentation fault. 0x0000000000000001 in ?? () (gdb) bt #0 0x0000000000000001 in ?? () #1 0x0000000000400670 in ?? () #2 0x0000000000000001 in ?? () #3 0x0000000000400642 in main () at foo.cc:21 (gdb) If we apply the following hack, which makes GDB ignore unwind descriptors in the first page, we get the expected backtrace. *** dwarf2-frame.c~ Wed Apr 16 11:16:43 2008 --- dwarf2-frame.c Wed Apr 16 11:16:43 2008 *************** dwarf2_frame_find_fde (CORE_ADDR *pc) *** 1571,1576 **** --- 1571,1583 ---- { struct objfile *objfile; + if (*pc < (CORE_ADDR)0x1000) + { + /* Workaround for apparent toolchain issue, + ignore any unwind descriptors that describe code on the zero page. + We know there is no code there. */ + return NULL; + } ALL_OBJFILES (objfile) { struct dwarf2_fde *fde; bash$ hacked-gdb a.out (gdb) r Starting program: /tmp/a.out Program received signal SIGSEGV, Segmentation fault. 0x0000000000000001 in ?? () (gdb) bt #0 0x0000000000000001 in ?? () #1 0x000000000040062a in crash () at foo.cc:15 #2 0x0000000000400642 in main () at foo.cc:21 (gdb) Assuming we want to have dwarf2_frame_find_fde reject clearly bogus pc values, the issue is of course how to cleanly recognize them. Suggestions? One alternative is something like this, the catch being how to write is_zero_page_executable. *************** dwarf2_frame_find_fde (CORE_ADDR *pc) @@ -1585,6 +1608,13 @@ while (fde) { + if (fde->initial_location + offset == 0 + && !is_zero_page_executable ()) + { + /* Ignore this FDE -- linker bug. */ + fde = fde->next; + continue; + }