ARM64裸机Payload移出全局const变量后.rodata地址异常求助
解决ARM64 Payload全局变量地址错位问题
核心问题根源
全局字符串存放在.rodata段,指针存放在.data段,默认链接脚本会将这些段分配到与.text间隔较大的地址区域,而你的Payload加载环境仅映射或默认从.text起始地址运行,导致代码访问的指针地址与实际字符串存储地址不匹配。
解决方案(按优先级排序)
1. 强制将全局变量嵌入.text段
直接用编译器属性把字符串和指针都放到.text段的自定义子段中,避免跨段地址偏移问题:
// 将字符串直接嵌入.text段,无需单独指针 const char txt[] __attribute__((section(".text.str"))) = "Hello, world!"; // 如果必须用指针(比如跨函数访问),同样把指针也塞进.text const char* txt_ptr __attribute__((section(".text.ptr"))) = txt;
这样编译后,字符串和指针会和代码逻辑放在同一个.text段内,链接器不会将其拆分到其他高地址区域,加载后地址完全匹配。
2. 使用自定义链接脚本控制段顺序
如果需要保留.rodata/.data段,自定义极简链接脚本强制所有必要段紧跟.text,确保地址连续:
ENTRY(_start) SECTIONS { . = 0x10000; // 替换为你的Payload实际加载基址 .text : { *(.text) // 代码段 *(.text.str) // 自定义字符串子段(如果用了方案1) *(.text.ptr) // 自定义指针子段(如果用了方案1) } .rodata : { *(.rodata) } > .text // .rodata紧跟.text .data : { *(.data) } > .text // .data紧跟.text /DISCARD/ : { *(.note*) *(.comment*) *(.eh_frame*) } // 丢弃无用段 }
在Makefile中指定链接脚本:
LDFLAGS += -T payload.ld
3. 精简objcopy命令,剔除冗余段
之前二进制暴增是因为默认objcopy包含了大量无用段,现在只保留必要段:
arm-none-eabi-objcopy -O binary \ --only-section=.text \ --only-section=.rodata \ --only-section=.data \ payload.elf payload.bin
这样生成的二进制大小会被严格控制在29000字节以内。
4. 验证地址正确性
编译后用arm-none-eabi-objdump -d -s payload.elf查看,确认:
- 代码中访问
txt的指令(比如ldr x0, =txt)对应的地址,与字符串实际存储地址一致 - 所有段的地址是连续的,没有出现大的间隔
内容的提问来源于stack exchange,提问作者kupper.m
相关产品推荐
相关产品推荐

