-1

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

Mirco
  • 99
  • 7
  • 1
    You debug a different file, how can you use the breakpoints which were defined for the old file? – user202729 Feb 02 '18 at 14:41
  • 1
    Use an IDE. They are smart enough to attach a breakpoint to a line and tell the debugger about it when it starts. They are also smart enough to know that the breakpoint location changes when you add a line before it. Very useful. – nwp Feb 02 '18 at 14:45
  • I don't know how that is implemented inside gdb. I think it would be desirable to be able to re-run you code, and reuse your breakpoints, after recompiling. I can expect that maybe line breakpoint go out of place, but not to be in need to restart gdb every time – Mirco Feb 02 '18 at 14:46
  • `file a.out` doesn't restart gdb. It loads the correct binary. And arguably letting all your breakpoints have the wrong location because you added or removed a line doesn't sound useful. – nwp Feb 02 '18 at 14:47
  • I agree. In fact I expect breakpoints on functions to be found. But here the problem is that gdb cannot find any position (e.g. where an assertion fails), regardless of the breakpoints. – Mirco Feb 02 '18 at 16:32

2 Answers2

0

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
Mirco
  • 99
  • 7
-1

after you change the source file and recompile u are generating a different file from the one loaded to GDB.

you need to stop the running debug cession and reload the file.

you cant save the previously defined breakpoints and watch points in the file to a changed source, since gdb is actually inserting additional code to your source to support breakpoints and registrar handlers.

if you change the source the the behavior is undefined and you need to reset those breakpoints.

you can refer to gdb manual regarding saving breakpoints in a file as Mark Plotnick suggested, but it wont work if you change the file(from my experience) https://sourceware.org/gdb/onlinedocs/gdb/Save-Breakpoints.html

  • Indeed, I am reloading the symbols. After recompiling, I issue a "run" command again, getting back the message `/home/myself/a.out' has changed; re-reading symbols. But gdb fails finding the right position where the assertion failed. – Mirco Feb 02 '18 at 16:27
  • there no way i know of to "save" the break points. you need to reset them when u reload a file. i assume it's because the virtual address of the expression you are trying to examine changed(after changing the file) and the previously set break point doesn't relate to it – Itay Sadovnik Feb 02 '18 at 20:19
  • 1
    [Getting gdb to save a list of breakpoints](https://stackoverflow.com/questions/501486/getting-gdb-to-save-a-list-of-breakpoints) – Mark Plotnick Feb 02 '18 at 22:12
  • It would be nice if there were a way of specifying gdb line-number breakpoints with some snippet of the source code at and around that line, like a ctags that indexed every line of the source. Then your breakpoint list could survive minor code edits. Maybe that's something an IDE could do. – Mark Plotnick Feb 04 '18 at 06:19
  • Indeed, it would. Nevertheless the problem I was experiencing was more subtle than this. It had to do with a failure resetting the breakpoints after the run command. It was a bug with PIE executables, which was fixed in version 8.0.1. I updated the post accordingly – Mirco Feb 04 '18 at 17:10