I'm trying to use GNU as
as a generic assembler similar in use as nasm
. I make a template source like this:
.section .text
.globl _start
.intel_syntax noprefix
_start:
call 0xb77431c0 # the instruction I want to assemble
And then I run the assemble command like this:
as --32 -o test.o test.s
ld -m elf_i386 -Ttext 0xb77431d9 --oformat binary -o test.bin test.o
All works well with binutils 2.24. But it appears that as
from binutils 2.22 (the one in Ubuntu Precise) aligns .text
section to the 4-byte boundary, thus instead of the expected disassembly I get wrong results:
# 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
The problem is in the as
command (i.e. not ld
): readelf -S
gives me the following for results of as
2.22:
$ readelf -S test.o | grep ' \.text'
[ 1] .text PROGBITS 00000000 000034 000005 00 AX 0 0 4
And for 2.24 I have
$ readelf -S test.o | grep ' \.text'
[ 1] .text PROGBITS 00000000 000034 000005 00 AX 0 0 1
So the problem is indeed alignment of .text
section. I've tried placing .align 0
and .align 1
in various places in the source, but it didn't change the output.
So my question now: how to explicitly specify section alignment for ELF target in GNU assembler?
Likely the default linker script LD is causing some kind of forced alignment. I'd create a basic linker script with the origin point, and tell it which sections you want (specifying the alignment), and in what order sections will appear.
linker.ld
SECTIONS
{
. = 0xb77431d9;
.text . : SUBALIGN(0)
{
*(.text)
}
}
This script utilizes the SUBALIGN directive to override the alignment of the .text
section as it appears in the input object. From the GNU Linker documentation it has this effect:
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.
Then use:
as --32 -o test.o test.s
ld -T linker.ld -m elf_i386 --oformat binary -o test.bin test.o
The output I get here is:
ndisasm -b 32 -o 0xb77431d9 test.bin
B77431D9 E8E2FFFFFF call dword 0xb77431c0
When a section in an object file(s) doesn't get processed by the sections in the linker script, the input sections will still be emitted. All unprocessed input sections will be output at the end in the order they were encountered by the linker.