I believe there are a lot of comrades debugging a program that contains shared library code, this time the most headaches is not to do a single step tracking (of course, you do not know how to solve the case ^_^), this article based on an example to tell how to solve this problem. First look at our program, which contains two files: Dyn.c, MAIN.C, where Dyn.c is compiled into a shared library libdyn.so, which is used when linking. One thing you must declare is that your shared library code must be with debugging information (for example, using the-G option). $cat DYN.C Dyn () { Puts ("Hello."); } $cat MAIN.C Main () { Puts ("before"); Dyn (); Puts ("after"); } $cat Makefile Main Gcc-g-save-temps-c Main.c-o MAIN.O Gcc-g-save-temps-c-fpic-ffunction-sections dyn.c Gcc-g-save-temps-shared Dyn.o-o libdyn.so GCC-G-save-temps MAIN.O Libdyn.so-o Main
Clean RM-RF *.O *.so Main Here we will compile and debug the program: $make main This will then generate our libdyn.so and main program in the current directory. If we enter $./main directly as usual to execute the program, this is not going to work, it will give us the wrong hint: Before ./main:relocation error:./main:undefined Symbol:dyn Why. It turns out we used shared libraries libdyn.so didn't tell the dynamic link program where to find him. Well, this time we'll tell it: $LD _library_path= ' pwd './main Before Hello. After How about the results we want? These are some pediatrics, cattle people do not joke ah, the following is to be said. Normally when we use GDB for debugging: $ gdb-q Main (GDB) B main Breakpoint 1 at 0x8048478:file main.c, line 3. (GDB) R Starting program:/home/lirui/test/main
Breakpoint 1, Main () at Main.c:3 3 puts ("before"); (GDB) Next Before 4 dyn (); (GDB) /home/lirui/test/main:relocation Error:/home/lirui/test/main:undefined Symbol:dyn
Program exited with code 0177. (GDB) According to our intention, we want to trace to the dyn () function inside to see some of the drum, but it can not find the corresponding symbolic information, how to do. Method One: Set the GDB environment variable ld_preload, before executing the program, the shared library code load comes in, can you find it? $GDB-Q Main (GDB) Set environment ld_preload./libdyn.so (GDB) Break dyn Breakpoint 1 at 0x80483a8 (GDB) Run Starting program:/home/lirui/test/main Breakpoint 1 at 0x400176ff:file dyn.c, line 3. Before
Breakpoint 1, dyn () at Dyn.c:3 3 puts ("Hello."); (GDB) List 1 dyn () 2 { 3 puts ("Hello."); 4} (GDB) This does not find the Dyn () function, so you can be very comfortable debugging it. Method Two: If you use the GDB version of the "Pending breakpoint" support (V6.3 support), then congratulations, you can set a pending breakpoint, and then have gdb to determine when the breakpoint will work. Here's one thing to note that you have to specify the location of your link library, which can be implemented by setting the environment variable Ld_library_path. Before executing GDB, we can do this: $ export ld_libary_path= ' pwd ', tell GDB to look for shared library files in the current directory, and then debug the program as usual: $ export ld_library_path= ' pwd ' $ gdb-q Main The Using host libthread_db the Library "/lib/libthread_db.so.1". (GDB) b dyn Function "dyn" not defined. Make breakpoint pending on future shared library load? (Y or [n]) y Breakpoint 1 (dyn) pending. (GDB) R Starting program:/home/lirui/test/tmp/main Reading symbols from shared object, read from Target Memory...done. Loaded system supplied DSO at 0xffffe000 Breakpoint 2 at 0xb7f4853a:file dyn.c, line 3. Pending breakpoint "dyn" resolved Before
Breakpoint 2, Dyn () at Dyn.c:3 3 puts ("Hello."); (GDB) L 1 dyn () 2 { 3 puts ("Hello."); 4} (GDB)Is that okay, ^_^? Method Three: This situation is only for the program you want to debug the whole is a dynamic link executable program, it in the load to memory, the entry address is dynamic change, if you use GDB for debugging, the initial time you use B function_name words, It sets the breakpoint on offset with 0x0 as the base address, and after the program is load to memory, the base address has changed, so it is always impossible to set a success breakpoint. (I ran into this when I was debugging Qemu). The simplest way is not to compile the program into a reusable, like a normal program to compile it, do not add-wl,-shared for GCC, such as parameters, this time the compilation is very easy to debug. In response to this situation, I think there should be a way, but I did not test success, is in the use of GDB, the original symbol table load, if the load came in, the use of the Symbol-file command (followed without parameters) to have loaded the symbol table discarded, Then use the add_symbol_file filename start_address command to load the symbol table from filename to the address starting with start_address, and you can debug it. I've experimented with programs that do not apply to shared libraries in this way, because we know that the starting address for a generic program is 0x8048000, but for shared objects, we don't know what the start address is, so it's hard to do, If there's a way to tell us the starting address of its. Text, it's easy to do it this way.
There should be other ways, if you know, please tell me colin719@126.com, thank you. Another type of makefile is: . Phony:all Clean All:main
Main Gcc-g-C Main.c-o MAIN.O Gcc-g-c-fpic-ffunction-sections DYN.C Gcc-g-shared Dyn.o-o libdyn.so Gcc-g-wl,-rpath./MAIN.O./libdyn.so-o Main
Clean RM-RF *.O *.so Main |