2017-11-27 3 views
1

저는 환경과 같은 임베디드 OS로 작업하고 있으므로 바이너리의 크기는 가능한 한 작아야합니다. 나는 실행 파일로 간단한 플랫 바이너리 파일을 사용하고 있었지만 지금은 ELF를 사용하려고한다. 난 그냥 어셈블리 코드를 사용하고 있지만 ld와 링크하고있다. 어셈블리 코드 :왜이 간단한 어셈블리 코드를 컴파일하고 ELF에 링크하면 플랫 바이너리보다 더 큰 크기가됩니까?

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 

그리고 마지막으로, 링커 스크립트 :

이 readelf 목록에 결과
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 
} 

:

[email protected]:~/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 프로그램 크기를 가능한 줄이려면 어떻게합니까?

참고로이 OS 환경에서는 재배치 또는 동적 코드가 없습니다. 그냥 플랫 프로그램 섹션을로드합니다.

+0

'.text' 정렬이 4k로 설정되어있는 것처럼 보입니다. – Jester

+0

프로그램 헤더 비트에 대해 파일 자체에서 4K로 정렬되어 있음을 알았지 만 LD에 @Jester를하지 말라고 말하지 않습니다. – Earlz

+0

4kb 정렬은 잠재적으로 입력 섹션에서 발생합니다. 오브젝트 파일을 처리하고 최종 실행 파일의 출력 섹션으로 전달합니다. '.text'와'.data' 라인에서 SUBALIGN 지시어를 사용하여이를 검증 할 수 있습니다. 그래서 이것은'.text phys : AT (phys) SUBALIGN (64)'와'.data : AT (scratch) SUBALIGN (64)'64를 사용할 수 있습니다. 잘). –

답변

2

"-n"("-nmagic"이라고도 함) 링커 옵션을 사용하여이 문제를 해결했습니다. 이것은 기본적으로 ld가 페이지 경계에서 프로그램 섹션을 정렬하는 것에 대해 걱정하지 않도록 지시합니다. 이것은 4K에서 약 700 (스트립 이후 400)에 이릅니다. 그리고 나서 그걸 약 150 바이트로 줄이기 위해 sstrip을 사용했습니다. 이것은이 유스 케이스에서 달성하고자하는 유형의 크기입니다.

관련 문제