linux zImage生成過程詳解

2021-05-14 09:49:14 字數 4251 閱讀 9149

核心編譯完成後會生成zimage核心映象檔案。關於bootloader載入zimage到核心,並且跳轉到zimage開始位址執行zimage的過程,相信大家都很容易理解。但對於zimage是如何解壓的過程,就不是那麼好理解了。本文將結合部分關鍵**,講解zimage的解壓過程。

先看看zimage的組成吧。在核心編譯完成後會在arch/arm/boot/下生成zimage。

在arch/armboot/makefile中:

$(obj)/zimage: $(obj)/compressed/vmlinux force

$(call if_changed,objcopy)

由此可見,zimage的是elf格式的arch/arm/boot/compressed/vmlinux二進位製化得到的

在arch/armboot/compressed/makefile中:

$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(head) $(obj)/piggy.o

$(addprefix $(obj)/, $(objs)) force

$(call if_changed,ld)

$(obj)/piggy.gz: $(obj)/../image force

$(call if_changed,gzip)

$(obj)/piggy.o: $(obj)/piggy.gz force

其中image是由核心頂層目錄下的vmlinux二進位製化後得到的。注意:arch/arm/boot/compressed/vmlinux是位置無關的,這個有助於理解後面的**。,鏈結選項中有個 –fpic引數:

extra_cflags := -fpic                               

總結一下zimage的組成,它是由乙個壓縮後的核心piggy.o,連線上一段初始化及解壓功能的**(head.o misc.o),組成的。

下面就要看核心的啟動了,那麼核心是從什麼地方開始執行的呢?這個當然要看lds檔案啦。zimage的生成經歷了兩次大的鏈結過程:一次是頂層vmlinux的生成,由arch/arm/boot/vmlinux.lds(這個lds檔案是由arch/arm/kernel/vmlinux.lds.s生成的)決定;另一次是arch/arm/boot/compressed/vmlinux的生成,是由arch/arm/boot/compressed/vmlinux.lds(這個lds檔案是由arch/arm/boot/compressed/vmlinux.lds.in生成的)決定。zimage的入口點應該由arch/arm/boot/compressed/vmlinux.lds決定。從中可以看出入口點為『_start』

output_arch(arm)

entry(_start)

sections

在arch/arm/boot/compressed/head.s中找到入口點.。

看看head.s會做些什麼樣的工作:

l     對於各種arm cpu的debug輸出設定,通過定義巨集來統一操作;l     設定kernel開始和結束位址,儲存architecture id;l     如果在arm2以上的cpu中,用的是普通使用者模式,則公升到超級使用者模式,然後關中斷l     分析lc0結構delta offset,判斷是否需要過載核心位址(r0存入偏移量,判斷r0是否為零)。l     需要過載核心位址,將r0的偏移量加到bss region和got table中的每一項。對於位置無關的**,程式是通過got表訪問全域性資料目標的,也就是說got表中中記錄的是全域性資料目標的絕對位址,所以其中的每一項也需要過載。l     清空bss堆疊空間r2-r3l     建立c程式執行需要的快取l     這時r2是快取的結束位址,r4是kernel的最後執行位址,r5是kernel境象檔案的開始位址

l     用檔案misc.c的函式decompress_kernel(),解壓核心於快取結束的地方(r2位址之後)。

可能大家看了上面的文字描述還是不清楚解壓的動態過程。還是先用圖表的方式描述下

**的搬運解壓過程。然後再針對中間的一些關鍵過程闡述。

假定zimage在記憶體中的初始位址為0x30008000(這個位址由bootloader決定,位置不固定)1、初始狀態

.text

0x30008000開始,包含piggydata段(即壓縮的核心段)

. got

. data

.bss

.stack

4k大小

2、head.s呼叫misc.c中的decompress_kernel剛解壓完核心後 

.text

0x30008000開始,包含piggydata段(即壓縮的核心段)

. got

. data

.bss

.stack

4k大小

解壓函式所需緩衝區

64k大小

解壓後的核心**

小於4m

3、此時會將head.s中的部分**重定位

.text

0x30008000開始,包含piggydata段(即壓縮的核心段)

. got

. data

.bss

.stack

4k大小

解壓函式所需緩衝區

64k大小

解壓後的核心**

小於4m

head.s中的部分重定位****

reloc_start至reloc_end

4、跳轉到重定位後的reloc_start處,由reloc_start至reloc_end的**複製解壓後的核心**到0x30008000處,並呼叫call_kernel跳轉到0x30008000處執行。

解壓後的核心

0x30008000開始

問題1:zimage是如何知道自己最後的執行位址是0x30008000的?問題2:呼叫decompress_kernel函式時,其4個引數是什麼值及物理含義?問題3:解壓函式是如何確定**中壓縮核心位置的? 

先回答第1個問題

這個位址的確定和makefile和鏈結指令碼有關,在arch/arm/makefile檔案中的textaddr-y  := 0xc0008000   這個是核心啟動的虛擬位址textaddr := $(textaddr-y)在arch/arm/mach-s3c2410/makefile.boot中zreladdr-y   := 0x30008000   這個就是zimage的執行位址了在arch/arm/boot/makefile檔案中zreladdr  := $(zreladdr-y)在arch/arm/boot/compressed/makefile檔案中zreladdr=$(zreladdr)在arch/arm/boot/compressed/makefile中有           .word   zreladdr    @ r4    核心就是用這種方式讓**知道最終執行的位置的 

接下來再回答第2個問題

decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,        int arch_id)l     output_start:指解壓後核心輸出的起始位置,此時它的值參考上面的圖表,緊接在解壓緩衝區後;l     free_mem_ptr_p:解壓函式需要的記憶體緩衝開始位址;l     ulg free_mem_ptr_end_p:解壓函式需要的記憶體緩衝結束位址,共64k;l     arch_id :architecture id,對於smdk2410這個值為193; 

最後回答第3個問題

首先看看piggy.o是如何生成的,在arch/arm/boot/compressed/makefie中    $(obj)/piggy.o: $(obj)/piggy.gz force                      piggy.o是由piggy.s生成的,咱們看看piggy.s的內容:.section .piggydata,#alloc

.globl   input_data

input_data:

.incbin  "arch/arm/boot/compressed/piggy.gz"

.globl   input_data_end

input_data_end:

再看看misc.c中decompress_kernel函式吧,它將呼叫gunzip()解壓核心。gunzip()在lib/inflate.c中定義,它將呼叫nextbyte(),進而呼叫get_byte()來獲取壓縮核心**。

資源生成的過程

資源的總入口 initializeresourcevariables mapjtbl jump table mmidatatype.h resource table 1.加到 resource base enum ifdef mmi anda dsm endif 這個巨集展開是這樣的 ap id,r...

WINCE核心生成過程

生成映像檔案nk.bin是平台建立過程的最後一步,也是配置windows ce的最終目標。makeimg.exe使用全部配置檔案把目標模組和檔案合併成乙個惟一的windows ce映像檔案nk.bin。圖1所示為nk.bin的生成過程。makeimg生成nk.bin的具體步驟 全並配置檔案 所有的....

arm linux 核心生成過程

1.依據arch arm kernel vmlinux.lds 生成linux核心原始碼根目錄下的vmlinux,這個vmlinux屬於未壓縮,帶除錯資訊 符號表的最初的核心,大小約23mb arm linux gnu ld el p no undefined x o vmlinux t arch ...