gdbfpic

Gdb cannot find assertion failure positions after recompiling


It seems that gdb fails finding the code position of an assertion failure, after I recompile my code. More precisely, I expect the position of a signal raise, relative to an assertion failure, to be

0x00007ffff7a5ff00 in raise () from /lib64/libc.so.`6

while instead I obtain

0x00007ffff7a5ff00 in ?? ()

For instance, consider the following code

#include <assert.h>

int main()
{
  assert(0);
  return 0;
}

compiled with debug symbols and debugged with gdb.

> gcc -g main.c
> gdb a.out

On the first run of gdb, the position is found, and the backtrace is reported correctly:

GNU gdb (Gentoo 8.0.1 p1) 8.0.1 
...
(gdb) r
Starting program: /home/myself/a.out 
a.out: main.c:5: main: Assertion `0' failed.

Program received signal SIGABRT, Aborted.
0x00007ffff7a5ff00 in raise () from /lib64/libc.so.6
(gdb) bt
#0  0x00007ffff7a5ff00 in raise () from /lib64/libc.so.6
#1  0x00007ffff7a61baa in abort () from /lib64/libc.so.6
#2  0x00007ffff7a57cb7 in ?? () from /lib64/libc.so.6
#3  0x00007ffff7a57d72 in __assert_fail () from /lib64/libc.so.6
#4  0x00005555555546b3 in main () at main.c:5
(gdb)

The problem comes when I recompile the code. After recompiling, I issue the run command in the same gdb instance. Gdb re-reads the symbols, starts the program from the beginning, but does not find the right position:

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
`/home/myself/a.out' has changed; re-reading symbols.
Starting program: /home/myself/a.out 
a.out: main.c:5: main: Assertion `0' failed.

Program received signal SIGABRT, Aborted.
0x00007ffff7a5ff00 in ?? ()
(gdb) bt
#0  0x00007ffff7a5ff00 in ?? ()
#1  0x0000000000000000 in ?? ()
(gdb) up
Initial frame selected; you cannot go up.
(gdb) n
Cannot find bounds of current function

At this point the debugger is unusable. One cannot go up, step forward. As a workaround, I can manually reload the file, and positions are found again.

(gdb) file a.out
Load new symbol table from "a.out"? (y or n) y
Reading symbols from a.out...done.
(gdb) r
Starting program: /home/myself/a.out 
a.out: main.c:5: main: Assertion `0' failed.

Program received signal SIGABRT, Aborted.
0x00007ffff7a5ff00 in raise () from /lib64/libc.so.6
(gdb) 

Unfortunately, after reloading the file this way, gdb fails resetting the breakpoints.

ERRATA CORRIGE: I was experiencing failure in resetting the breakpoints using gdb 7.12.1. After upgrading to 8.0.1 the problem vanished. Supposedly, this was related to the bugfix https://sourceware.org/bugzilla/show_bug.cgi?id=21555. However, code positions where assertions fail still cannot be found correctly.

Does anybody have any idea about what is going on here?

This has started happening after a system update. The system update recompiled all system libraries, including the glibc, as position independent code, i.e., compiled with -fPIC.

Also, the version of the gcc I am using is 6.4.0


Solution

  • Here is a workaround. Since file re-reads the symbols correctly, while run does not, we can define a hook for the command run so to execute file before:

    define hook-run
      pi gdb.execute("file %s" % gdb.current_progspace().filename)
    end