gpt4 book ai didi

C全局静态变量初始化是由链接器完成的?

转载 作者:太空宇宙 更新时间:2023-11-04 05:49:54 26 4
gpt4 key购买 nike

假设我们有:

f1.c

#include <stdio.h>
static int x = 10;

void f1() {
printf("f1.c : %d\n", x);
}

主.c

extern void f1();
int main(int argc, char **argv) {
f1();
return 0;
}

我们将编译和读取两个 ELF 文件符号表(rel.ELF 和 exec ELF):

$> gcc -c *.c
$> readelf -s f1.o | grep x
Num: Value Size Type Bind Vis Ndx Name
5: 0000000000000000 4 OBJECT LOCAL DEFAULT 3 x
$> gcc *.o
$> readelf -s a.out | grep x
Num: Value Size Type Bind Vis Ndx Name
38: 0000000000601038 4 OBJECT LOCAL DEFAULT 25 x

通过读取可重定位对象,可以看到全局静态变量xValue(也就是地址)是0000000000000000文件 f1.o.
这意味着我们还没有初始化它,因为它仍然是一个 rel。 ELF 目标文件和链接器将处理此问题。

那么我的问题是,如果链接器在链接 0000000000601038 之后将已知地址处的 x 的值设置为 10,它是如何做到的?链接器从哪里获得信息以将值设置为 10 以及谁提供此信息 (f1.o?)?

最佳答案

0000000000000000(在目标文件 f1.o 中)是一个相对地址(静态变量的),因此是一个偏移量, 该文件还包含 relocation与其相关的指令。用于打印参数 x 的代码也有一些重定位(在一些加载机器指令上)。

在该目标文件中,您可能有一个 .data 部分。该部分应以包含 10 的单词(具有您在 f1.o 中观察到的 0 偏移量)开头。

阅读更多关于 linkers 的信息(我推荐 Levine 的 Linkers and loaders 书)。链接进程(获取 ELF 可执行文件)正在处理重定位指令。另请阅读有关 ELF 格式的更多信息,从 elf(5) 开始(在阅读了 ELF 维基页面之后)。也学习ABI规范(对于 Linux x86-64,请参阅 here 来自 this 答案)详细说明了可能的重定位指令。

您可能希望使用 gcc -Wall -S -fverbose-asm -O1 f1.c 编译您的 f1.c 然后查看生成的汇编程序文件 f1.s

您可能还想使用各种工具(如 readelf(1))检查目标文件 f1.o 和 ELF 可执行文件 a.outobjdump(1) .两者都接受许多选项(特别是 objdump-r 选项以显示重定位指令)。

Dynamic linking (属于 C standard library libc.*.so)在 ELF 可执行文件中引入了一些额外的复杂性。另见 ld-linux(8) (它在运行时开始时做一些链接工作)和 vdso(7) .您可能还想阅读 Drepper 的 How To Write Shared Libraries纸。

免费教科书 Operating Systems: Three Easy Pieces也可能值得一读(它解释了 process 是什么以及它的执行过程)。

关于C全局静态变量初始化是由链接器完成的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44962697/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com