Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to step into a function in a shared library with GDB

I am trying to debug an application that is built from a number of shared libraries using GDB.

Start of gdb:

prompt$ gdb
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-50.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.

Tell GDB the program to debug:

(gdb) file /home/me/build-path/my-program
Reading symbols from /home/me/build-path/my-program...done.

Set a breakpoint within the application:

(gdb) my-program-src.cpp:57
breakpoint 1 at 0x819df9b: file src/my-program-src.cpp, line 57

Run the program:

(gdb) run 
 Starting program: /home/me/build-path/my-program

The program stops at the breakpoint, as expected:

 Breakpoint 1 MyClass:func(this-0xffffc1c0) at src/my-program-src.cpp:235

Line 235 of my-program-src.cpp is a constructor call for class Derived which is in MySharedLib1.so.

'class Derived' is derived from 'class Base' which is in MySharedLib2.so

If I now step, the program exits inside `MySharedLib2.so' with a SIG SEGV (which is what I am trying to debug), i.e:

Program received signal SIGSEGV, Segmentation fault.
0x0024c2fa in osal::MsgQMsg::id(unsigned int) () from /home/me/build-path/lib/libMySharedLib2.so

GDB is not stepping into either of the shared libraries.

bt gives the name of the function where the problem occurred, but list shows code in my-program-src.cpp

All code is compiled with the following options:

gcc -MD -D__LINUX__  -g -Wall -Wextra -Iinc -m32 -fpic -I../../public_inc /home/me/src/file.c -o /home/me/build-path/obj/file.o

The shared libraries are linked with the following options:

gcc -o /home/me/build-path/lib/libMySharedLib1.so -shared /home/me/build-path/obj/file.o -L/home/me/build-path/lib/ -m32

If I change the Makefiles so that archives libraries are build (i.e. .a) I can step into functions as expected.

Further information:

If I manually try to add the symbols from the shared library I get the following:

(gdb) add-symbol-file  /home/me/build-path/lib/libMySharedLib2.so
The address where /home/me/build-path/lib/libMySharedLib2.so has been loaded is missing

(Note: i get the same response from add-symbol-file once the breakpoint has been hit)

If I can set a breakpoint in a function within the shared library, GDB breaks as expected but if I type list GDB shows the calling line in the main application code (i.e. the calling function that is not in a shared library). GDB does not complain about source files not being found.

Why can't I step into my shared libraries?

Why can't I step through code in shared libraries?

like image 406
mark Avatar asked Dec 18 '12 10:12

mark


2 Answers

If the shared library has no debug symbols/info, gdb will by default step over it rather than into it. You can use stepi (abbrev si) to instead step by single instructions. I find the following commands in by .gdbinit file useful:

define sx
  si
  x /1i $pc
end
document sx
    Step one instruction and print next instruction
end
define nx
  ni
  x /1i $pc
end
document nx
    Step one instruction running through calls and print next instruction
end

which defines the commands sx/nx to step by single instructions, and then disassemble the next instruction to be run. Quite useful when trying to debug through machine code with no debug info.

like image 128
Chris Dodd Avatar answered Oct 11 '22 10:10

Chris Dodd


It may be a typo, but you used libMySharedLib2.so with a 2 not a 1 when you tried to load the symbols.

In any case, you should use g++ to compile and link c++ code. Furthermore, the main program doesn't have to be pic, although it probably doesn't hurt.

It works for me as follows:

$ cat >lib.h
class Base
{
        int _x;
    public:
        Base(int);
};

class Derived : public Base
{
    public:
        Derived(int x);
};
$ cat >lib.cpp
#include "lib.h"

Base::Base(int x)
{
    _x = *reinterpret_cast<int*>(x);
}

Derived::Derived(int x) : Base(x)
{
}
$ cat >main.cpp
#include "lib.h"

int main(int, char**)
{
    Derived d(0);
    return 0;
}
$ g++ -shared -fpic -m32 -g -Wall -o libMySharedLib1.so lib.cpp
$ g++ -m32 -g -Wall -L. -l MySharedLib1 main.cpp
$ LD_LIBRARY_PATH=$PWD gdb ./a.out
GNU gdb (GDB) 7.3.50.20111117-cvs-debian
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from a.out...done.
(gdb) r
Starting program: a.out     

Program received signal SIGSEGV, Segmentation fault.
0xf7fdb552 in Base::Base (this=0xffffd83c, x=0) at lib.cpp:5
5           _x = *reinterpret_cast<int*>(x);
(gdb) bt
#0  0xf7fdb552 in Base::Base (this=0xffffd83c, x=0) at lib.cpp:5
#1  0xf7fdb5ba in Derived::Derived (this=0xffffd83c, x=0) at lib.cpp:8
#2  0x08048591 in main () at main.cpp:5
(gdb) br main
Breakpoint 1 at 0x804857d: file main.cpp, line 5.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: a.out     

Breakpoint 1, main () at main.cpp:5
5           Derived d(0);
(gdb) s
Derived::Derived (this=0xffffd83c, x=0) at lib.cpp:8
8       Derived::Derived(int x) : Base(x)
(gdb) s
Base::Base (this=0xffffd83c, x=0) at lib.cpp:5
5           _x = *reinterpret_cast<int*>(x);

(gdb output slightly edited)

like image 20
Jester Avatar answered Oct 11 '22 09:10

Jester