I'm trying to locate where the libc program segments are in a program's memory, by reading the program headers.
On Centos 6, when I use readelf on the libc.so.6 file, the VirtAddr contains the correct address where the program segment is loaded in the process's memory:
[user@centos6 src]$ readelf -l /lib64/libc.so.6 --wide
Elf file type is DYN (Shared object file)
Entry point 0x3032c1ee30
There are 10 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000003032c00040 0x0000003032c00040 0x000230 0x000230 R E 0x8
INTERP 0x15aab0 0x0000003032d5aab0 0x0000003032d5aab0 0x00001c 0x00001c R 0x10
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x000000 0x0000003032c00000 0x0000003032c00000 0x18a00c 0x18a00c R E 0x200000
LOAD 0x18a700 0x0000003032f8a700 0x0000003032f8a700 0x004f58 0x009228 RW 0x200000
DYNAMIC 0x18db40 0x0000003032f8db40 0x0000003032f8db40 0x0001f0 0x0001f0 RW 0x8
NOTE 0x000270 0x0000003032c00270 0x0000003032c00270 0x000044 0x000044 R 0x4
TLS 0x18a700 0x0000003032f8a700 0x0000003032f8a700 0x000010 0x000068 R 0x8
GNU_EH_FRAME 0x15aacc 0x0000003032d5aacc 0x0000003032d5aacc 0x0065ec 0x0065ec R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x8
GNU_RELRO 0x18a700 0x0000003032f8a700 0x0000003032f8a700 0x003900 0x003900 R 0x1
So in this case, the DYNAMIC segment is located at 0x0000003032f8db40
But on Centos 7, the VirtAddr contains an offset instead, and I have to add the libc base address to this offset to find where the segment is in memory:
[user@centos7 src]$ readelf -l /usr/lib64/libc.so.6 --wide
Elf file type is DYN (Shared object file)
Entry point 0x22660
There are 10 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x000230 0x000230 R E 0x8
INTERP 0x18eb00 0x000000000018eb00 0x000000000018eb00 0x00001c 0x00001c R 0x10
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x1c3170 0x1c3170 R E 0x200000
LOAD 0x1c36f0 0x00000000003c36f0 0x00000000003c36f0 0x0051b0 0x009b10 RW 0x200000
DYNAMIC 0x1c6b60 0x00000000003c6b60 0x00000000003c6b60 0x0001f0 0x0001f0 RW 0x8
NOTE 0x000270 0x0000000000000270 0x0000000000000270 0x000044 0x000044 R 0x4
TLS 0x1c36f0 0x00000000003c36f0 0x00000000003c36f0 0x000010 0x0000a0 R 0x10
GNU_EH_FRAME 0x18eb1c 0x000000000018eb1c 0x000000000018eb1c 0x006aec 0x006aec R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x1c36f0 0x00000000003c36f0 0x00000000003c36f0 0x003910 0x003910 R 0x1
In this case, the DYNAMIC segment would be located at 0x00000000003c6b60 + libc base address.
I'm guessing this is probably due to ASLR on Centos 7, which causes the libc library to be loaded at a different address each time. On Centos 6, it seems like the libc is always loaded at the same address.
Is there a way to determine, just from reading the ELF header, whether I need to add the libc base address to the VirtAddr to get the actual location of the program segment in memory?