C 在x86_64 linux中将程序重新定位到2GB以上时发生链接器错误?

C 在x86_64 linux中将程序重新定位到2GB以上时发生链接器错误?,c,linux,gcc,linker,x86-64,C,Linux,Gcc,Linker,X86 64,我有一个用户程序,它通常编译为在0x400460处有一个入口点,我必须重新定位该入口点,以便在Linux中加载的共享库的2GB内有一个入口点。e、 g 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命令行参

我有一个用户程序,它通常编译为在
0x400460
处有一个入口点,我必须重新定位该入口点,以便在Linux中加载的共享库的
2GB
内有一个入口点。e、 g

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=0x8000000
来指定
.text
序列的起始地址

问题是,当我在这个参数中给出高于
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
地址空间

这是用
2GB
(位于
0x79990000
)下的文本段编译的二进制文件的
readelf-a
输出

您可以看到
INIT
和一些其他部分仍然从低
2GB
地址空间开始。因此,动态链接器无法在运行时偏移重新定位地址,因为重新定位类型是
R\u X86\u 64\u 32

  • 因此,我尝试使用
    gcc-mcmodel=large
    标志编译代码,但仍然收到相同的链接器错误。使用
    large
    模型本应纠正此错误,但事实并非如此

  • 我被困在这一点上,任何帮助都是非常感谢的


我正在使用x86_64 ubuntu。gcc版本4.8.2

您首先应该了解,用于x86_64的ABI有几种不同的“模型”:小型、内核、中型和大型。以下是GCC
-mcmodel
选项下的描述:

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

/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
,它通常只用于饼图可执行文件,而不是
crt1.o
。您可以通过
-nostartfiles
并在link命令行上手动指定所有开始文件来实现这一点。可能值得针对glibc提交一份错误报告,要求将x86_64
crt1.o
转换为“大型”,以便它与32位范围内未链接的主程序一起工作


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

“我必须重新定位,以便在Linux中加载的共享库的2GB范围内有一个入口点。例如”--绝对不能保证共享库将加载到您希望加载的位置(我预计加载地址在
echo 1>/proc/sys/vm/legacy_va_layout
之后会发生剧烈变化)。此外,你到底为什么想要在共享库的2GB范围内?@EmployeedRussian我正在做一个需要这个的学术项目。非常感谢你的回答。有没有可能用另一种方法,也就是说,我可以强制像libc.so和other这样的共享库在使用小mod时加载到最初的2GB地址空间el?再次感谢您。原因是什么?根据您的需要,我可能会有一个替代解决方案。实际上,我正在尝试以一种与当前不同的方式访问共享库函数(通过PLT和GOT表使用间接寻址)。您希望能够通过代码中的重新定位直接调用它(文本)段?如果您使用带有完整64位字段的大型模型进行重新定位,这可能会起作用。@abhi:为了记录在案,自此注释线程以来,现代gcc已经
gcc-fno plt
使用
调用[func@GOTPCREL]
采用RIP相对寻址模式,虽然不如
call rel32
好,但肯定比
mov r64、imm64
/
call reg
好,您可以从
-mcmodel=large
中获得!请参阅的底部,了解
-fno plt
(大多数答案都是关于PIE可执行文件的。)
/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