我正在使用类似嵌入式操作系统的环境,因此二进制文件的大小需要尽可能小。我一直在使用简单的平面二进制文件作为可执行文件,但现在我正在尝试使用 ELF。我只是使用汇编代码,但与 ld 链接。汇编代码:
CPU i386
BITS 32
SECTION .text progbits alloc exec nowrite
GLOBAL start
start:
mov eax, 0
add eax, 1
inc eax
mov eax, 0x12345678
mov dword [0x100000], eax
mov ebx, dword [0x100000]
mov eax, ebx
out 0xF3, al ;dump memory API call
out 0xF0, ax
cli
hlt
构建命令:
yasm -o testbench/test.o testbench/test.asm -f elf32
i386-elf-gcc -T testbench/linker.ld -o test.elf -ffreestanding -nostdlib testbench/test.o -Wl,--gc-sections -dead_strip -fdata-sections -ffunction-sections -Os -nostartfiles -nodefaultlibs
strip --strip-all test.elf
最后,链接器脚本:
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
phys = 0x1000;
scratch = 0x100000;
MEMORY
{
coderom (rx) : ORIGIN = phys, LENGTH = 128K
scratchram (!rx) : ORIGIN = scratch, LENGTH = 1024K
}
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text.start);
*(.text*)
*(.rodata)
. = ALIGN(4);
} > coderom
__text_end=.;
.data : AT(scratch)
{
data = .;
*(.data)
. = ALIGN(4);
} > scratchram
__data_end=.;
__binary_end = .;
.bss : AT(scratch + (bss - data))
{
bss = .;
*(.bss)
. = ALIGN(4);
} > scratchram
}
这导致了这个 readelf 列表:
earlz@earlz-ubdev:~/x86LibSC$ readelf -a test.elf
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x1000
Start of program headers: 52 (bytes into file)
Start of section headers: 4160 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 1
Size of section headers: 40 (bytes)
Number of section headers: 5
Section header string table index: 4
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00001000 001000 000024 00 AX 0 0 16
[ 2] .data PROGBITS 00100000 001024 000000 00 WA 0 0 1
[ 3] .bss NOBITS 00100000 000000 000000 00 WA 0 0 1
[ 4] .shstrtab STRTAB 00000000 001024 00001c 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x00001000 0x00001000 0x00024 0x00024 R E 0x1000
Section to Segment mapping:
Segment Sections...
00 .text
There is no dynamic section in this file.
There are no relocations in this file.
The decoding of unwind sections for machine type Intel 80386 is not currently supported.
No version information found in this file.
如您所见,这应该最多编译为 100 或 200 字节(使用平面二进制格式时也是如此)。但由于某种原因,这占用了超过 4Kb。
除了在汇编器中手动构建 ELF 文件外,如何尽可能地减小 ELF 程序的大小?
作为引用,在此操作系统环境中没有重定位或动态代码。它只是加载平面程序部分。
最佳答案
我最终通过使用“-n”(也称为“-nmagic”)链接器选项解决了这个问题。这基本上告诉 ld 不要担心在页面边界上对齐程序部分。这让我从 4K 到大约 700(剥离后 400)。然后我用了 sstrip将其进一步减少到大约 150 个字节。这是我希望为此用例实现的大小类型。
关于assembly - 为什么编译这个简单的汇编代码并链接到 ELF 会导致比平面二进制文件更大的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47517571/