Stepping over runtime loader dynamic symbol resolution code
If the program uses ELF-style shared libraries, then calls to functions in shared libraries go through stubs, which live in a table called the PLT (Procedure Linkage Table). The first time the function is called, the stub sends control to the dynamic linker, which looks up the function’s real address, patches the stub so that future calls will go directly to the function, and then passes control to the function.
If we are stepping at the source level, we don’t want to see any of this — we just want to skip over the stub and the dynamic linker. The simple approach is to single-step until control leaves the dynamic linker.
However, on some systems (e.g., Red Hat’s 5.2 distribution) the dynamic linker calls functions in the shared C library, so you can’t tell from the PC alone whether the dynamic linker is still running. In this case, we use a step-resume breakpoint to get us past the dynamic linker, as if we were using next to step over a function call.
The in_solib_dynsym_resolve_code function says whether we’re in the dynamic linker code or not. Normally, this means we single-step. However, if gdbarch_skip_solib_resolver then returns non-zero, then its value is an address where we can place a step-resume breakpoint to get past the linker’s symbol resolution function.
The in_dynsym_resolve_code hook of the target_so_ops vector can generally be implemented in a pretty portable way, by comparing the PC against the address ranges of the dynamic linker’s sections.
The gdbarch_skip_solib_resolver implementation is generally going to be system-specific, since it depends on internal details of the dynamic linker. It’s usually not too hard to figure out where to put a breakpoint, but it certainly isn’t portable. gdbarch_skip_solib_resolver should do plenty of sanity checking. If it can’t figure things out, returning zero and getting the (possibly confusing) stepping behavior is better than signaling an error, which will obscure the change in the inferior’s state. */