靜態鏈接學習之 ELF 文件 DIY
阿新 • • 發佈:2019-05-07
\n sin csdn tin symbol off -m 需要 自帶
目的
編寫一個最小的 ELF 程序,來加強對 ELF 文件格式的掌握和理解。(參考:《程序員的自我修養》一書)
源代碼
這裏采用 GCC 內置匯編代碼的編寫來避免 libc 中自帶的庫函數代碼。
- 匯編代碼采用 AT&T 格式
char *str="H3ll0\n"; void print(){ asm( "movl $6,%%edx \n\t" "movl %0,%%ecx \n\t" "movl $0,%%ebx \n\t" "movl $4,%%eax \n\t" "int $0x80 \n\t" ::"r"(str):"edx","ecx","ebx" ); } void exit(){ asm( "movl $42,%ebx \n\t" "movl $1,%eax \n\t" "int $0x80 \n\t" ); } void nomain(){ print(); exit(); }
這裏采用系統調用號來進行系統調用。
參考:http://syscalls.kernelgrok.com/
編譯
這裏需要編譯成 32 位的程序,在 64 位機器下需要使用下面的命令:
gcc -c -m32 -fno-builtin tiny.c
ld -m elf_i386 -static -e nomain -o tiny tiny.o
參考:https://blog.csdn.net/neuq_jtxw007/article/details/78112672
執行、查看大小
1112 個字節。還可以繼續削減他的大小。
自定義程序段
先查看他有哪些段,再決定去掉哪些無用的段。
[email protected]:~/testelf$ readelf -S ./tiny There are 9 section headers, starting at offset 0x2f0: 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 08048094 000094 000042 00 AX 0 0 1 [ 2] .rodata PROGBITS 080480d6 0000d6 000007 00 A 0 0 1 [ 3] .eh_frame PROGBITS 080480e0 0000e0 00007c 00 A 0 0 4 [ 4] .data PROGBITS 0804915c 00015c 000004 00 WA 0 0 4 [ 5] .comment PROGBITS 00000000 000160 000035 01 MS 0 0 1 [ 6] .shstrtab STRTAB 00000000 0002ae 000042 00 0 0 1 [ 7] .symtab SYMTAB 00000000 000198 0000e0 10 8 7 4 [ 8] .strtab STRTAB 00000000 000278 000036 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)
9 個段,首先 text 、rodata、data
這三個段可能是需要的,我們可以把他合成為一個段(代碼和數據混合),這樣就可以縮減描述各自屬性段的字節大小。eh_frame
和 comment
可以直接去除。
自定義 ld 腳本
通過自定義 ld 腳本的方法,來控制 ld 鏈接器的行為。
腳本如下:
ENTRY(nomain) SECTIONS{ . = 0x8048000+SIZEOF_HEADERS; tinytext : { *(.text) *(.data) *(.nodata) } /DISCARD/ : { *(.comment) *(.eh_frame)} }
編譯
[email protected]:~/testelf$ gcc -m32 -c ./tiny.c -fno-builtin -o tiny.o
[email protected]:~/testelf$ ld -static -m elf_i386 -T tiny.lds ./tiny.o -o tiny
運行之後還是正常的。
查看段信息,這是被合並成了一個段 tinytext
,權限是 WAX。
[email protected]:~/testelf$ readelf -S tiny
There are 6 section headers, starting at offset 0x190:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .rodata PROGBITS 08048074 000074 000007 00 A 0 0 1
[ 2] tinytext PROGBITS 0804807c 00007c 000048 00 WAX 0 0 4
[ 3] .shstrtab STRTAB 00000000 000162 00002c 00 0 0 1
[ 4] .symtab SYMTAB 00000000 0000c4 000080 10 5 4 4
[ 5] .strtab STRTAB 00000000 000144 00001e 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)
查看大小
640 個字節,還可以使用 strip 來去除 symbol 信息。
[email protected]:~/testelf$ ls -al ./tiny
-rwxrwxr-x 1 nick nick 640 5月 7 16:40 ./tiny
這裏就只有 384 字節。
[email protected]:~/testelf$ strip tiny
[email protected]:~/testelf$ ls -al ./tiny
-rwxrwxr-x 1 nick nick 384 5月 7 16:45 ./tiny
應該還能再削減大小,先填坑。。
靜態鏈接學習之 ELF 文件 DIY