- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试为 i386-elf 目标构建 gcc 4.6。
我的问题如下。编译 libgcc
时,我得到了使用全局偏移表的 output-file _fixunsdfdi.o
。
该函数用于将 'double' 转换为 'unsigned long long'。当我查看程序集时,它看起来像是放置在 GOT 中的 Wtype_MAXp1_F - 但为什么呢?
我配置了
--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_
我不想创建全局偏移表,因为我在其他地方不需要它,而且我正在处理的项目中的链接器目前不支持它。
Q1:为什么在全局偏移表中使用符号?
Q2:有没有办法避免使用全局偏移表?有什么帮助吗?
最佳答案
好吧,我不确定我是否完全理解,但就是这样......
Q1:为什么要使用全局偏移表(GOT)中的符号?
使用 GOT 是因为通过编译器、链接器和加载器的工作方式,无法判断每个对象在运行时将在内存中的何处结束。编译器正确的步骤一次看到一个模块,所以它无法分辨每个(外部)函数和全局变量的引用位置。相反,它会为每一个创建一个符号,以便在链接时解析。对于静态函数/变量,它生成直接访问它们的代码(它依赖于平台:在 Linux/x86_64 中使用程序计数器的偏移量)。对于外部,它通过运行时数据结构生成间接访问代码:GOT。
在链接时,您可以知道哪些模块调用了哪些符号,因此链接器的工作是确保所有符号(无论是在您的程序中还是在其外部依赖项中)都已解析,这意味着它们在其他地方定义组成程序的多个模块。对于在您自己的代码中定义(或静态链接)的对象,可以在您的二进制文件(ELF/COFF/PE/等)中告诉它的位置,但在加载时间之前您不知道它们在内存中的位置。链接器还将所需的共享库和(可选)它们在运行时的可能位置写入二进制文件。
当你运行你的程序时,the loader !将尝试找到所有依赖项(共享库),然后作为进程启动的一部分将构建 GOT 结构。它会将您的程序代码从二进制的文本部分加载到内存中,并且对于每个符号,它将在 GOT 中创建一个条目,其中包含实际的内存地址。然后它将对每个共享库执行相同的操作。还值得注意的是,某些库可能会保留独立于 GOT 的内部偏移量表。这样您就可以多次定义相同的符号。这是用 Window SxS 发生的例子! (Microsoft 对 DLL hell 问题的回答)。
从程序的角度来看,每次访问外部符号都需要 2 次内存访问(间接)。如果这个符号代表一个函数,那么还有一个PLT结构体,就是一个跳转表,每个地方都有GOTO指令。
Q2:有没有办法避免使用全局偏移表?有什么帮助吗?
是的,最简单的方法是弄清楚哪些函数/全局变量在定义它们的模块之外不需要访问,并将它们声明为静态的。这样,编译器就会知道它可以生成直接访问代码来找到它们(从程序计数器偏移是它在 Linux/x86_64 中完成的方式,但它取决于平台)。
我听说在大型项目中有专门的构建团队识别紧密耦合的模块集并将它们集成到一个大的 C 文件中,以尽量减少暴露在一般产品中的符号数量,但我从来没有亲眼所见。
还有一些链接器选项可以帮助您避免暴露符号,但据我所知,它们只是语法糖。 GOT和PLT还在用,只是你把它的内容弄成不透明了。
这个主题的一个很好的资源是 Ulrich Drepper 的 How to Write Shared Libraries !
关于c - 为什么 libgcc 使用全局偏移表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20068781/
据我所知,libgcc 实现了一些 libc 函数,当程序使用内置函数并且 gcc 决定不通过某些内联汇编实现它时调用这些函数。然而,是否有可能让 gcc 始终将所有内置函数作为对 libgcc 的调
我正在尝试为 i386-elf 目标构建 gcc 4.6。 我的问题如下。编译 libgcc 时,我得到了使用全局偏移表的 output-file _fixunsdfdi.o。 该函数用于将 'dou
我一直在 Mac OS X 10.6 上使用 GCC 4.6.2。我在编译时使用 -static-libgcc 选项,否则我的二进制文件会在系统上寻找 libgcc,我不确定 OS X 是否支持 GC
我正在用 C++ 编写一个 Windows DLL。这个库只有 C 接口(interface),并且只使用也有 C 接口(interface)的标准 Windows 库。因此,将所有 C++ 库静态链
当我编译一个二进制文件时,即使我有依赖项,我仍然会收到以下错误。 /usr/bin/ld: 找不到 -l-static-libgcc /usr/bin/ld: 找不到-l-static-libstdc
我正在尝试编译 zbar-0.10 以静态链接到 MinGW 依赖项,因此它不需要 libgcc_s_dw2-1.dll、libwinpthread-1.dll 和 libstdc++-6.dll。
我有一个带有为目标平台编译的 libgcc 的交叉编译器,但不存在标准 C 库。 libgcc 依赖于哪些函数,我在哪里可以找到这些信息? 最佳答案 这些是 libgcc 所依赖的 C 函数:: 强
我目前正在尝试将我所有应用程序的依赖项编译为静态库。我的动机: 不依赖任何操作系统提供的库以拥有完美可重现的代码库 避免在其他系统上部署时由动态链接引起的问题 在链接不同版本的库时避免运行时冲突 能够
我们已经使用 RPM 文件在 AIX 6.1 上安装了 GCC 和 libgcc。 我想知道的是为什么“libgcc_s.a”没有创建在下面的文件夹下? /opt/freeware/lib/gcc/p
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 9 年前。 Improve this
我正在尝试安装交叉编译器,this tutorial ,当我想制作 libgcc 时,我只是把 make all-target-libgcc在我的终端。这会抛出错误 checking whether
我正在尝试生成一个不依赖于 libc(或任何其他)的可执行文件。首先,我这样做了: // test.c void _start() { // write(1, "hello!\n", 7);
我正在尝试使用 Google Toolchain 为我的 Android 手机独立编译内核,并且已经尝试过 Uber 和 linarc。 他们都给出了同样的错误,我不明白: /home/aayushg
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 7 年前。 Improve
int main(int argc, char **argv) { return 0; } 我交叉编译(host=linux x86_64,target=linux aarch64) /pat
我一直在使用clang-3.5愉快地构建musl libc的位码版本和使用结果生成漂亮的独立可执行文件。 最近对clang-3.8的尝试并不那么令人满意。看起来位代码 clang-3.8 生成使用 中
我正在尝试为 Android 交叉编译一个非常简单的程序,该程序适用于 android-ndk-r6b 和之前的版本,但不适用于 android-ndk- r7 及更新版本: int main() {
我正在尝试构建 GCC 4.7.3。当我用相当旧的系统 GCC 4.1 构建它时,一切正常,我得到了 GCC 4.7.3。但是当我试图用刚刚编译的 GCC 4.7.3(实际上是自己构建)重建它时,我遇
我尝试使用 -static -static-libgcc -static-libstdc++ 编译项目,以便静态链接库。但是,exec 是用动态链接库编译的。我尝试重新安装 gcc 和 g++ 但它没
我在将 libgcc 链接到静态链接 .so 时遇到问题 它仅在使用 -m64 链接 64 位模块时发生 Ubuntu 64 位 12.10 gcc 4.7 在 Ubuntu 64 位 12.04 g
我是一名优秀的程序员,十分优秀!