【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。

相关推荐
名字还没想好☜8 小时前
Python f-string 进阶:数字格式化、对齐填充、调试 = 号与嵌套表达式
开发语言·数据库·python·字符串格式化·f-string
一壶浊酒..11 小时前
Scrape Webpack练习
开发语言·javascript·webpack
命运之光12 小时前
【C语言完整代码】就诊信息管理系统
java·c语言·开发语言
命运之光12 小时前
【C语言完整代码】图书管理系统:图书馆场景下的增删改查实战
c语言·开发语言
猿长大人13 小时前
C# | Serilog 新手入门
开发语言·c#·.net·log
在世修行14 小时前
从零打造 C# 工业视觉检测系统(七):串口通信 SerialPort 封装与开发
开发语言·c#·modbus rtu·rs232/rs485
沫璃染墨14 小时前
《从零入门Linux系统篇(十五):系统工具篇·六——GDB调试器详解:从程序执行控制到高级调试技巧》
linux·运维·服务器·c语言·c++
Hammer_Hans15 小时前
DFT笔记98
java·开发语言·数据库
qq_4480111616 小时前
C语言中的野指针和空指针
c语言·开发语言·单片机
估值探索者16 小时前
【Python实时盯盘与预警 #08】成交额突然放大2倍?Python窗口比较抓异动
java·开发语言·python