Skip to content

Deepseek relocation table and symbol table

好的!符号表(Symbol Table)重定位表(Relocation Table) 是目标文件(Object File)中的关键数据结构,它们在链接(Linking)阶段起着核心作用。以下以 C 语言为例,结合具体场景详细解释它们的意义和功能:


1. 符号表(Symbol Table)

符号表记录了目标文件中定义的符号(如函数、全局变量)及其属性,是链接器(Linker)解析跨文件符号依赖的核心依据。

符号(Symbol)是什么?

  • 符号可以是:
  • 函数名(如 main, printf
  • 全局变量(如 int global_var;
  • 静态变量(如 static int static_var;

符号表的作用

  1. 记录符号的定义与引用
    - 符号表中包含符号的 名称地址作用域(全局/局部)等信息。
    - 例如:

    • main 函数在代码段中的地址。
    • global_var 全局变量在数据段中的地址。
  2. 解决符号的跨文件引用
    当多个目标文件需要互相调用函数或访问变量时,链接器通过符号表找到符号的实际地址。


示例:符号表的内容

假设有 main.cmath.c 两个文件:

math.c

C
int add(int a, int b) {
    return a + b;
}

main.c

C
extern int add(int, int);  // 声明外部函数

int global_var = 42;        // 全局变量

int main() {
    int result = add(3, 4);
    return 0;
}

编译后的符号表(简化)

符号名(Symbol) 类型(Type) 地址(Address) 作用域(Scope)
add 函数 0x0000 全局(Global)
global_var 变量 0x1000 全局(Global)
main 函数 0x2000 全局(Global)
  • :未定义的符号(如 printf)也会被记录为“未解决”(Undefined),需由链接器处理。

2. 重定位表(Relocation Table)

重定位表记录了目标文件中 需要被修正的地址引用。这些地址在汇编阶段无法确定(例如调用外部函数或访问跨文件的全局变量),需在链接阶段由链接器修正。

为什么需要重定位?

  • 地址不确定性:汇编阶段无法预知符号的最终地址(例如其他目标文件中的函数位置)。
  • 动态修正:链接器将多个目标文件合并时,需要修正这些地址引用。

示例:重定位表的内容

main.c 中的代码为例:

C
extern int add(int, int);

int main() {
    int result = add(3, 4);  // 调用外部函数 add
    return 0;
}

对应的汇编代码(x86)

Text Only
main:
    ...
    call add     ; 调用 add 函数(地址未知)
    ...
  • 在目标文件 main.o 中,call add 的机器码中 add 的地址是临时的(例如填 0x00000000)。
  • 重定位表 会记录这条指令的位置,并标记:“此处需要替换为 add 函数的真实地址”。

重定位表的条目(简化)

偏移量(Offset) 符号(Symbol) 类型(Type)
0x1234 add R_X86_64_PC32
  • 偏移量(Offset):需要修正的地址在目标文件中的位置。
  • 符号(Symbol):需要引用的符号名(如 add)。
  • 类型(Type):重定位的计算方式(例如相对地址或绝对地址)。

3. 符号表与重定位表的协作流程

链接器(Linker)的工作流程如下:

  1. 符号解析(Symbol Resolution)
    - 遍历所有目标文件的符号表,检查每个未定义的符号是否在其他目标文件中定义。
    - 例如:发现 main.o 需要 add 函数,而 math.o 中定义了 add

  2. 地址分配(Address Allocation)
    - 将所有目标文件的代码段和数据段合并,为每个符号分配最终地址。

  3. 重定位(Relocation)
    - 根据重定位表中的条目,修正代码中的地址引用。
    - 例如:将 call add 的临时地址替换为 add 函数的实际地址。


4. 实际工具查看符号表与重定位表

以 Linux 工具 objdumpreadelf 为例:

查看符号表

Bash
objdump -t main.o  # 显示符号表

输出示例:

Text Only
SYMBOL TABLE:
0000000000000000 g     F .text  0000000000000015 main
0000000000000000 g     O .data  0000000000000004 global_var
                 U add  # "U" 表示未定义(Undefined)

查看重定位表

Bash
readelf -r main.o  # 显示重定位表

输出示例:

Text Only
Relocation section '.rela.text' at offset 0x200:
  Offset     Info     Type           Symbol's Name
  0x00001234 0x00000102 R_X86_64_PC32 add

关键术语中英对照

中文术语 英文翻译
符号表 Symbol Table
重定位表 Relocation Table
符号 Symbol
全局符号 Global Symbol
未定义符号 Undefined Symbol
偏移量 Offset
重定位条目 Relocation Entry
链接器 Linker
地址修正 Address Fixup

总结

  • 符号表(Symbol Table):记录目标文件中定义的符号及其属性,是链接器解析符号依赖的“地图”。
  • 重定位表(Relocation Table):标记需要修正的地址引用,是链接器合并代码时进行地址修正的“任务清单”。

二者共同协作,确保多个目标文件能正确合并为一个可执行文件。