为何ELF文件LOAD程序头虚拟地址与GDB显示的运行时虚拟地址不一致?
问题解答:ELF LOAD头VirtAddr与GDB实际加载地址不符
这是**地址空间布局随机化(ASLR)**导致的典型现象,现代Linux系统默认开启这个安全机制,用来降低内存攻击的风险。我来给你拆解清楚:
核心原因
ELF文件中LOAD头的VirtAddr是相对虚拟地址(RVA)——也就是相对于程序加载基址的偏移量,而不是进程运行时的绝对虚拟地址。当ASLR开启时,操作系统会为每个新启动的进程随机分配一个基地址,所有段的实际加载地址都是「随机基地址 + VirtAddr」的结果。
验证你的例子
看你提供的输出:
- readelf的LOAD头:第二个LOAD段的VirtAddr是
0x1000,对应程序的代码段(.text)区域。 - GDB的memmap:Entry point是
0x555555555040,这个地址减去LOAD头的0x1000,得到0x555555554000——这就是本次运行时操作系统分配的随机基地址。 - 对应其他段:比如
.interp段在0x5555555542a8,减去基址0x555555554000得到0x2a8,这个偏移正好落在第一个LOAD段(VirtAddr0x0,大小0x560)的范围内,完全匹配ELF文件的定义。
如何让地址匹配(调试时)
如果想关闭ASLR,让实际加载地址和ELF文件的VirtAddr一致,可以用两种方式:
- 在GDB内临时关闭:启动GDB后执行
set disable-randomization on,然后再运行程序。 - 系统全局关闭(需要root权限):执行
echo 0 > /proc/sys/kernel/randomize_va_space(重启后会恢复默认)。
附你提供的原始输出
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 memmap 输出
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
内容的提问来源于stack exchange,提问作者Mah35h
相关产品推荐
相关产品推荐

