问题
There is a shared library elf file, I use readelf -l
to see the program headers, the output is:
Elf file type is DYN (Shared object file)
Entry point 0x0
There are 11 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00000034 0x00000034 0x00100 0x00100 R 0x4
INTERP 0x000194 0x00000194 0x00000194 0x00013 0x00013 R 0x1
[Requesting program interpreter: /system/bin/linker]
LOAD 0x000000 0x00000000 0x00000000 0x3aa8c4 0x3aa8c4 R E 0x1000
LOAD 0x3ab1cc 0x003ac1cc 0x003ac1cc 0x062c0 0x25ee4 RW 0x1000
LOAD 0x3b2000 0x003d3000 0x003d3000 0x02561 0x02561 R E 0x1000
LOAD 0x3b4e8c 0x003d6e8c 0x003d6e8c 0x00298 0x00299 RW 0x1000
LOAD 0x3b5268 0x003d8268 0x003d8268 0x00128 0x00128 RW 0x1000
DYNAMIC 0x3b5268 0x003d8268 0x003d8268 0x00128 0x00128 RW 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0
EXIDX 0x2e71e8 0x002e71e8 0x002e71e8 0x0b558 0x0b558 R 0x4
GNU_RELRO 0x3ab1cc 0x003ac1cc 0x003ac1cc 0x01e34 0x01e34 RW 0x4
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .dynsym .dynstr .hash .gnu.version .gnu.version_d .rel.dyn .plt .text .ARM.extab .ARM.exidx .rodata
03 .data.rel.ro.local .fini_array .data.rel.ro .got .data .bss
04 .rel.plt
05 .init_array
06 .dynamic
07 .dynamic
08
09 .ARM.exidx
10 .data.rel.ro.local .fini_array .data.rel.ro .got
if the following struct represents an program header:
typedef struct {
uint32_t p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t p_flags;
uint32_t p_align;
} Elf32_Phdr;
Then my question is: How to understand the difference between p_offset
and p_vaddr
which corresponds to Offset
and VirtAddr
in output of readelf -l
? Will them always be the same? And will them be changed by the procedure of dynamic loading?
回答1:
Generally speaking-
p_offset
- offset within the elf file
p_vaddr
- address of section after loaded to memory (say, after c runtime initialization finished)
They will not always be the same, those addresses can be configured using linker script for example. Refer to this.
As for the shared library addresses after library loaded into a process address space - this depends on process addresses space, ASLR, and more, but its safe to say that the dynamic loader will set new addresses (p_vaddr
, aka execution address)
回答2:
How to understand the difference between p_offset and p_vaddr which corresponds to Offset and VirtAddr in output of readelf -l?
The runtime loader will mmap
a set of pages at offset .p_offset
(rounded down to pagesize) at virtual address .p_vaddr
(similarly rounded down; that address will actually have some large multiple-page offset added to it for ET_DYN
object).
Will them always be the same?
They aren't the same even in your example:
LOAD 0x3ab1cc 0x003ac1cc
0x3ab1
!= 0x3ac1
. What is guaranteed is that .p_offset % pagesize == .p_vaddr % pagesize
(otherwise mmap
will become impossible).
来源:https://stackoverflow.com/questions/52533193/how-to-understand-the-difference-between-offset-and-viraddr-in-program-headers-i