代码之家  ›  专栏  ›  技术社区  ›  cong

如何理解elf中程序头中Offset和VirAddr之间的区别?

  •  1
  • cong  · 技术社区  · 6 年前

    有一个共享库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_offset p_vaddr 对应于 Offset VirtAddr 输出 ? 它们会一直是一样的吗?动载程序会改变它们吗?

    2 回复  |  直到 6 年前
        1
  •  3
  •   Community Neeleshkumar S    4 年前

    一般来说-

    p_offset -elf文件中的偏移量

    p_vaddr -加载到内存后节的地址(例如,c运行时初始化完成后)

    它们并不总是相同的,例如,可以使用链接器脚本来配置这些地址。 Refer to this

    至于库加载到进程地址空间后的共享库地址,这取决于进程地址空间、ASLR等,但可以肯定的是,动态加载程序将设置新的地址( p\u瓦德 ,又名执行地址)

        2
  •  2
  •   Employed Russian    6 年前

    如何理解在readelf-l的输出中对应于offset和VirtAddr的p\u offset和p\u vaddr之间的区别?

    运行时加载程序将 mmap 偏移的一组页 .p_offset .p_vaddr (类似地四舍五入;该地址实际上会添加一些大的多页偏移量 ET_DYN 对象)。

    他们 不是

    LOAD           0x3ab1cc 0x003ac1cc
    

    0x3ab1 != 0x3ac1 . 什么 这是保证吗 .p_offset % pagesize == .p_vaddr % pagesize (否则 mmap公司 将变得不可能)。