煩惱著要開始上班了
菜鳥人生 Start?[Y/N]
> N
今天還沒進入正題
因為我們需要先簡單了解編譯流程
這樣才知道為什麼昨天的執行檔沒有拔掉symbol
到底編譯器做了哪些事, 實際上分成哪幾個stage
我們寫好一個C code, 丟給compiler
現在的編譯器都會直接做好每個流程, 所以其實可以每個階段分開做.
之前在LLVM寫過簡單的Pass, 目的就是在C code產出asm code之後可以經過我們自己的Pass來做優化
首先我們先看整個流程圖
reference: 圖片來源
我們寫的C code一定會include到header檔, 除非是人中之龍. 什麼code都要自己手刻才完美的例外.
這裡會經過Preprocessor, 目的是處理包含巨集(define)的擴展, 包含include哪些. 再丟給compiler把需要的檔案編譯成asm code(.s file)
$ gcc --help
...
-S Compile only; do not assemble or link
$ gcc -S hello.c
$ file hello.s
hello.s: assembler source, ASCII text
在這步驟我們可以使用-S flag單純編譯C code->ASM 而不會進行組譯和link
剛剛我們產生了一個asm file, 稍微看看內容可以看到很像挖到古埃及文物一樣的文字
接下來我們會把這個檔案餵給assembler進行組譯成object file;
$ gcc -c hello.s
$ file hello.o
hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
如果執行檔或專案很大就會有很多的object file要linking
假設我們自己有一個main()的hello.o 跟一個類似handler形式的world.o
$ gcc -o hello_world hello.o world.o
$ file hello_world
hello_world: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=d7706b2b9613194ec27473ff5b772d770d0058fe, not stripped
可以看一下main跟lib兩個function都被併在同一個執行檔上
另外一個點是我們產出來的ELF file沒有經過strip, 所以我們還可以從symbol table抓一些資訊, 不管是debugger用還是其他靜態工具, 一旦經過strip之後就會很難判讀與追蹤代碼
執行檔一般只會躺在檔案系統上, 如果沒有執行與載入, 他就只是二進制文件而不會是程序.
執行時會由loader加載, 查找每一個section到對應的記憶體位址上, 需要重定位的擺好之後回填正確的位址, 函式庫則會依據是否為動態連結的優化方式, 若為動態連結則會找到已經躺在記憶體上的共享函式庫並且回填已知的位址
參考圖片:
謝謝大家
已經被月餅砸到咪咪貓貓還活下來的我