如何在 GNU 中指定 ELF 部分对齐方式?

How to specify ELF section alignment in GNU as?

我正在尝试将 GNU as 用作通用 assembler,其用法与 nasm 类似。我制作了这样的模板源:

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

然后我 运行 这样的 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(Ubuntu Precise 中的 as.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 assembler 中明确指定 ELF 目标的部分对齐?

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

linker.ld

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

此脚本利用 SUBALIGN 指令覆盖 .text 部分在输入对象中的对齐方式。从 GNU Linker 文档来看,它具有以下效果:

3.6.8.4 Forced Input Alignment

You can force input section alignment within an output section by using SUBALIGN. The value specified overrides any alignment given by input sections, whether larger or smaller.

然后使用:

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

当链接器脚本中的部分未处理目标文件中的部分时,仍会发出输入部分。所有未处理的输入部分将按照链接器遇到它们的顺序在最后输出。