这是一个链接问题,而不是组装问题。
如果您要求 GCC(或更好的 ld)显示带有 -Wl,--verbose 的链接脚本,您会找到该行
.got.plt : { *(.got.plt) *(.igot.plt) }
指示链接器获取所有.got.plt 部分,按照遇到的顺序。
通常,链接器会将通配符匹配的文件和部分按照在链接过程中出现的顺序放置。
来自here
由于您使用 CRT 进行编译,这意味着它自己的目标文件,您的目标文件在它之后。
我不知道这种排序是标准化的还是跨不同版本的 GCC 的任何东西,我认为它可以随时更改。
您应该能够确认将-v 和-Wl,-M 添加到GCC 的命令行;第一个将向您展示 GCC 如何调用链接器,对我来说是:
/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o test /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. /tmp/ccref9XH.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o
很难看出来,但是test.s 目标文件是/tmp/ccref9XH.o(在完整输出的上面几行组装)并且一些CRT 目标文件在它之前被传递给collect2。
第二个选项将显示输出和输入部分之间的映射:
.got.plt 0x0000000000601000 0x25
*(.got.plt)
.got.plt 0x0000000000601000 0x20 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o
0x0000000000601000 _GLOBAL_OFFSET_TABLE_
.got.plt 0x0000000000601020 0x5 /tmp/ccisjx2P.o
0x0000000000601024 main
显示crt1.o 的.got.plt 部分位于第一位(请注意,您将main 留在了.got.plt 部分中)。
我还没有找到一种令人满意的方法来克服这个问题。
一种可能性是复制链接描述文件并将.got.plt 定义更改为:
.got.plt : { *(.got.plt.pre) *(.got.plt) *(.igot.plt) }
然后您可以将您的数据放入.got.plt.pre(注意:未经测试)。
但这是可维护性的噩梦。
我正在尝试使用ld 中的--sort-section=name 将SORT 命令添加到链接器脚本中输入的每个通配符部分。
这应该根据“文件或部分名称”对齐部分。
经过几次尝试后,我查看了源代码,它实际上只是部分名称,所以在这里没有用。
我已恢复为--sort-section=alignment。
首先,文件test.s必须用gcc -c test.s -o test.o组装成一个目标文件。
这里的问题是使test.o 中的.plt.got 部分的对齐方式大于8(其他.plt.got 部分使用的对齐)。
我检查了objcopy,但什么也没找到,也许有人会找到合适的命令?
我亲自使用十六进制编辑器修补了test.o 文件,使该部分对齐为 32 字节。
然后调用gcc -Wl,--sort-section=alignment test.o -o test 会生成一个ELF,其中test.s 部分在其他部分之前。
然而,这是一个繁琐的解决方案,尽管人们可以轻松地开发一种工具来更改 ELF 部分的对齐方式,但我希望找到一个现有的工具。
很抱歉,以上都不是您问题的正确答案。