在x86_64 Linux中重新部署一个2GB以上的程序的链接器错误?

我有一个用户程序,通常编译有一个入口点在0x400460 ,我不得不重新定位入口点在2GB的Linux内加载的共享库开始。 例如linux-vdso.so.1 => (0x00007fff109cd000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcd195e6000) /lib64/ld-linux-x86-64.so.2 (0x00007fcd199af000)

我正在使用gcc命令行参数-Wl,-Ttext=0x80000000来指定.text segemnt的开始地址。

问题是,当我给这个参数超过2GB的地址时,我得到一个链接器错误是:

 gcc test.c -ggdb -Wl,-Ttext=0x80000000 -o test1 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 10 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 1 has invalid symbol index 11 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 2 has invalid symbol index 2 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 3 has invalid symbol index 2 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 4 has invalid symbol index 10 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 5 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 6 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 7 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 8 has invalid symbol index 2 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 9 has invalid symbol index 2 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 10 has invalid symbol index 11 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 11 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 12 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 13 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 14 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 15 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 16 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 17 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 18 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 19 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 20 has invalid symbol index 20 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_line): relocation 0 has invalid symbol index 2 /usr/lib/x86_64-linux-gnu/crt1.o: In function `_start': (.text+0x12): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_fini' defined in .text section in /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS) /usr/lib/x86_64-linux-gnu/crt1.o: In function `_start': (.text+0x19): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_init' defined in .text section in /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS) /usr/lib/x86_64-linux-gnu/crt1.o: In function `_start': (.text+0x20): relocation truncated to fit: R_X86_64_32S against symbol `main' defined in .text section in /tmp/ccFshK69.o /var/services/homes/adabral/elider/gc/a1/lib/gcc/x86_64-unknown-linux- gnu/4.8.2/crtbegin.o: In function `deregister_tm_clones': crtstuff.c:(.text+0x8): relocation truncated to fit: R_X86_64_32S against `.tm_clone_table' /var/services/homes/adabral/elider/gc/a1/lib/gcc/x86_64-unknown-linux- gnu/4.8.2/crtbegin.o: In function `register_tm_clones': crtstuff.c:(.text+0x38): relocation truncated to fit: R_X86_64_32S against `.tm_clone_table' collect2: error: ld returned 1 exit status 

:就这个问题而言,在我经历了几个SO问题和论坛之后,我可以看出,其中一些部分仍然被映射到2GB低地址空间。

这是readelf -a的输出,它是用2GB0x79990000 )以下的文本段编译的二进制文件。

 Dynamic section at offset 0x190310 contains 24 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000000c (INIT) 0x4003f0 0x000000000000000d (FINI) 0x79990204 0x0000000000000019 (INIT_ARRAY) 0x79b902f8 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) 0x000000000000001a (FINI_ARRAY) 0x79b90300 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) 0x0000000000000004 (HASH) 0x400278 0x0000000000000005 (STRTAB) 0x400318 0x0000000000000006 (SYMTAB) 0x4002a0 0x000000000000000a (STRSZ) 72 (bytes) 0x000000000000000b (SYMENT) 24 (bytes) 0x0000000000000015 (DEBUG) 0x0 0x0000000000000003 (PLTGOT) 0x79b904e8 0x0000000000000002 (PLTRELSZ) 72 (bytes) 0x0000000000000014 (PLTREL) RELA 0x0000000000000017 (JMPREL) 0x4003a8 0x0000000000000007 (RELA) 0x400390 0x0000000000000008 (RELASZ) 24 (bytes) 0x0000000000000009 (RELAENT) 24 (bytes) 0x000000006ffffffe (VERNEED) 0x400370 0x000000006fffffff (VERNEEDNUM) 1 0x000000006ffffff0 (VERSYM) 0x400360 0x0000000000000000 (NULL) 0x0 

你可以看到, INIT和其他一些部分仍然从低2GB地址空间开始。 所以dynamic链接器在重定位types为R_X86_64_32时不能在运行时偏移重定位地址。

  • 所以我试着用gcc -mcmodel=large标志编译我的代码,但是我仍然得到相同的链接器错误。 使用large模型应该纠正了这个错误,但事实并非如此。

  • 我坚持在这一点上,任何帮助,高度赞赏。

(我正在使用x86_64 ubuntu机器。gcc版本4.8.2)谢谢

Solutions Collecting From Web of "在x86_64 Linux中重新部署一个2GB以上的程序的链接器错误?"

您应该首先了解x86_64的ABI有几个不同的“模型”:小型,内核,中型和大型。 这些在GCC -mcmodel选项下描述: http : -mcmodel

你所遇到的是crt1.o ,链接到每个负责获取初始ELF寄存器/堆栈状态并将它们传递到最终调用main的libc启动代码的程序中的启动代码似乎正在使用小模型。 你可以在这里看到:

 /usr/lib/x86_64-linux-gnu/crt1.o: In function `_start': (.text+0x20): relocation truncated to fit: R_X86_64_32S against symbol `main' defined in .text section in /tmp/ccFshK69.o 

发生了什么事情是, crt1.o重新定位了main的地址,只允许填入一个32位地址(注意:即使main是在共享库中定义的,而不是在可执行文件中,也会有在可执行文件中输入PLT,这个PLT条目的地址将成为重新定位的main官方地址。)

为了解决这个问题,你需要一个可以处理完整的64位地址的crt1.o 一种方法可能是通过使用Scrt1.o ,通常只用于PIE可执行文件,而不是crt1.o 您可能可以通过-nostartfiles来实现此-nostartfiles并手动指定链接命令行上的所有启动文件。 对于glibc,可能值得提交一个bug报告,要求将x86_64 crt1.o转换为“大型模式”,以便它能够与不在32位范围内链接的主程序一起使用。

请注意,您可能还需要使用-mcmodel=large (或者可能是-fPIE )才能使所有自己的代码在高地址上链接并正常工作。 这可能会使其变得更大更慢。 你可能想重新思考你为什么这样做,是否真的需要。