linuxprocesselfdisassembly

How to map runtime address from /proc/pid/maps to binary executable?


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.


Solution

  • 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).