elf - 如何理解elf中Program Headers中Offset和VirAddr的区别?

标签 elf dynamic-linking dynamic-loading readelf

有共享库elf文件,我用readelf -l查看程序头,输出为:

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 

如果以下结构表示程序头:

   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;

那么我的问题是:如何理解p_offsetp_vaddr的区别,分别对应OffsetVirtAddrreadelf -l 的输出中?他们会永远一样吗?动态加载的过程会改变它们吗?

最佳答案

How to understand the difference between p_offset and p_vaddr which corresponds to Offset and VirtAddr in output of readelf -l?

运行时加载器将在虚拟地址 .p_vaddrmmap 偏移量为 .p_offset 的一组页面(向下舍入为页面大小)(类似地四舍五入;该地址实际上会为 ET_DYN 对象添加一些大的多页偏移量)。

Will them always be the same?

即使在您的示例中,它们也不相同:

LOAD           0x3ab1cc 0x003ac1cc

0x3ab1 != 0x3ac1 保证的是 .p_offset % pagesize == .p_vaddr % pagesize(否则 mmap 将变得不可能)。

关于elf - 如何理解elf中Program Headers中Offset和VirAddr的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52533193/

相关文章:

linker - 解释 readelf -S 输出

x86-64 - 是否可以用编译后的二进制文件中的虚拟对象替换特定函数的每个实例?

C++ 动态库 - 在 OS X 上运行时链接符号

linux - 在 .so 文件中更新动态链接的 .so 文件和在 .so 文件中更新静态链接的 .a 文件

linux - 进程如何在 Linux 中找到动态共享库?

javascript - 将远程 XML 加载到网页中并通过 JavaScript 访问其内容

c - 直接从 C 中的(共享)内存执行二进制/elf 文件

找不到符号表(Elf格式)(C编程)

c++ - 如何链接 DLL 以供 LoadLibrary() 使用(在 Windows 上的 C++ 中)并从调用 exe 导入变量

c++ - 如果从 dlopen 的库中调用 dlopen() 是否存在负载泄漏?