You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LOAD程序头中的偏移为何与地址空间中的偏移不匹配?

为何ELF LOAD段偏移与pmap输出不一致?

问题详情

我有如下ELF程序头信息:

Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align

  LOAD           0x002dd0 0x0000000000003dd0 0x0000000000003dd0 0x000250 0x000258 RW  0x1000

该LOAD段本应映射以下节:

.init_array .fini_array .dynamic .got .got.plt .data .bss 

执行readelf -l program可以确认这些节的起始地址确实是0x002dd0:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  (...)
  [20] .init_array       INIT_ARRAY      0000000000003dd0 002dd0 000008 08  WA  0   0  8
  [21] .fini_array       FINI_ARRAY      0000000000003dd8 002dd8 000008 08  WA  0   0  8
  [22] .dynamic          DYNAMIC         0000000000003de0 002de0 0001e0 10  WA  7   0  8
  [23] .got              PROGBITS        0000000000003fc0 002fc0 000028 08  WA  0   0  8
  [24] .got.plt          PROGBITS        0000000000003fe8 002fe8 000028 08  WA  0   0  8
  [25] .data             PROGBITS        0000000000004010 003010 000010 00  WA  0   0  8
  [26] .bss              NOBITS          0000000000004020 003020 000008 00  WA  0   0  1

但启动进程后通过pmap查看,对应映射的偏移是0x003000而非0x002dd0:

Address Perm   Offset   Inode Size Rss Anonymous  Mapping
    63a2b2ccb000 rw-p 00003000 5243856    4   4         4  program

疑惑点:如果偏移从0x003000开始,那0x002dd0-0x002fff范围内的数据岂不是丢失了?

原因分析

这是**RELRO(重定位只读)**机制导致的,具体逻辑如下:

  • RELRO是一种程序安全机制,会把.init_array、.fini_array、.dynamic、.got这些原本属于RW(读写)LOAD段的节设置为只读权限,系统会为这部分内容单独创建一个新的只读映射(权限通常为r--p),0x002dd0-0x002fff范围的内容就属于这个只读映射,你可以在pmap的完整输出里找到对应的条目。
  • 你看到的0x003000偏移的RW映射,只包含.data和.bss这两个仍需要读写权限的节,所以不存在数据丢失的情况——只是原本的一个LOAD段被RELRO拆分成了两个不同权限的映射段,以此提升程序安全性,防范内存篡改类攻击。

内容的提问来源于stack exchange,提问作者Wiertek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:03:21