C全局静态变量初始化是由链接器完成的吗? [英] C global static variable initialization is done by linker?

查看:92
本文介绍了C全局静态变量初始化是由链接器完成的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有:

f1.c

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

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

main.c

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

我们将编译并读取两个ELF文件符号表(相对于ELF和exec ELF):

we will compile and read the two ELF file symboltables (rel. ELF and 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

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

I can see that the Value (also known as address) in which the global static variable x is 0000000000000000 from reading the relocatable object file f1.o.
Which means we haven't initialized it yet since it is still a rel. ELF object file and the linker will take care of this.

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

So my question is then, if the linker is the one to set x to the value of 10 at known address after linking of 0000000000601038, how does it do so? Where does the linker get the information to set the value to 10 and who gives this information (f1.o?) ?

推荐答案

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

The value 0000000000000000 (in object file f1.o) is a relative address (of the static variable), so is an offset, and that file also contains relocation directives related to it. The code for getting the argument x to print has also some relocation on it (on some load machine instruction).

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

In that object file you probably have a .data section. That section should start with a word (having the 0 offset you observed in f1.o) containing 10.

详细了解链接器(我建议Levine的 ELF 可执行文件)正在处理重定位指令.另请阅读有关ELF格式的更多信息,从 elf(5)(在阅读 ELF 维基页面之后).还要研究 ABI 规范(对于Linux x86-64,请参见答案),其中详细介绍了可能的重定位指令.

Read much more about linkers (I recommend Levine's Linkers and loaders book). The linking process (to get the ELF executable) is processing relocation directives. Read also more about the ELF format, starting with elf(5) (after having read the ELF wikipage). Study also the ABI specifications (for Linux x86-64 see here from this answer) which details possible relocation directives.

您可能想用gcc -Wall -S -fverbose-asm -O1 f1.c编译f1.c,然后查看发出的汇编文件f1.s

You may want to compile your f1.c with gcc -Wall -S -fverbose-asm -O1 f1.c then look at the emitted assembler file f1.s

您可能还想使用各种工具(例如f1.o和ELF可执行文件a.out. .html"rel =" nofollow noreferrer> readelf(1)和

You may also want to inspect the object file f1.o and the ELF executable a.out with various tools like readelf(1) and objdump(1). Both accept numerous options (notably the -r option to objdump to show relocation directives).

动态链接(属于 ld-linux(8)(其中在运行时开始时进行一些链接工作)和 vdso(7).您可能还需要阅读Drepper的 如何编写共享库 纸.

Dynamic linking (of the C standard library libc.*.so) introduces some additional complexity in the ELF executable. See also ld-linux(8) (which does some linking job at start of runtime) and vdso(7). You may also want to read Drepper's How To Write Shared Libraries paper.

免费提供的教科书 操作系统:三件简单的书 也可能值得一读(它解释了过程是什么)以及执行过程如何.)

The freely available textbook Operating Systems: Three Easy Pieces could also be worthwhile to read (it explains what a process is and how its execution proceeds).

这篇关于C全局静态变量初始化是由链接器完成的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆