sdaau
sdaau

Reputation: 38619

Debugging Release (without symbols) in gdb, but with source build folder (.o files)?

There is an application I've built from source, which works for the most part fine, but for a certain problem I've encountered recently, it warrants a trip down the debugger.

However, the problem is that the build takes an hour or more, and I've already built this application in release, meaning gdb says "(no debugging symbols found)...done.".

I can still set function breakpoints in gdb with the executable as is, except I cannot step through code ("Single stepping until exit from function ... , which has no line number information. ; Cannot find bounds of current function").

So, given that I have the sources and a source build folder full of .o files, - in the interest of not having to waste potentially several hours on building a debug version - I was wondering if it is possible to somehow instruct gdb to use these files/directories, to then let me step through the code?

Upvotes: 1

Views: 1120

Answers (1)

Employed Russian
Employed Russian

Reputation: 213375

I was wondering if it is possible to somehow instruct gdb to use these files/directories, to then let me step through the code?

Yes.

First, you need to prepare a matching copy of the functions you want to step through, but with debug info.

Suppose you have foo() and bar() in foo.o and bar.o respectively. You need to rebuild them with all original flags, and -g added:

rm -f foo.o bar.o
make foo.o bar.o CFLAGS="$ORIGINAL_FLAGS -g"

Next you need to figure out where foo() and bar() are located:

nm -A foo.o bar.o | egrep ' (foo|bar)$'

Finally you need to use GDB add-symbol-file foo.o $ADDR_foo_o and add-symbol-file bar.o $ADDR_bar_o to enjoy your source debugging.

Computing $ADDR_foo_o is somewhat tricky: you need

  • the address of foo inside foo.o (a1) (output from nm above),
  • the address of .text in foo.o (a2, use readelf -WS foo.o | grep '\.text$'),
  • the address of foo in the main binary (a3, use nm a.out | grep ' foo$').

I believe you need $ADDR_foo_o = $a3 - $a1 + $a2.

For a position-independent executable, you'll also need to add a.out relocation (a4), which you can find from info file or info proc mappings.

P.S. In order to avoid this pain, you should always build your release binaries with -g flag (which is orthogonal to optimization flags), and use strip -g a.out -o a.out-for-deployment. Then keep a.out for debugging, and deploy the stripped version to production / customers.

Upvotes: 3

Related Questions