2008年1月5日 星期六

GNU gcc and ld

由於之前常常使用 makefile 去產生執行檔,但往往很多 makefile 都是從其他已經寫好的範例複製過來的,常常會忘記基本的 gcc 與 ld 的使用,甚至要拿來幫助 debug 的時候都忘記指令要怎麼下了,所以寫下這個筆記,以後要找比較方便。

寫程式有時候想瞭解某部份程式碼是否有問題,但卻礙於當程式編譯後,不知道確切的執行位址,要 debug 的時候就麻煩許多。而這時候最好就是拆解成 asm code 並同時產生 program map file 來尋找相對應的地方。這樣的情況在 embedded system 中更容易遇到,因需要定義哪邊的記憶體位置可以拿來使用,而 program (通常是 startup code)通常會被載入某特定區域,所以會在 linking 時做給予位址的動作,此時會有一個 linker script 來作為 mapping 的依據。 當然這個 script 也是事先寫好的。

參考 test.ld 如下:

ENTRY (main)

MEMORY
{
ram : ORIGIN = 0x00200000, LENGTH = 32M
rom : ORIGIN = 0x60000000, LENGTH = 16M
}

SECTIONS
{
data :
{
_DataStart = . ;
*(.data)
_DataEnd = . ;
} >ram

bss :
{
_BssStart = . ;
*(.bss)
_BssEnd = . ;
} >ram

text :
{
*(.text)
} >ram
}


用gcc編譯時:

#產生 test.o(object code), test.s(asm code)
# gcc -c -S -Wall test.c


會有下列檔案:
test.c
test.o
test.s


#手動連結,產生 t.out 執行檔,產生 test.map(map file),依照 test.ld(linker script),並連結標準函式庫-lc(libc)

# ld -o t.out -Map test.map -T test.ld -lc


這樣就可以完成 debug 所需要的資訊,而如果對看 asm code 覺得吃力,可以在想要看的程式馬前後插入下列程式碼(在 C 中):

__asm__("nop");
...
code...
...
__asm__("nop");


這樣就可以明確知道要 debug 的源碼到底位於那一段記憶體區段,甚至可以知道在編譯時最佳化會不會影響到程式的運作。


PS.太久沒寫code,很多東西快忘光了趕快紀錄一下。XD

參考連結:

沒有留言: