如何了解elf程序头中的Offset和VirAddr之间的区别? [英] How to understand the difference between Offset and VirAddr in Program Headers in elf?

查看:485
本文介绍了如何了解elf程序头中的Offset和VirAddr之间的区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个共享的库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;

然后我的问题是:如何理解readelf -l的输出中OffsetVirtAddr对应的p_offsetp_vaddr之间的区别?他们会永远一样吗?并会通过动态加载程序来更改它们吗?

解决方案

一般来说-

p_offset-elf文件中的偏移量

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

它们并不总是相同的,例如,可以使用链接描述文件配置这些地址. 参见. >

对于将库加载到进程地址空间后的共享库地址-这取决于进程地址空间,ASLR等,但是可以肯定地说动态加载程序将设置新地址(p_vaddr,也称为执行地址)

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?

解决方案

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)

这篇关于如何了解elf程序头中的Offset和VirAddr之间的区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆