This is the mail archive of the gdb@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]

determining whether page 0 (or low addresses in general) is executable


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;
+          }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]