简体   繁体   中英

Stepping out after stopping on catchpoint in GDB

In order to debug my program, I need to see what is happening exactly after a shared library was loaded. I use GDB's catch load command to stop on shared library events.

My understanding of shared libraries tells the following: initially the PLT entry points to some code that loads the lib. When it is called, the library gets loaded and the PLT entry starts pointing to the actual loaded library code so that the next time the lib is called we just jump to its code without reloading. Taking that into account I expect the catchpoint to be inside some system function that was called from PLT, and I expect my code to be somewhere higher on the stack.

However, the stack at the catchpoint looks like this:

(gdb) bt #0 0x00007ffff7df0632 in ?? () from /lib64/ld-linux-x86-64.so.2 #1 0x00007ffff7dd8c2a in ?? () from /lib64/ld-linux-x86-64.so.2 #2 0x00007ffff7dd7c38 in ?? () from /lib64/ld-linux-x86-64.so.2 #3 0x000000000000000a in ?? () #4 0x00007fffffffde1e in ?? () // several frames without location info

At this point, I want to continue executing my code from the point where it started loading shared libs. However, I cannot see my code in the stack. Moreover, I don't understand the meaning of frame #3 . I cannot step out further than that frame because GDB is unable to find a valid return address on the stack (which is obvious because 0xa is definitely not a valid return address).

What is 0xa and why is it on the stack? Is there a way to stop GDB in my code exactly after the shared library was loaded?

My understanding of shared libraries tells the following: initially the PLT entry points to some code that loads the lib. When it is called, the library gets loaded and the PLT entry starts pointing to the actual loaded library code so that the next time the lib is called we just jump to its code without reloading.

This understanding is incorrect.

There are two cases to consider, and neither of them involves loading the library when a function from it is called.

Case #1: your binary is linked against shared library directly, like so:

gcc main.c -lc  # links against libc.so.6

You can see the set of libraries that your binary is directly linked against with readelf -d a.out | grep NEEDED readelf -d a.out | grep NEEDED .

In this case, all the libraries are loaded by the dynamic loader before the executable starts running.

Case #2: you dynamically add a new library via dlopen .

In that case, the library is loaded from within dlopen implementation.

What you are likely confused about is lazy PLT resolution (which has nothing to do with library loading). You can read about it here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM