用"汉堡包"比喻理解32位ELF文件结构
让我们用一个形象的汉堡包来理解32位ELF可执行文件的结构:
🍔 完整ELF汉堡包结构
[面包顶] ELF Header (文件头) - 描述整个文件的基本信息
[番茄酱] Program Header Table (程序头表) - 告诉系统如何"吃"这个汉堡
[肉饼] .text段 - 核心代码(牛肉饼)
[奶酪] .data段 - 已初始化数据(融化的奶酪)
[生菜] .rodata段 - 只读数据(脆生菜)
[酱料] .bss段 - 未初始化数据(隐形酱料,吃的时候才加上)
[面包底] Section Header Table (节区头表) - 汉堡的原料清单
1️⃣ ELF Header - 汉堡包装纸
想象这是汉堡外面的包装纸,上面印着:
"这是一个ELF汉堡" (魔数\x7FELF)
"32位大小" (1)
"小端口味" (1)
"制作版本v1"
"从第1000口开始吃" (e_entry入口地址)
"配料表在第52字节处" (e_phoff程序头位置)
"营养表在文件末尾" (e_shoff节区头位置)
2️⃣ Program Header - 食用说明书
就像汉堡附带的"如何食用"说明:
LOAD说明1:
- 从哪里咬(offset):0x1000
- 咬到哪(vaddr):0x08048000
- 要嚼多少口(filesz):0x500
- 实际消化量(memsz):0x500
- 吃法权限:可读可执行(RX)
LOAD说明2:
- 从哪里咬:0x2000
- 咬到哪:0x08049000
- 嚼多少口:0x300
- 实际消化量:0x500 (多出的0x200是bss段)
- 吃法权限:可读可写(RW)
3️⃣ .text段 - 牛肉饼
汉堡的核心部分,包含:
; 主厨特制代码
_start:
mov eax, 1 ; 拿叉子
mov ebx, msg ; 指向"美味!"标签
int 0x80 ; 执行吃汉堡动作
4️⃣ .data段 - 奶酪片
已经准备好的配料:
int delicious_level = 100; // 美味度初始值
char sauce[] = "mayo"; // 已有酱料
5️⃣ .bss段 - 隐形酱料
吃的时候才会准备的配料:
int later_added_salt; // 吃的时候才会撒的盐
char buffer[1024]; // 吃的时候才准备的餐巾纸
🛠️ 制作过程类比
-
准备原料(写汇编/C代码):
section .recipe ; 食谱段落 cook_hamburger: add beef, 1 grill 5min
-
包装汉堡(链接过程):
ld -m elf_i386 -T burger.ld -o hamburger.elf beef.o cheese.o
-
质量检查(readelf查看):
readelf -a hamburger.elf # 检查汉堡完整结构
💡 关键点记忆口诀
ELF汉堡三层楼,
头表身段要记牢。
程序头表像菜单,
节区头表是账单。
text代码是肉饼,
data奶酪已备好。
bss空盘后加料,
加载入口最重要。
通过这个汉堡比喻,你应该能形象地理解:
• ELF头是包装信息
• 程序头表告诉系统如何加载(怎么吃)
• text/data/bss是不同配料
• 程序入口就是第一口咬下的位置
• 动态链接就像额外要的番茄酱包(需要时才加载)