在Assembly中,如何在本节开头插入数据(或代码或符号)?

时间:2018-11-24 09:18:55

标签: assembly x86 binary compiler-construction elf

我想在特定部分的开头插入一些数据(或代码或符号)。
假设在<.got>节的开头插入数据0x11223344

# gcc -o test test.s
.global main

.section .got.plt
.byte 0x11, 0x22, 0x33, 0x44

main:
 nop

但是,正如您所见,
编译后,数据将附加到<.got.plt>的 end 处。

Disassembly of section .got.plt:

080495dc <_GLOBAL_OFFSET_TABLE_>:
 80495dc:   f0 94                   lock xchg %eax,%esp
 80495de:   04 08                   add    $0x8,%al
    ...
 80495e8:   86 82 04 08 11 22       xchg   %al,0x22110804(%edx)
 80495ee:   33                      .byte 0x33
 80495ef:   44                      inc    %esp


问题:

我可以在本节的开头插入数据(或代码或符号)吗?
..是否有任何编译选项或类似汇编程序指令的内容?

1 个答案:

答案 0 :(得分:1)

这是一个链接问题,而不是一个装配问题。

如果您要求GCC(或更好的ld)显示带有-Wl,--verbose的链接脚本,您会找到一行

.got.plt        : { *(.got.plt)  *(.igot.plt) }

指示链接程序按照遇到的顺序 提取所有.got.plt部分。

  

通常,链接器将按通配符在链接期间显示的顺序放置文件和节。

来自here

由于您正在使用CRT进行编译,这意味着它具有自己的目标文件,因此您的目标文件将紧随其后。
我不知道此订购是标准化的还是在GCC的不同版本中进行了订购,我认为可以随时更改。

您应该能够确认在GCC的命令行中添加了-v-Wl,-M;第一个将向您展示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的{​​{1}}部分(请注意,您在.got.plt部分保留了main)。


我没有找到令人满意的方法来克服这个问题。
一种可能是复制链接程序脚本,并将.got.plt定义更改为以下内容:

.got.plt

然后您可以将数据放入.got.plt : { *(.got.plt.pre) *(.got.plt) *(.igot.plt) } 中(注意:未经测试)。
但这是可维护性的噩梦。

我正在尝试使用.got.plt.pre中的--sort-section=name,将ld命令添加到链接描述文件中输入的每个通配符节中。
这应该根据“ 文件或节名称”对齐节。
经过几次尝试,我查看了源代码,它实际上只是部分名称,因此在这里没有用。

我已恢复为SORT
首先,必须使用--sort-section=alignment将文件test.s组装成目标文件。
这里的问题是使gcc -c test.s -o test.o中的.plt.got部分的对齐方式大于8(其他test.o部分使用的对齐方式)。
我检查了.plt.got,但是什么也没找到,也许有人会找到合适的命令?
我已经用十六进制编辑器为objcopy文件打了补丁,使该部分对齐了32个字节。
然后调用test.o会产生一个ELF,其中gcc -Wl,--sort-section=alignment test.o -o test节位于其他节之前。

尽管这是一个麻烦的解决方案,尽管可以轻松开发一种工具来更改ELF截面对齐方式,但我希望找到一个现有的工具。

很抱歉,以上都不是您的问题的正确答案。