为什么libgcc使用全局偏移表?
我正在尝试为i386-elf目标构建gcc 4.6。
我的问题如下。 在编译libgcc
我得到了使用全局偏移表的output-file _fixunsdfdi.o
。
将“double”转换为“unsigned long long”时使用该函数。 当我看着程序集时,它看起来像它的Wtype_MAXp1_F,它放在GOT中 - 但是为什么?
我配置了
--target=i386-elf --enable-languages=c --disable-nls --disable-libssp --disable-libquadmath --enable-shared=no --enable-static=yes
//Code for fixunsdfdi (from libgcc2.c)
#if defined(L_fixunsdfdi) && LIBGCC2_HAS_DF_MODE
UDWtype __fixunsdfDI (DFtype a)
{
/* Get high part of result. The division here will just moves the radix
point and will not cause any rounding. Then the conversion to integral
type chops result as desired. */
const UWtype hi = a / Wtype_MAXp1_F;
/* Get low part of result. Convert `hi' to floating type and scale it back,
then subtract this from the number being converted. This leaves the low
part. Convert that to integral type. */
const UWtype lo = a - (DFtype) hi * Wtype_MAXp1_F;
/* Assemble result from the two parts. */
return ((UDWtype) hi << W_TYPE_SIZE) | lo;
}
#endif
//Dump of the output
Class: 32-bit
Data: Little Endian
Header version: 1[Current Version]
OS/ABI: 0[UNIX System V ABI]
Type: 1[REL (Relocatable file)]
Machine: 0003h[Intel Architecture EM_386]
File version: 1[Current Version]
Entry point address: 00000000h
Start of program headers: 0 (bytes into file)
Start of section headers: 35496 (bytes into file)
Flags: 0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 15
Section header string table index: 12
[file offset:00008AA8h]Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[0] NULL 00000000 000000 000000 00 0 0 0
[1] .text PROGBITS 00000000 000034 000067 00 AX 0 0 4
[2] .rel.text REL 00000000 008E18 000018 08 13 1 4
[3] .data PROGBITS 00000000 00009C 000000 00 WA 0 0 4
[4] .bss NOBITS 00000000 00009C 000000 00 WA 0 0 4
[5] .stab PROGBITS 00000000 00009C 0004D4 0C 7 0 4
[6] .rel.stab REL 00000000 008E30 000030 08 13 5 4
[7] .stabstr STRTAB 00000000 000570 00844A 00 0 0 1
[8] .rodata.cst4 PROGBITS 00000000 0089BC 000008 04 A 0 0 4
[9] .comment PROGBITS 00000000 0089C4 000028 01 0 0 1
[10] .eh_frame PROGBITS 00000000 0089EC 000054 00 A 0 0 4
[11] .rel.eh_frame REL 00000000 008E60 000008 08 13 10 4
[12] .shstrtab STRTAB 00000000 008A40 000067 00 0 0 1
[13] .symtab SYMTAB 00000000 008D00 0000E0 10 14 12 4
[14] .strtab STRTAB 00000000 008DE0 000038 00 0 0 1
[file offset:00008E18h]Relocation section '.rel.text' contains 3 entries:
Type: REL
Num: Offset Info Type Sym.Value Addend To->Sym. Name
0: 0000000E 00000D0A R_386_GOTPC 00000000 00000003 _GLOBAL_OFFSET_TABLE_
1: 0000001A 00000709 R_386_GOTOFF 00000000 00000000 .LC0
2: 0000004A 00000809 R_386_GOTOFF 00000004 00000000 .LC1
[file offset:00008E30h]Relocation section '.rel.stab' contains 6 entries:
Type: REL
Num: Offset Info Type Sym.Value Addend To->Sym. Name
0: 00000014 00000201 R_386_32 00000000 00000000 .text
1: 00000020 00000201 R_386_32 00000000 00000000 .text
2: 00000434 00000C01 R_386_32 00000000 00000000 __fixunsdfdi
3: 0000044C 00000201 R_386_32 00000000 00000000 .text
4: 000004C4 00000201 R_386_32 00000000 00000067 .text
5: 000004D0 00000201 R_386_32 00000000 00000067 .text
[file offset:00008E60h]Relocation section '.rel.eh_frame' contains 1 entries:
Type: REL
Num: Offset Info Type Sym.Value Addend To->Sym. Name
0: 00000020 00000202 R_386_PC32 00000000 00000000 .text
[file offset:00008D00h]Symbol table '.symtab' contains 14 entries:
Num[h]: Value Size Type Bind Vis Ndx Name
000000: 00000000 0000 NOTYPE LOCAL UND
000001: 00000000 0000 FILE LOCAL ABS libgcc2.c
000002: 00000000 0000 SECTION LOCAL 1 .text
000003: 00000000 0000 SECTION LOCAL 3 .data
000004: 00000000 0000 SECTION LOCAL 4 .bss
000005: 00000000 0000 SECTION LOCAL 8 .rodata.cst4
000006: 00000000 0000 SECTION LOCAL 10 .eh_frame
000007: 00000000 0000 NOTYPE LOCAL 8 .LC0
000008: 00000004 0000 NOTYPE LOCAL 8 .LC1
000009: 00000000 0000 SECTION LOCAL 5 .stab
00000A: 00000000 0000 SECTION LOCAL 7 .stabstr
00000B: 00000000 0000 SECTION LOCAL 9 .comment
00000C: 00000000 0067 FUNC GLOBAL 1 __fixunsdfdi
00000D: 00000000 0000 NOTYPE GLOBAL UND _GLOBAL_OFFSET_TABLE_
我不想创建全局偏移量表,因为我在其他地方不需要它,而且它目前在im工程的链接器中不受支持。
Q1:为什么它使用全局偏移表中的符号?
Q2:有没有办法避免使用全局偏移表? 有什么帮助吗?
好吧,我不确定我是否完全理解,但在这里呢...
Q1:为什么它使用全局偏移表(GOT)中的符号?
使用GOT是因为通过编译器,链接器和加载器的工作方式,不可能知道每个对象在运行时将在内存中结束的位置。 编译器的适当步骤一次只能看到一个模块,所以它不能说明每个(外部)函数和全局变量的引用位置。 相反,它为每一个创建一个符号在链接时解决。 对于静态函数/变量,它会生成直接访问它们的代码(它取决于平台:在Linux / x86_64中使用的是程序计数器的偏移量)。 对于外部,它通过运行时数据结构生成间接访问代码:GOT。
在链接时,您可以知道哪些模块调用了哪些符号,因此链接器的工作是确保所有符号(无论是在您的程序中还是在其外部依赖项中的符号)都已解决,这意味着它们在多个模块中的其他位置定义编写你的程序。 对于在你自己的代码中定义的对象(或静态链接),可以在你的二进制文件(ELF / COFF / PE / etc)中告诉它的位置,但是你不知道在加载时间之前它们将在内存中的什么位置。 链接器还会在运行时写入所需的共享库和(可选)它们的可能位置。
当你运行你的程序时,加载器! 将尝试查找所有依赖项(共享库),然后作为进程启动的一部分将构建GOT结构。 它会从二进制文本部分将程序代码加载到内存中,对于每个符号,它将在GOT中创建一个条目,并在实际内存地址中找到它。 然后它会为每个共享库执行相同的操作。 还值得注意的是,一些图书馆可能保留独立于GOT的内部补偿表。 这样您可以多次定义相同的符号。 这是通过示例窗口SxS发生的事情! (微软对DLL地狱问题的回答)。
从程序的角度来看,每次访问外部符号需要2次内存访问(间接)。 如果符号表示一个函数,那么还有另一个结构PLT,即每个地方都有一个跳转表,带有GOTO指令。
Q2:有没有办法避免使用全局偏移表? 有什么帮助吗?
是的,最简单的方法是找出你不需要访问定义的模块外的哪些函数/全局变量,并将它们声明为静态。 通过这种方式,编译器会知道它可以生成直接访问代码来找到它们(与程序计数器的偏移是在Linux / x86_64中完成的方式,但是它取决于平台)。
我已经读过,在大型项目中,有一个专门的构建团队可以识别紧密耦合的模块集,并将它们集成到一个大的C文件中,以尽量减少通用产品中暴露的符号数量,但我从未见过它手。
也有链接器选项,可以帮助您避免暴露符号,但我知道它们只是语法糖。 GOT和PLT仍在使用,只是你的内容不透明。
Ulrich Drepper的如何编写共享库是一个很好的资源。
链接地址: http://www.djcxy.com/p/75549.html上一篇: Why does libgcc use global offset table?
下一篇: Can I provide the username to use in a SAML request? (AD FS)