ldd
The program ldd
is wrong for a few reasons.
First, ldd
is not meant to be accurate for determining load addresses. Use the environment variable LD_TRACE_LOADED_OBJECTS
.
Second, ldd
will never be correct with ASLR enabled as Guntram showed. You can disable this pretty trivially if you have sudo
access.
$ LD_TRACE_LOADED_OBJECTS=1 /bin/bash | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f44dae1b000)
$ LD_TRACE_LOADED_OBJECTS=1 /bin/bash | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9b35341000)
$ LD_TRACE_LOADED_OBJECTS=1 /bin/bash | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fef18efd000)
$ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
0
$ LD_TRACE_LOADED_OBJECTS=1 /bin/bash | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff75e7000)
$ LD_TRACE_LOADED_OBJECTS=1 /bin/bash | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff75e7000)
$ LD_TRACE_LOADED_OBJECTS=1 /bin/bash | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff75e7000)
You can verify this by starting an instance of bash in the background and inspecting its maps file.
$ bash &
[1] 30398
[1] + 30398 suspended (tty input) bash
$ grep libc /proc/30398/maps | head -n1
7ffff75e7000-7ffff77a2000 r-xp 00000000 08:01 525269 /lib/x86_64-linux-gnu/libc-2.19.so
info sharedlibrary
The address reported by info sharedlibrary
is the address of the .text
area.
Note that in the particular libc that I have, the .text is at 0x1f4a0
.
$ readelf --wide --section-headers /lib/x86_64-linux-gnu/libc-2.19.so | grep text
[12] .text PROGBITS 000000000001f4a0 01f4a0 145c23 00 AX 0 0 16
In GDB, if we look at the load addresses of libc
, we see that it is loaded at 0x7ffff7a14000
. This will change each time the program is run, if ASLR is enabled on the system. If you run it under GDB, it will also disable ASLR. Run the command set disable-randomization off
before running the target and you will observe it change each run.
gdb-peda$ info proc mapping
...
0x7ffff7a14000 0x7ffff7bcf000 0x1bb000 0x0 /lib/x86_64-linux-gnu/libc-2.19.so
0x7ffff7bcf000 0x7ffff7dcf000 0x200000 0x1bb000 /lib/x86_64-linux-gnu/libc-2.19.so
0x7ffff7dcf000 0x7ffff7dd3000 0x4000 0x1bb000 /lib/x86_64-linux-gnu/libc-2.19.so
0x7ffff7dd3000 0x7ffff7dd5000 0x2000 0x1bf000 /lib/x86_64-linux-gnu/libc-2.19.so
...
You can verify this by checking to see if it starts with the ELF header.
gdb-peda$ hexdump 0x00007ffff7a14000 4
0x0000 0x00007ffff7a14000 │ 7f 45 4c 46 │ .ELF
0x0004 0x00007ffff7a14004
If we add the 0x1f4a0
offset from the .text
area, we get 0x7ffff7a334a0
.
gdb-peda$ printf "%p\n",(0x00007ffff7a14000+0x1f4a0)
0x7ffff7a334a0
Now if we look at info sharedlibrary
, we see exactly this address.
gdb-peda$ info sharedlibrary libc
From To Syms Read Shared Object Library
0x00007ffff7a334a0 0x00007ffff7b790c3 Yes /lib/x86_64-linux-gnu/libc.so.6
Extra Tips
In GDB, you should use the info proc mapping
command to get the base address of a loaded module.
However, this is not available on FreeBSD, since GDB does not support the FreeBSD-specific APIs necessary to get module base addresses. Instead, you must use the info proc mapping
command and perform the translation yourself (by subtracting the address of the .text
section).