为什么gdb显示的LOAD程序头虚拟地址和运行时虚拟地址不一样?

why virtual address of LOAD program header and runtime virtual address shown by gdb is different?

我一直在努力了解elf文件格式和elf格式文档,LOAD头的VirtAddr应该是加载段的虚拟地址。但是 gdb memmap 显示要加载到不同 virt 地址的段。

$ readelf -l

  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align

  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000560 0x0000000000000560  R      0x1000
  LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000
                 0x00000000000001e5 0x00000000000001e5  R E    0x1000
  LOAD           0x0000000000002000 0x0000000000002000 0x0000000000002000
                 0x0000000000000118 0x0000000000000118  R      0x1000
  LOAD           0x0000000000002de8 0x0000000000003de8 0x0000000000003de8
                 0x0000000000000248 0x0000000000000250  RW     0x1000

gdb 内存映射

    Entry point: 0x555555555040
    0x00005555555542a8 - 0x00005555555542c4 is .interp
    0x00005555555542c4 - 0x00005555555542e4 is .note.ABI-tag
    0x00005555555542e4 - 0x0000555555554308 is .note.gnu.build-id
    0x0000555555554308 - 0x0000555555554324 is .gnu.hash
    0x0000555555554328 - 0x00005555555543d0 is .dynsym
    0x00005555555543d0 - 0x0000555555554454 is .dynstr
    0x0000555555554454 - 0x0000555555554462 is .gnu.version
    0x0000555555554468 - 0x0000555555554488 is .gnu.version_r
    0x0000555555554488 - 0x0000555555554548 is .rela.dyn
    0x0000555555554548 - 0x0000555555554560 is .rela.plt
    0x0000555555555000 - 0x000055555555501b is .init
    0x0000555555555020 - 0x0000555555555040 is .plt
    0x0000555555555040 - 0x00005555555551d5 is .text
    0x00005555555551d8 - 0x00005555555551e5 is .fini
    0x0000555555556000 - 0x000055555555600a is .rodata
    0x000055555555600c - 0x0000555555556040 is .eh_frame_hdr
    0x0000555555556040 - 0x0000555555556118 is .eh_frame
    0x0000555555557de8 - 0x0000555555557df0 is .init_array
    0x0000555555557df0 - 0x0000555555557df8 is .fini_array
    0x0000555555557df8 - 0x0000555555557fd8 is .dynamic
    0x0000555555557fd8 - 0x0000555555558000 is .got
    0x0000555555558000 - 0x0000555555558020 is .got.plt
    0x0000555555558020 - 0x0000555555558030 is .data
    0x0000555555558030 - 0x0000555555558038 is .bss

VirtAddr of LOAD header should be the virtual address of the loaded segment.

这仅适用于 ET_EXEC 类型的 ELF 图像。

但是你有一个 ET_DYN 类型的 ELF 映像(可能是位置无关的可执行文件),并且这些映像在运行时被重新定位到不同的虚拟地址。