指向文件偏移量的地址


0

我已经从ELF符号表中读取了st_value,值为4195622.转换为十六进制时,值为400580.我知道文件偏移量为580字节。

我的问题是如何实际将地址转换为具体的文件偏移量。

由于

0

减去0x400000st_value由于地址位于所述第一LOAD段的二进制的。


根据System V的ABI(通用),将st_value符号的含义取决于什么类型的对象文件的二进制文件:

针对不同目标文件类型的符号表项略有st_value成员的不同解释 。

  • 在可重定位的文件,st_value保持对准约束其截面索引是SHN_COMMON的符号。
  • 在可重新定位的文件中,st_value为定义的符号保存段偏移量。也就是说,st_valuest_shndx标识的部分开头的偏移量。
  • 在可执行文件和共享目标文件中,st_value保存虚拟地址。为了使这些文件的符号对动态链接器更有用,段偏移量(文件解释)让位给段编号无关的虚拟地址(内存解释)。通过ld
  • 连接

可执行ELF64目标文件具有通过链接脚本变量__executable_start给定的0x0000000000400000规范基地址。这意味着可以从st_value中减去基地址的值来找到它的文件偏移量。

我们可以通过查看ELF64二进制文件的链接图来验证这一点。这里的ld -M /bin/ls输出的一个片段:

Memory Configuration 

Name  Origin  Length  Attributes 
*default* 0x0000000000000000 0xffffffffffffffff 

Linker script and memory map 

LOAD /bin/ls 
    0x0000000000400000  PROVIDE (__executable_start, 0x400000) <-------------- 
    0x0000000000400190  . = (0x400000 + SIZEOF_HEADERS) 

.interp  0x0000000000400190 0x1c 
*(.interp) 
.interp 0x0000000000400190 0x1c /bin/ls 

.note.ABI-tag 0x00000000004001ac 0x20 
.note.ABI-tag 0x00000000004001ac 0x20 /bin/ls 

.note.gnu.build-id 
    0x00000000004001cc 0x24 
*(.note.gnu.build-id) 
.note.gnu.build-id 
    0x00000000004001cc 0x24 /bin/ls 

这可以进一步通过检查相同的二进制的部分以分段映射经由readelf -l /bin/ls验证:

Elf file type is EXEC (Executable file) 
Entry point 0x404890 
There are 9 program headers, starting at offset 64 

Program Headers: 
  Type  Offset  VirtAddr  PhysAddr 
    FileSiz  MemSiz  Flags Align 
  PHDR  0x0000000000000040 0x0000000000400040 0x0000000000400040 
    0x00000000000001f8 0x00000000000001f8 R E 8 
  INTERP  0x0000000000000238 0x0000000000400238 0x0000000000400238 
    0x000000000000001c 0x000000000000001c R 1 
   [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] 
  LOAD  0x0000000000000000 0x0000000000400000 0x0000000000400000 <------------- 
    0x0000000000019d44 0x0000000000019d44 R E 200000 
  LOAD  0x0000000000019df0 0x0000000000619df0 0x0000000000619df0 
    0x0000000000000804 0x0000000000001570 RW 200000 
  DYNAMIC 0x0000000000019e08 0x0000000000619e08 0x0000000000619e08 
    0x00000000000001f0 0x00000000000001f0 RW 8 
  NOTE  0x0000000000000254 0x0000000000400254 0x0000000000400254 
    0x0000000000000044 0x0000000000000044 R 4 
  GNU_EH_FRAME 0x000000000001701c 0x000000000041701c 0x000000000041701c 
    0x000000000000072c 0x000000000000072c R 4 
  GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 
    0x0000000000000000 0x0000000000000000 RW 10 
  GNU_RELRO 0x0000000000019df0 0x0000000000619df0 0x0000000000619df0 
    0x0000000000000210 0x0000000000000210 R 1 

Section to Segment mapping: 
  Segment Sections... 
  00 
  01 .interp 
  02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 
  03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 
  04 .dynamic 
  05 .note.ABI-tag .note.gnu.build-id 
  06 .eh_frame_hdr 
  07 
  08 .init_array .fini_array .jcr .dynamic .got 

第一LOAD段具有基地址为0x0000000000400000

比较值在Off柱与那些在Address列:

$ readelf -SW /bin/ls 
There are 28 section headers, starting at offset 0x1a700: 

Section Headers: 
  [Nr] Name  Type  Address  Off Size ES Flg Lk Inf Al 
  [ 0]   NULL  0000000000000000 000000 000000 00 0 0 0 
  [ 1] .interp  PROGBITS 0000000000400238 000238 00001c 00 A 0 0 1 
  [ 2] .note.ABI-tag NOTE  0000000000400254 000254 000020 00 A 0 0 4 
  [ 3] .note.gnu.build-id NOTE  0000000000400274 000274 000024 00 A 0 0 4 
  [ 4] .gnu.hash  GNU_HASH 0000000000400298 000298 000068 00 A 5 0 8 
  [ 5] .dynsym  DYNSYM  0000000000400300 000300 000c18 18 A 6 1 8 
  [ 6] .dynstr  STRTAB  0000000000400f18 000f18 000593 00 A 0 0 1 
  [ 7] .gnu.version VERSYM  00000000004014ac 0014ac 000102 02 A 5 0 2 
  [ 8] .gnu.version_r VERNEED  00000000004015b0 0015b0 000090 00 A 6 2 8 
  [ 9] .rela.dyn  RELA  0000000000401640 001640 0000a8 18 A 5 0 8 
  [10] .rela.plt  RELA  00000000004016e8 0016e8 000a80 18 A 5 12 8 
  [11] .init  PROGBITS 0000000000402168 002168 00001a 00 AX 0 0 4 
  [12] .plt  PROGBITS 0000000000402190 002190 000710 10 AX 0 0 16 
  [13] .text  PROGBITS 00000000004028a0 0028a0 00f65a 00 AX 0 0 16 
  [14] .fini  PROGBITS 0000000000411efc 011efc 000009 00 AX 0 0 4 
  [15] .rodata  PROGBITS 0000000000411f20 011f20 0050fc 00 A 0 0 32 
  [16] .eh_frame_hdr PROGBITS 000000000041701c 01701c 00072c 00 A 0 0 4 
  [17] .eh_frame  PROGBITS 0000000000417748 017748 0025fc 00 A 0 0 8 
  [18] .init_array INIT_ARRAY 0000000000619df0 019df0 000008 00 WA 0 0 8 
  [19] .fini_array FINI_ARRAY 0000000000619df8 019df8 000008 00 WA 0 0 8 
  [20] .jcr  PROGBITS 0000000000619e00 019e00 000008 00 WA 0 0 8 
  [21] .dynamic  DYNAMIC  0000000000619e08 019e08 0001f0 10 WA 6 0 8 
  [22] .got  PROGBITS 0000000000619ff8 019ff8 000008 08 WA 0 0 8 
  [23] .got.plt  PROGBITS 000000000061a000 01a000 000398 08 WA 0 0 8 
  [24] .data  PROGBITS 000000000061a3a0 01a3a0 000254 00 WA 0 0 32 
  [25] .bss  NOBITS  000000000061a600 01a5f4 000d60 00 WA 0 0 32 
  [26] .gnu_debuglink PROGBITS 0000000000000000 01a5f4 000008 00 0 0 1 
  [27] .shstrtab  STRTAB  0000000000000000 01a5fc 0000fe 00 0 0 1 
Key to Flags: 
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large) 
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) 
  O (extra OS processing required) o (OS specific), p (processor specific) 
+1

感谢这个,抱歉耽误了! 28 11月. 172017-11-28 11:20:55

  0

@ Marius.pharoe没问题 - 不客气 28 11月. 172017-11-28 22:22:13