You can download from site:
預備知識,閱讀文章“as中常見僞指令.word .align .balign[lw] .macro .globl”
C源檔案到ELF可執行檔案的生成過程
1. 編譯器的預處理
2. C源代碼轉換為彙編代碼
3. 生成目标檔案
4. 将目标檔案連結為ELF可執行檔案
ELF檔案類型共有4種類型
1. 可重定位檔案relocatable file
執行file xx.o,其中xx表示編譯過程生成的目标檔案
傳回ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
2. 可執行檔案executable file
執行file /bin/sh
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
3. 共享目标檔案share object file
執行file /lib/libmemusage.so
/lib/libmemusage.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped
4. 核心轉儲檔案core dump file
執行file /proc/kcore
ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from '-3b3e-428f-91d0-1a730571'
編寫C代碼
現在通過舉例說明整個編譯過程,首先建立show.c和mian.c檔案,其中show.c檔案的内容如下
#include
void show()
{
printf ("this program is used to test ld\n");
}
mian.c的内容如下
extern void show();
int main()
{
show();
return 0;
}
C源代碼轉換為彙編代碼
用gcc加上-save-temps選項編譯完成以後,可以看到彙編檔案show.s内容如下
.file "show.c"
.section .rodata
.align 4
.LC0:
.string "this program is used to test ld"
.text
.globl show
.type show, @function
show:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $.LC0, (%esp)
call puts
leave
ret
.size show, .-show
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,"",@progbits
從彙編檔案show.s裡可以發現彙編檔案裡包含了很多的僞指令,其中align4表示16位元組對齊,globl是的show符号對ld可見,即全局的。所有彙編檔案.text section最後都會放在ELF檔案的.text section
生成目标檔案
對show.o進行反彙編(objdump –d show.o)
Disassembly of section .text:
00000000 :
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 18 sub $0x18,%esp
6: c7 04 24 00 00 00 00 movl $0x0,(%esp)
d: e8 fc ff ff ff call e
12: c9 leave
13: c3 ret
對main.o進行反彙編(objdump –d main.o)
Disassembly of section .text:
00000000 :
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: e8 fc ff ff ff call 7
b: b8 00 00 00 00 mov $0x0,%eax
10: 89 ec mov %ebp,%esp
12: 5d pop %ebp
13: c3 ret
而目标檔案的生成也很簡單,隻是把彙編檔案進行編譯為對應機器碼。該過程沒有按照僞指令進行對齊邊界,也沒有進行的位址修正,對需要修正的位址隻是在目前位址上+1.
将目标檔案連結為ELF可執行檔案
連結器最後将所有的目标檔案連結為ELF可執行檔案,對ELF檔案反彙編内容如下
080483e4 :
80483e4: 55 push %ebp
80483e5: 89 e5 mov %esp,%ebp
80483e7: 83 e4 f0 and $0xfffffff0,%esp
80483ea: e8 09 00 00 00 call 80483f8
80483ef: b8 00 00 00 00 mov $0x0,%eax
80483f4: 89 ec mov %ebp,%esp
80483f6: 5d pop %ebp
80483f7: c3 ret
080483f8 :
80483f8: 55 push %ebp
80483f9: 89 e5 mov %esp,%ebp
80483fb: 83 ec 18 sub $0x18,%esp
80483fe: c7 04 24 d0 84 04 08 movl $0x80484d0,(%esp)
8048405: e8 0e ff ff ff call 8048318
804840a: c9 leave
804840b: c3 ret
804840c: 90 nop
804840d: 90 nop
804840e: 90 nop
804840f: 90 nop
在連結器連結完成以後可以看出main函數調用show函數的位址和show函數對printf函數的位址都變成絕對位址,而且程式在最後加入了4條nop操作,使得以16位元組對齊。