With a binary executable and a /proc/pid/maps of a process which spawns from it, I want to map a runtime instruction address at this time (can be retrieved by gdb or any debuggers) towards the corresponding "static" instruction address (can be retrieved by objdump, ida or any disassemblers) in the binary executable.
For example, for PIE executables or shared libraries, this is easy:
xxxx-yyyy r-xp 0000000 ... path/to/mysharedlibrary.so
Then for runtime address zzzz
, its corresponding static address can be calculated by
static-address = zzzz - xxxx
The calculated address can be verified by looking at objdump or IDA.
However, for non-PIE or statically-linked executable, the above rule cannot be applied:
400000-yyyy r-xp 000000 ... path/to/executable
We do not need to additionally sub the base address from runtime address, the runtime address is the same as static address instead.
I wonder what is the exact rule for calculating the correct address, since the above two rules are completely by experience.
For example, for PIE executables or shared libraries, this is easy:
It is also incorrect. Or rather, it's only correct when the binary is linked at address 0
(which is usually the case for ET_DYNAMIC
(shared libraries and PIE
binaries), but is not the case when the shared library is prelinked. See man prelink).
I wonder what is the exact rule for calculating the correct address
You need 2 numbers: in-memory address (from /proc/$pid/maps
) and the linked-at address (from readelf -Wl
-- the first PT_LOAD
segment .p_vaddr
).
Subtracting the second from the first gives you relocation (difference between what you see in nm
/ objdump
etc. and actual in-memory address).