2.交叉工具链
2.交叉工具鏈
一、交叉工具鏈:
交叉工具鏈,其實他有兩個含義,一個就是交叉工具,所謂的交叉工具就是運行的環境和編譯的環境不是在一體的。就像我們現在,編譯裸機程序是在pc機上面執行的。可我們運行程序是在開發板。鏈,就是很多的意思,就是一個工具的集合。在我們前面配置arm-linux-gcc的工具中。在/usr/local/arm/4.3.2/bin的目錄下有很多編譯工具。例如圖1-1:
圖1.-1 交叉工具鏈
下面我們來寫一個簡單的程序,用這些工具編譯。
Hello.c:
#include <stdio.h>
void main(){
????printf("hello fish!\n");
}
這是一個簡單的hello程序。首先我們先用我們熟悉的gcc編譯并執行。圖1-2:
圖1-2
我們看到程序正常運行。輸出了內容。
接下來我們用剛安裝的交叉工具來編譯運行。圖1-3:
圖1-3
我們看見程序出錯了。提示的信息是不能運行的二進制文件。這就奇怪了。這是為啥呢?其實呢。我在前面已經提過了,arm-linux-*工具,編譯的程序是在開發板運行的。其實我們可以通過:file 文件名.來查看該應用程序運行的平臺。圖1-4:
圖1-4
可以看到信息,hello是gcc編譯生成的是運行在x86架構的,hello1是arm-linux-gcc編譯生成的是運行在ARM架構的。
接下來我們把hello1拷貝到開發板運行看看。
我已在開發板燒寫好了linux系統,通過u盤,把hello1拷貝到開發板。然后插入開發板的usb口。在終端可以看見提示信息,這是因為我們的linux帶有usb驅動,當我們的usb插進去的時候,它檢測到了usb,加載好了驅動。現在我們進入u盤,運行hello1程序。圖1-5.這時仍然提示錯誤。如下:
?
?
這是為啥呢?這是我們的開發板缺少程序運行時需要的動態庫,因為我剛才編譯的時候沒有加-static屬性。加上-static屬性重新編譯。圖1-6:
圖1-6
可以看到,這次加入了-static條件,編譯生成的hello2程序比hello1大了許多,就是因為把運行需要的庫文件都靜態鏈接進來了。同樣拷貝到u盤,可以看到順利運行。圖1-7:
圖1-7
二、交叉工具鏈的詳述:
1.arm-linux-gcc編譯器:
前面,可以看到gcc和arm-linux-gcc工具的編譯條件都是一樣的。可為什么編譯出來的應用程序會運行在不同的平臺呢?這是因為,他們兩個在編譯的時候引用的頭文件不同。傳統的gcc是默認去/usr/include尋找它需要的頭文件。圖1-8:
圖1-8頭文件
而arm-linux-gcc尋找的頭文件的目錄不同。首先使用arm-linux-gcc –help查看它的使用:圖1-9:
圖1-9
注意到參數-print-search-dirs就是顯示尋找頭文件的參數目錄。加上該參數得到一下信息圖1-10:
圖1-10
從上面的顯示看到arm-linux-gcc默認是到我們安裝arm-linux-gcc的目錄去找頭文件的。
?
?
2.arm-linux-ld:
arm-linux-ld是鏈接器,下面介紹它的使用。
首先先用arm-linux-gcc生成中間文件.o文件。圖2-1:
arm-linux-gcc -g -c led.S
圖2-1
在上面的參數中-g表示可以用gdb來調試信息,-c是只編譯不鏈接。最后生成led.o中間文件。接下來就是使用arm-linux-ld把該文件鏈接成elf文件:圖2-2:
arm-linux-ld -Tled.lds -o led.elf led.o
圖2-2
上面語句的意思是利用arm-linux-ld鏈接器,按照-T指定的鏈接器腳本,把生成的led.o(如果有多個.o文件,在后面繼續加上),鏈接成led.elf文件。
?
3.arm-linux-readelf:
利用該工具可以查看生成的.elf文件的內容:
執行:arm-linux-readelf -a led.elf。-a參數是all的意思,表示查看所有信息:圖2-3:
圖2-3
從上面看到elf文件有一個固定的頭:ELF Header:然后:
Data: 2's complement, little endian
是表示他是運行在小端處理器的。
Machine: ARM
是表示他是運行在ARM平臺的。
所以當運行一個程序出錯的時候,當檢查完語法沒問題,仍然不能運行的時候,就應該用readelf查看一下這些信息是否符合。如果上面的兩種檢查完了之后還是不能運行。接下來就是查看需要的庫是否存在。使用的命令:
arm-linux-readelf -d hello
運行結果:圖2-4:
圖2-4
上面顯示了該hello應用程序需要的庫是libc.so.6.如果沒有該庫,該程序運行不了。
?
?
?
?
4.arm-linux-objdump:
ARM反匯編器。
上面已經使用arm-linux-gcc編譯產生了可執行文件hello2.現在對它進行反匯編。命令:
arm-linux-objdump -D -S hello2 >mydump
該命令的意思是將hello2可執行程序反匯編,輸出到mydump文件。執行之后會在該目錄下產生一個mydump文件:圖2-5:
打開可以看到對應的匯編代碼:
但是,都是匯編代碼,看起來還是非常困難。可以在編譯的時候加上-g調試信息的參數,這樣反匯編之后會有部分的c代碼存在。這樣可以讓我們更加容易看懂程序。
圖2-5
可以看到加上-g編譯,反匯編后,在匯編代碼里居然有c代碼出現。在上面的代碼中printf("hello fish!\n");的匯編實現就是它下面兩行。源代碼:
5.最后一個是文件格式轉換工具:arm-linux-objcopy:
從上面的操作知道,匯編代碼通過arm-linux-gcc -g -c led.S,把一個匯編文件轉化為一個led.o文件,接著使用:arm-linux-ld -Tled.lds -o led.elf led.o,把led.o利用led.lds腳本,鏈接成一個led.elf文件。但是elf文件無法在板子運行,必須轉化為.bin格式的二進制文件。這就是arm-linux-objcopy的功能:
arm-linux-objcopy -O binary led.elf led.bin
圖2-6:
圖2-6
?
轉載于:https://www.cnblogs.com/FORFISH/p/5188679.html
總結
- 上一篇: 【PL/SQL】--导出oracle单表
- 下一篇: 我的新设计