relocatable文件,即可重定向文件,這個文件是由編譯器彙編源文件(.c/.s)而成的。直接生成的重定向文件叫object file,經過封裝的重定向文件稱為library file。relocatable文件是一個中間的過渡文件,其本身也不能被ARM直接執行,需經過第二步轉換,即鏈接,所以這... ...
大家好,我是豹哥,獵豹的豹,犀利哥的哥。今天豹哥給大家講的是嵌入式開發里的relocatable文件(object, library)。
前三節課里,豹哥都是在給大家介紹嵌入式開發中的input文件。從今天這節課開始,豹哥就陸續為大家講output文件。上一節課project文件里講說到project文件是一個承前啟後的文件,今天豹哥就為大家講project生成的第一類output文件:relocatable文件。
文件關係:source文件 + project文件 -> relocatable文件
relocatable文件,即可重定向文件,這個文件是由編譯器彙編源文件(.c/.s)而成的。直接生成的重定向文件叫object file,經過封裝的重定向文件稱為library file。可重定向文件屬於ELF文件的分支,關於ELF文件的詳細解釋可見第六節課executable文件。
本文主角object file和library file,僅是一個中間的過渡文件,其本身也不能被ARM直接執行,需經過第二步轉換,即鏈接,所以這兩個文件都是鏈接器的輸入文件。讓我們來簡單分析一下這兩個文件。在開始分析之前我們先回到上一節課project文件的最後創建的demo工程上,編譯這個demo工程可以得到如下.o文件,這些文件全是object文件,每一個源文件都對應一個object文件,本文以task.o為例講解relocatable文件。
D:\myProject\bsp\builds\demo\Release\Obj\main.o
D:\myProject\bsp\builds\demo\Release\Obj\reset.o
D:\myProject\bsp\builds\demo\Release\Obj\startup.o
D:\myProject\bsp\builds\demo\Release\Obj\startup_MKL25Z4.o
D:\myProject\bsp\builds\demo\Release\Obj\system_MKL25Z4.o
D:\myProject\bsp\builds\demo\Release\Obj\task.o -o
一、解析object文件
task.o文件大小有11683bytes,而從源文件里看其僅包含4個變數和3個函數,可見更多的數據是記錄性數據。
1.1 獲得file header
c:\cygwin64\bin>x86_64-w64-mingw32-readelf.exe -h task.o
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: ARM
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 8283 (bytes into file)
Flags: 0x5000000, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 85
Section header string table index: 1
分析file header可知task.o是REL類型ELF文件,其一共含有85個section header,沒有program header。
1.2 獲得section header
c:\cygwin64\bin>x86_64-w64-mingw32-readelf.exe -S task.o
There are 85 section headers, starting at offset 0x205b:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000034 000000 00 0 0 0
[ 1] .shstrtab STRTAB 00000000 000034 0001eb 00 0 0 0
[ 2] .symtab SYMTAB 00000000 00021f 000350 10 3 45 0
[ 3] .strtab STRTAB 00000000 00056f 000248 00 0 0 0
[ 8] .bss NOBITS 00000000 000e1c 000004 00 WA 0 0 4
[ 9] .noinit NOBITS 00000000 000e1c 000004 00 WA 0 0 4
[10] .data PROGBITS 00000000 000e1c 000004 00 WA 0 0 4
[11] .bss NOBITS 00000000 000e20 000010 00 WA 0 0 4
[12] .text PROGBITS 00000000 000e20 000058 00 AX 0 0 4
[13] .textrw PROGBITS 00000000 000e78 000010 00 WAX 0 0 4
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
y (purecode), p (processor specific)
分析section header可知該task.o里的各個常見section(.bss, .noinit, .data, .text, .textrw)的大小,各個段的含義詳見第二節課linker文件。
1.3 獲得symbol list
c:\cygwin64\bin>x86_64-w64-mingw32-readelf.exe -s task.o
Symbol table '.symtab' contains 53 entries:
Num: Value Size Type Bind Vis Ndx Name
3: 00000000 16 OBJECT LOCAL DEFAULT 11 s_array
4: 00000000 4 OBJECT LOCAL DEFAULT 8 s_variable0
5: 00000000 4 OBJECT LOCAL DEFAULT 10 s_variable2
45: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_memcpy
46: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_memset
47: 00000000 0 FUNC GLOBAL DEFAULT UND free
48: 00000000 0 FUNC GLOBAL DEFAULT UND malloc
49: 0000000f 60 FUNC GLOBAL DEFAULT 12 heap_task
50: 00000000 4 OBJECT GLOBAL DEFAULT 9 n_variable1
51: 00000001 14 FUNC GLOBAL DEFAULT 12 normal_task
52: 00000001 16 FUNC GLOBAL DEFAULT 13 ram_task
分析symbol list可知我們在task.c里定義的函數和全局變數的信息,其中Value表明的是各symbol對象(函數/全局變數)在存儲器中的分配地址,由於object文件並沒有經過鏈接,所以此處地址信息是無效的(待分配的)。翻看到第六節課executable文件里2.2.4一節,便可看到這些symbol對象Value的值開始變得真實有效了。這就解釋了為什麼object文件是relocatable的。
二、關於library文件
本質上library文件跟object文件是一樣的,都是未經鏈接器鏈接的文件。library文件的應用場景是,在一些特殊場合,你不想把你的C源代碼開放給別人閱讀和自由修改,但是你又需要分享你的代碼給別人使用,怎麼解決這個問題?library文件就是解決這個問題的,可以藉助編譯器的選項(IAR下是Options->General Options->Output->Output file里選擇Library(預設是executable)),那麼添加進整個工程的所有源文件會被彙編封裝成一個.a文件(即library文件),這時候你只需要將該.a文件以及配套API頭文件分享給別人即可。別人只需要添加你的.a文件以及配套.h文件進他自己的工程,便可直接調用你的API。
至此,嵌入式開發里的relocatable文件(object, library)文件豹哥便介紹完畢了,掌聲在哪裡~~~