如何在GNU中指定ELF节对齐?

时间:2016-04-30 14:21:26

标签: assembly elf memory-alignment gas

我正在尝试将GNU as用作与nasm类似的通用汇编程序。我制作了这样的模板源:

.section .text
.globl _start
.intel_syntax noprefix
_start:
call 0xb77431c0 # the instruction I want to assemble

然后我像这样运行汇编命令:

as --32 -o test.o test.s
ld -m elf_i386 -Ttext 0xb77431d9 --oformat binary -o test.bin test.o

一切都适用于binutils 2.24。但似乎来自binutils 2.22的as(Ubuntu Precise中的那个)将.text部分与4字节边界对齐,因此不是预期的反汇编我得到错误的结果:

 # expected and working in binutils 2.24
$ ndisasm -b 32 -o 0xb77431d9 test.bin
B77431D9  E8E2FFFFFF        call dword 0xb77431c0

 # actual in binutils 2.22
$ ndisasm -b 32 -o 0xb77431d9 test.bin
B77431D9  90                nop
B77431DA  90                nop
B77431DB  90                nop
B77431DC  E8DFFFFFFF        call dword 0xb77431c0

问题出在as命令中(即不是ld):readelf -Sas 2.22的结果提供了以下内容:

$ readelf -S test.o | grep ' \.text'
  [ 1] .text             PROGBITS        00000000 000034 000005 00  AX  0   0  4

对于2.24我有

$ readelf -S test.o | grep ' \.text'
  [ 1] .text             PROGBITS        00000000 000034 000005 00  AX  0   0  1

所以问题确实是.text部分的对齐。我尝试在源中的不同位置放置.align 0.align 1,但它没有更改输出。

现在我的问题:如何在GNU汇编程序中明确指定ELF目标的节对齐?

2 个答案:

答案 0 :(得分:2)

可能默认的链接描述文件 LD 会导致某种强制对齐。我使用原点创建一个基本的链接描述文件,并告诉它你想要哪些部分(指定对齐方式),以及将出现的部分顺序。

<强> linker.ld

SECTIONS
{
    . = 0xb77431d9;
    .text . : SUBALIGN(0)
    {
        *(.text)
    }
}

此脚本使用SUBALIGN指令覆盖输出对象中显示的.text部分的对齐方式。从GNU Linker文档中可以看出这种效果:

  

3.6.8.4强制输入对齐

     
    

您可以使用SUBALIGN强制输出节中的输入节对齐。该     指定的值将覆盖输入节给出的任何对齐,无论是更大还是更小。

  

然后使用:

as --32 -o test.o test.s
ld -T linker.ld -m elf_i386 --oformat binary -o test.bin test.o

我得到的输出是:

ndisasm -b 32 -o 0xb77431d9 test.bin
B77431D9  E8E2FFFFFF        call dword 0xb77431c0

如果目标文件中的某个部分未被链接描述文件中的部分处理,则仍会发出输入部分。所有未处理的输入节将按照链接器遇到的顺序在末尾输出。

答案 1 :(得分:1)

answer by Michael Petch (v3)的启发,我找到了一种方法,使工作的链接描述文件能够使输出部分对齐:

SECTIONS
{
    . = 0xb77431d9;
    .text . : SUBALIGN(0)
    {
        *(.text)
    }
}

现在我有以下结果:

$ as --32 -o test.o test.s
$ ld -m elf_i386 -T linker.ld --oformat binary -o test.bin test.o
$ ndisasm -b 32 -o 0xb77431d9 test.bin
B77431D9  E8E2FFFFFF        call dword 0xb77431c0

这正是所需的输出,具有正确的调用目标,没有无关的对齐。