如何在 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 -S
为 as
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
当链接器脚本中的部分未处理目标文件中的部分时,仍会发出输入部分。所有未处理的输入部分将按照链接器遇到它们的顺序在最后输出。
我正在尝试将 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 -S
为 as
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
当链接器脚本中的部分未处理目标文件中的部分时,仍会发出输入部分。所有未处理的输入部分将按照链接器遇到它们的顺序在最后输出。