文件偏移量与共享库中的虚拟地址

时间:2017-10-11 08:34:54

标签: shared-libraries elf memory-mapping virtual-address-space

对于共享库文件,如何在文件偏移量和符号定义的虚拟地址之间进行转换?

在ELF文档中,对于符号表中的符号,

  

在可执行文件和共享对象文件中,st_value包含虚拟地址。为了使这些文件的符号对动态链接器更有用,段偏移(文件解释)让位于与第二个数字无关的虚拟地址(内存解释)。

但是如何在文件中获得相应的偏移?或者给出一个偏移量,我该如何计算虚拟地址(文件解释到内存解释)?

想象一下这样的场景。在执行进程期间,假设它正在使用在共享库中实现的函数,比如libx.so,并且库文件被映射到由vma表示的区域。

//addr holds the value of PC
offset = (vma->vm_pgoff << PAGE_SIZE) + addr -vma->vm_start;

据我了解,现在offset保存了库文件中指令的偏移量。鉴于此偏移,我想知道函数名称。一种方法是计算与offset对应的虚拟地址,并将虚拟地址与符号表中的st_value进行比较。如果st_value被处理为按升序存储,则st_value_1 < virtual_address < st_value_2表示st_name_1是我正在寻找的。所以问题在于转换 作为参考,符号表条目的数据结构是:

typedef struct{
  Elf32_Word     st_name; 
  Elf32_Addr     st_value;
  Elf32_Word     st_size;
  unsigned char  st_info;
  unsigned char  st_other;
  Elf32_Half     st_shndx;
}Elf32_Sym;

1 个答案:

答案 0 :(得分:0)

程序头表PT_LOAD条目定义了加载器/链接器如何映射虚拟地址空间中ELF文件的部分内容。如果要在文件偏移量和(相对)虚拟内存地址之间进行转换,则应使用此选项:

~$ readelf -l /lib/i386-linux-gnu/libc-2.24.so 

Elf file type is DYN (Shared object file)
Entry point 0x18400
There are 10 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x00000034 0x00000034 0x00140 0x00140 R E 0x4
  INTERP         0x166374 0x00166374 0x00166374 0x00013 0x00013 R   0x4
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x00000000 0x00000000 0x1b01c8 0x1b01c8 R E 0x1000
  LOAD           0x1b0260 0x001b1260 0x001b1260 0x02c74 0x0579c RW  0x1000
  DYNAMIC        0x1b1db0 0x001b2db0 0x001b2db0 0x000f0 0x000f0 RW  0x4
  NOTE           0x000174 0x00000174 0x00000174 0x00044 0x00044 R   0x4
  TLS            0x1b0260 0x001b1260 0x001b1260 0x00008 0x00048 R   0x4
  GNU_EH_FRAME   0x166388 0x00166388 0x00166388 0x061ec 0x061ec R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
  GNU_RELRO      0x1b0260 0x001b1260 0x001b1260 0x01da0 0x01da0 R   0x1

例如,考虑此符号

   Num:    Value  Size Type    Bind   Vis      Ndx Name
   188: 0005df80    35 FUNC    GLOBAL DEFAULT   13 fopen@@GLIBC_2.1

它的(相对)虚拟地址是0x0005df80。它属于第一个PT_LOAD条目,其范围在从0x000000000x00000000 + 0x1b01c8的相对虚拟内存中。它在该细分中的偏移量为Value - VirtAddr = 0x00000000。因此,它在文件中的偏移量为PhysAddr + (Value - VirtAddr) = 0005df80