Why does compiling this simple assembly code and linking to ELF result in such a bigger size than flat binary?

我只是一个虾纸丫 提交于 2019-12-11 00:12:09

问题


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

Build commands:

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

And finally, linker script:

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
}

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.

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.

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

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


回答1:


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.



来源:https://stackoverflow.com/questions/47517571/why-does-compiling-this-simple-assembly-code-and-linking-to-elf-result-in-such-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!