Day.5 深入理解连结之符号解析

在上一篇文章中,我们熟悉了可重定位文件和可执行文件,我们继续学习连节操作的具体步骤---「符号解析」

符号与符号表

连结的过程就是把多个不同的 obj file 相互"黏"在一起,为了使不同的 obj file 能够相互黏合,必须有固定的规则才行,才能避免连结的过程中不同变数和函数之间的混淆,在连结中,我们将函数很变数称为符号(Symbol),连结过程中很关键的一个部份就是符号的管理,每一个 obj file 都会有一个相对应的符号表(Symbol Tabel) ,记录着目标文件中所用到的所有符号,每个定义的符号都有一个对应值,称为Symbol Value,对於variable和functoin来说,Symbol Value指的就是他们的地址。

符号解析到底做了什麽?

  • 程序中有定义和引用的符号(包括函数与变数)
  • 编译器将定义的符号放在符号表中
    • 符号表是一个资料结构
    • 每个表象包含符号名、长度位置等讯息
  • 连结器将每个符号的引用与每一个确定的符号建立关联

下面将使用一个具体的例子介绍符号的类型:

// main.c
int buf[2] = {1, 2};
void swap();


int main() {
    swap();
    return 0;
}
// swap.c
extern int buf[];
int *bufp0 = &buf[0];

static int *bufp1;

void swap() {
    int temp;
    bufp1 = &buf[1];
    temp = *bufp0;
    *bufp0 = *bufp1;
    *bufp1 = temp;
 }
  • 全局符号 (Global symbols) :

    • 定义在目标文件的全域符号,可被其他 obj file 使用。像是是非 static C函数和非 static 的C全局变数,如:main中的buf。
  • 外部符号 (External symbols):

    • 你有使用,但是却没有定义在自己的obj file中 如:printf或是 main.c 中的函数名 swap
  • 局部符号 (Local symbols):

    • 仅由此 module中 定义和引用的符号,像是static variable, 这类的符号对linker来说意义不大,linker往往忽略他们,如:swap.c 中的 bufp1。

※函数中的区域变数比如 temp 是存在 stack 中的,编译器管不到。

如何查看Obj file 中的符号?

首先通过命令
$ gcc -c main.c -o main.o 在通过
$ readelf -s main.o 看符号表:

  • ‎buf 是属於第 3(Ndx)节,OBJECT 物件,全域作用域,大小 8位元组。‎
  • ‎swap 不知道是哪个节的,不知道什麽类型,没有定义的符号(UND),全域作用域‎
  • ‎main 第 1 节(.text)函数物件,大小 25 位元组。‎

连结器如何解析多重定义的全局符号?

在编译阶段, Compiler 会将每个 symbol 分类为 strong 或 weak

  • Strong Symbol : 包含 procedures 和被初始化过的全域变数。
  • Weak Symbol : 未被初始化的全域变数。

Linker 利用以下列规则来决定如何做 Linking :

  • 同时存在多个同名 strong symbol 是不允许的。
  • 假设有一个 strong symbol 与多个 weak symbol , Linker 应选择 strong symbol。
  • 如果只有多个 weak symbol 同名 ,任意选择其中一个。

举一个例子(规则二)

/* foo4.c */
#include <stdio.h>
void f(void);

int x ; // Weak Symbol

int main(){
    f();
    printf("x = %d\n", x);
    return 0;
}
/* bar4.c */
int x; // Weak Symbol

void f(){
    x = 15212
}

foo4.c x 被弱定义一次,bar4.c x 也被弱定义一次,因此会任意选择一个定义,造成难以察觉的错误。

tags: IT 铁人系列文章

参考资料

深入理解计算机系统
程序设计师的自我修养


<<:  Day3 # 资料型别

>>:  Day4:如何使用Parrot_Security的CeWL工具收集特定网站的Wordlist

Day 17 Matcher 介绍 (中)

该文章同步发布於:我的部落格 今天一样继续来介绍实用的 Matcher 和举例~ all matc...

Day19 vue.js之我的专案显示

延续昨日 今天从我的专案开始 老样子先新增一个project.vue 再来去加入新的path 然後先...

专案档案结构

第二阶段也接近到尾声了,现在便利贴已经有了比较丰富的功能了,可以拖曳便利贴、改变颜色、改变文字、新增...

Day8:EndPoint for Microsoft Defender 警示和事件

当我们布署完Microsoft Defender for Endpoint 接下来当侦测到威胁时,系...

云端资安之AWS篇

今天要谈的是AWS(Amazon Web Services)云端服务, 这个也是众多云端服务当中,我...