【RISC-V】从C到可执行文件分析链接重定位的过程

代码testlinker.c

cpp 复制代码
int a = 5;

int foo(void){
    return a;
}

int main(void){
    foo(); 
}

运行命令,生成中间文件

bash 复制代码
riscv64-linux-gnu-gcc testlinker.c -o testlinker --save-temps -mno-relax

--save-temps:保留所有中间文件。

-mno-relax:关闭链接器松弛优化

  • .c:高级语言文件

  • .i:预处理文件。

  • .s:汇编文件

  • .o:可重定位文件

  • 无后缀:可执行文件

查看汇编后还没链接的重定位文件

复制代码
riscv64-linux-gnu-objdump -d -r testlinker.o

以下这几行就是需要链接器重定位的地方,可以看到此时全局变量 a 的地址是"未知"的,只能留一个占位符(通常是0x0),需要在重定位中填入修正值

如a: R_RISCV_PCREL_LO12_I .L0:表示在地址偏移 a处有一个 重定位项(relocation entry) ,类型是 R_RISCV_PCREL_LO12_I,其目标符号是 .L0

重定位修正值(relocation addend / relocation offset)

在链接阶段,链接器需要写入到目标指令或数据中的具体数值,用于修正该位置的占位值(通常是 0),使其在最终可执行文件中能正确引用符号(如变量、函数)的实际地址。

修正值的计算公式取决于类型:

如a是R_RISCV_PCREL_HI20类型的,修正值=S+A-P,其中:

  • S:链接地址,被引用符号(如 a)在最终可执行文件的链接地址
  • A:重定位项中携带的附加常量(addend),在某些情况下要考虑对齐用于调整对齐
  • P:当前重定位发生处(即 auipc 指令)的 运行时地址(运行到重定位发生处该指令PC的值)。

先通过查看程序反汇编查询P,可以看到auipc指令时P=0x602(PS:这是基于人的视角从可执行文件倒推,实际链接器在连接的时候会直接根据S、A、P计算出修正值,填入重定位值)

复制代码
riscv64-linux-gnu-objdump -d testlinker

查看符号表,查看全局变量a在哪被定义

复制代码
riscv64-linux-gnu-readelf -s testlinker

可以看到链接地址S为2008,不用对齐,A=0

所以offset = S + A - P = 0x1A06,所以链接器要填入的重定位的值就是0x1A06。

相关推荐
青槿吖20 小时前
第二篇:告别XML臃肿配置!Spring注解式IOC/DI保姆级教程,从入门到真香
xml·java·开发语言·数据库·后端·sql·spring
t1987512820 小时前
TOA定位算法MATLAB实现(二维三维场景)
开发语言·算法·matlab
梦想的旅途220 小时前
如何通过 QiWe API 实现企业微信主动发消息
开发语言·python
jllllyuz20 小时前
粒子群算法解决资源分配问题的MATLAB实现
开发语言·算法·matlab
凌晨一点的秃头猪20 小时前
Python文件操作
开发语言·python
myloveasuka21 小时前
C++进阶:利用作用域解析运算符 :: 突破多态与变量隐藏
开发语言·c++
OxyTheCrack21 小时前
【C++】详细拆解std::mutex的底层原理
linux·开发语言·c++·笔记
云栖梦泽21 小时前
易语言开发从入门到精通:进阶篇·网络爬虫与数据采集分析系统深度实战
开发语言
lsx20240621 小时前
XSLT `<sort>` 元素详解
开发语言
_olone21 小时前
牛客每日一题:显生之宙(Java)
java·开发语言·算法·牛客