If an object file participates in dynamic linking, its program header table will have an element of type PT_DYNAMIC.
This segment contains the .dynamic section. A special symbol, _DYNAMIC, labels the section,
which contains an array of the following structure. The d_tag member controls the interpretation of d_un.
Example of dynamic section:
DT_DEBUG
Name
Value
d_un
Description
DT_DEBUG
21
d_ptr
Reserved for debugging use.
The run-time linker exposes a rendezvous structure to allow debuggers
to interface with it. This structure, r_debug, is defined in link.h.
If the executable’s dynamic section has a DT_DEBUG element, the
run-time linker sets that element’s value to the address where this
structure can be found.
So once in memory, the run-time linker sets the DT_DEBUG pointer (d_ptr) to the r_debug struct.
r_debug
link_map
The first item in the array points to the application itself, and then you can iterate over the loaded modules.
The last one in the list will be NULL.
Example
Now that we have the handle, we can start getting headers, sections and symbols.
Although I could get the section header, iterate over it, and see it in memory, it would error with segmentation fault
when I tried to read from it.
Iterate over program header until PT_DYNAMIC is found. p_vddr will point to the dynamic section.
Again iterate over the dynamic section. DT_STRTAB points to the address of the dynamic string table.
DT_SYMTAB points to address of the dynamic symbol table.
.dynsym
Because of the problem with reading the section headers, we need to find another way to find the size
of the .dynsym. From the default linker script (via -Wl,--verbose):
.dynstr comes after .dynsym. So to get the size of the section