【问题标题】:How variables of .bss are resolved in final image?.bss 的变量如何在最终图像中解析?
【发布时间】:2009-12-27 15:19:12
【问题描述】:

如果这个问题太琐碎,请原谅我!众所周知,最终的可执行文件不会为映像中的未初始化数据分配空间。但我想知道,如何解决对 .bss 中符号的引用?

目标文件是否仅包含 .bss 的这些变量的地址,而不是为它们分配空间?如果是这样,这些解析的地址存储在哪里?

例如。如果在 C 模块中我有类似以下全局变量的东西 -

int x[10]; 字符 chArray[100];

上述变量的空间可能不存在于图像中,但如何引用它们?他们的地址在哪里解析?

提前致谢! /MS

【问题讨论】:

    标签: linker loader


    【解决方案1】:

    .bss 符号就像编译器(或汇编器)生成的任何其他符号一样被解析。通常这是通过将相关符号放在“部分”中来实现的。例如,编译器可能会将程序代码放在名为“.text”的节中(出于历史原因;-),将初始化数据放在名为“.data”的节中,将统一数据放在名为.“.bss”的节中。

    例如:

    int i = 4;
    int x[10];
    char chArray[100];
    
    int main(int argc, char**argv)
    {
    }
    

    产生(使用 gcc -S):

        .file   "test.c"
    .globl i
        .data
        .align 4
        .type   i, @object
        .size   i, 4
    i:
        .long   4
        .text
    .globl main
        .type   main, @function
    main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        subl    $4, %esp
        addl    $4, %esp
        popl    %ecx
        popl    %ebp
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .comm   x,40,32
        .comm   chArray,100,32
        .ident  "GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)"
        .section        .note.GNU-stack,"",@progbits
    

    .data 指令告诉汇编器将 i 放在数据段中,“.long 4”给它它的初始值。当文件被组装时,i 将被定义在数据段的偏移量 0 处。

    .text 指令将 main 放在 .text 部分中,偏移量也为零。

    这个例子的有趣之处在于 x 和 chArray 是使用 .comm 指令定义的,而不是直接放在 .bss 中。两者都只给出了一个大小,而不是一个偏移量(还)。

    当链接器获取目标文件时,它通过将所有具有相同名称的部分组合在一起并相应地调整符号偏移来将它们链接在一起。它还为每个部分提供了一个绝对地址,应该在该地址处加载它。

    .comm 指令定义的符号被组合(如果存在多个同名定义)并放置在 .bss 部分。正是在这一点上,他们得到了他们的地址。

    【讨论】:

    • +1 无法更好地解释它!当然,所有这些都取决于架构,虽然我不知道一个例子,但所有 .bss 地址都可以相对于硬件寄存器组成 - 所以实际地址仅在运行时解析.
    • @Autopulated:好点子。我实际上实现了一个 C 编译器,它正是这样做的:它使用 X 索引寄存器指向 .bss 区域以获取与位置无关的数据。
    • 谢谢:-)。因此,如果得到它,一旦所有 .comm 指令组合在一起,.bss 就会解析其符号,并且这些解析的地址在它们被引用的任何地方都被修补(一种 .bss + 变量的偏移量)。 .bss 基础是在运行时分配的。对吗?
    • @MS:这取决于具体的环境。可能有一个寄存器在运行时指向 .bss 部分,或者在链接时可以知道 bss 部分的地址并由链接器填写实际地址。许多目标文件格式会跟踪目标文件中特定符号的访问位置(通常称为重定位记录),并且可以修改目标代码以在链接期间固定符号地址。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    • 2015-03-10
    • 2018-04-05
    • 2017-07-18
    • 1970-01-01
    • 2013-09-03
    • 1970-01-01
    相关资源
    最近更新 更多