在x86_64 linux中重定位程序超过2GB的链接器错误?
我有一个用户程序,通常编译为在0x400460有一个入口点,我必须重新定位,以便在
Linux中加载的共享库的2GB内有一个入口点.例如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的输出,用于编译文本段低于2GB(在0x79990000)的二进制文件. 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地址空间开始.因此,动态链接器无法在运行时偏移重定位地址,因为重定位类型为R_X86_64_32. >所以我尝试用gcc -mcmodel = large flag编译我的代码,但我仍然得到相同的链接器错误.使用大型模型应该已经纠正了这个错误,但事实并非如此. (我正在使用x86_64 ubuntu机器.gcc versio 4.8.2) 解决方法
您应该首先了解x86_64的ABI有几个不同的“模型”:小型,内核,中型和大型.这些在GCC -mcmodel选项下描述:
http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86-64-Options.html
您所遇到的是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并在链接命令行上手动指定所有启动文件来实现此目的.可能值得提交针对glibc的错误报告,请求将x86_64 crt1.o转换为“大型模型”,以便它可以与未在32位范围内链接的主程序一起使用. 请注意,对于所有自己的代码,您可能还需要-mcmodel = large(或者可能是-fPIE可以工作),以使其链接并在高地址处正常工作.这可能会使它变得更大更慢.您可能想重新考虑为什么要这样做,以及您是否真的需要. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |