如何在C语言中获取符号相对偏移?GCC等编译器实现方案问询
在C中生成符号相对自身起始位置的偏移量(适配GCC/vbcc/SAS/C)
针对你需要复刻汇编中Start dc.l tokenTable-Start的相对偏移逻辑,以下是几种适配不同编译器的实现方案:
方案1:纯C写法(利用编译器地址计算)
核心思路是将偏移表强制放在.text段,通过地址转整数后相减得到编译时可计算的字节偏移,与汇编逻辑完全对齐。
GCC实现
#include <stdint.h> // 将偏移表强制放入.text段,used属性防止编译器优化丢弃 static const ULONG offset_table[] __attribute__((section(".text"), used)) = { // 转换为uintptr_t后相减,得到tokenTable相对于offset_table起始的字节偏移 (ULONG)((uintptr_t)&tokenTable - (uintptr_t)&offset_table[0]), // 其他符号的偏移同理 (ULONG)((uintptr_t)&other_symbol - (uintptr_t)&offset_table[0]) }; // 后续定义目标静态符号 static const ULONG tokenTable[] = { /* 你的符号内容 */ }; static const ULONG other_symbol[] = { /* 你的符号内容 */ };
vbcc实现
#include <stdint.h> // 强制放入.text段 static const ULONG offset_table[] __section(".text") = { (ULONG)((uintptr_t)&tokenTable - (uintptr_t)&offset_table[0]), (ULONG)((uintptr_t)&other_symbol - (uintptr_t)&offset_table[0]) }; static const ULONG tokenTable[] = { /* 你的符号内容 */ }; static const ULONG other_symbol[] = { /* 你的符号内容 */ };
SAS/C实现
SAS/C通过#pragma section指定段:
#include <stdint.h> // 指定后续代码放入.text段 #pragma section text static const ULONG offset_table[] = { (ULONG)((uintptr_t)&tokenTable - (uintptr_t)&offset_table[0]), (ULONG)((uintptr_t)&other_symbol - (uintptr_t)&offset_table[0]) }; // 恢复默认段设置 #pragma section reset static const ULONG tokenTable[] = { /* 你的符号内容 */ }; static const ULONG other_symbol[] = { /* 你的符号内容 */ };
方案2:嵌入式汇编写法(完全复刻原汇编逻辑)
如果纯C写法存在兼容性问题,直接嵌入汇编是最可靠的方式,完全对应原汇编的dc.l定义逻辑:
GCC/vbcc通用写法
// 嵌入汇编定义偏移表,与原汇编逻辑完全一致 asm( ".text\n" "offset_table:\n" " .long tokenTable - offset_table\n" // 直接生成字节偏移 " .long other_symbol - offset_table\n" ); // 声明符号让C代码可访问 extern const ULONG offset_table[]; extern const ULONG tokenTable[]; extern const ULONG other_symbol[]; // 后续定义目标符号 static const ULONG tokenTable[] = { /* 你的符号内容 */ }; static const ULONG other_symbol[] = { /* 你的符号内容 */ };
SAS/C汇编写法
适配SAS/C的汇编语法:
asm( "SECTION TEXT\n" "offset_table:\n" " DC.L tokenTable-offset_table\n" " DC.L other_symbol-offset_table\n" ); extern const ULONG offset_table[]; extern const ULONG tokenTable[]; extern const ULONG other_symbol[]; static const ULONG tokenTable[] = { /* 你的符号内容 */ }; static const ULONG other_symbol[] = { /* 你的符号内容 */ };
注意事项
- 段一致性:确保偏移表和目标符号都在同一个段(
.text),否则地址相减的结果无意义。 - 链接脚本调整:如果需要偏移表严格放在
.text段开头,可能需要修改链接脚本,将偏移表所在的section放在.text的最前端。 - 符号可见性:目标符号必须是编译时可见的静态/全局符号,外部符号的偏移需在链接阶段计算,可能需要链接器脚本的额外支持。
内容的提问来源于stack exchange,提问作者Fredrik Rambris
相关产品推荐
相关产品推荐

