本文介绍了为什么编译这个简单的汇编代码并链接到ELF会导致比平面二进制文件大得多的大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用类似嵌入式OS的环境,因此二进制文件的大小需要尽可能小.我一直在使用简单的平面二进制文件作为可执行文件,但是现在我正在尝试使用ELF.我只是在使用汇编代码,而是与ld链接.汇编代码:

I'm working with an embedded OS like environment, and so size of binaries needs to be as small as possible. I had been using simple flat binary files as an executable, but now I'm trying to use ELF. I'm just using assembly code, but linking with ld. Assembly code:

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列表的结果是

Which results in this readelf listing:

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.

As you can see, this should compile to 100 or 200 bytes at the maximum (and did when using flat binary format).. but for some reason this takes up over 4Kb.

如何在不使用汇编器手动构建ELF文件的情况下尽可能减小ELF程序的大小?

How can I reduce the ELF program size as much as possible short of building the ELF file manually in the assembler?

作为参考,在此OS环境中,没有重定位或动态代码.它只加载平面程序段.

For reference, in this OS environment there are no relocations or dynamic code. It just loads flat program sections.

推荐答案

我最终使用"-n"(也称为"-nmagic")链接器选项解决了这个问题.这基本上告诉ld不必担心在页面边界上对齐程序部分.这使我从4K上升到大约700(剥离后为400).然后,我使用了 strips 将其进一步减少到大约150个字节.这是我要为该用例实现的大小类型.

I ended up solving this by using the "-n" (also known as "-nmagic") linker option. This basically tells ld to not worry about aligning program sections on page boundaries. This got me from 4K to about 700 (400 after strip). And then I used sstrip to reduce that further to just about 150 bytes. This is the type of size I was looking to achieve for this use case.

这篇关于为什么编译这个简单的汇编代码并链接到ELF会导致比平面二进制文件大得多的大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-17 15:59