六、u-boot 啟動流程---u-boot.lds


6.1 u-boot.lds  鏈接腳本分析

  uboot 編譯出來的第一個鏈接腳本就是執行 u-boot.lds 鏈接腳本,去掉里面無用的和沒有定義的,進行分析。

 1 /* 配置頭文件,自動生成的,包含芯片SOC 相關的頭文件 */  2 #include <config.h>  3 /* 主要是做一些 32位 和64 位的適配定義 */  4 #include <asm/psci.h>  5 /* 輸出格式為 elf32-littlearm, */  6 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")  7 OUTPUT_ARCH(arm) /* 輸出架構為 ARM */  8 /* 用來指定整個程序的入口地址,所謂入口地址就是整個程序的開頭地址,可以認為就是整個程序的第一句指令。有點像C語言中的main。 */  9 ENTRY(_start) /* _start 就是匯編的起始函數 */  10 /* SECTIONS 就是整個鏈接腳本的指定 */  11 SECTIONS  12 {  13 /* 指定程序的鏈接地址有2種方法:一種是在Makefile中ld的flags用-Ttext 0x20000000來指定;  14  第二種是在鏈接腳本的SECTIONS開頭用.=0x20000000來指定。  15  兩種都可以實現相同效果。這兩種技巧是可以共同配合使用的,也就是說既在鏈接腳本中指定也在ld flags中用-Ttext來指定。兩個都指定以后以-Ttext指定的為准。  16  uboot的最終鏈接起始地址就是在Makefile中用-Ttext 來指定的,注意 TEXT_BASE 變量。最終來源是 Makefile 中配置對應的命令中,在make xxx_config時得到的。  17  若沒有配置,則由此處指定*/  18 . = 0x00000000;  19  20 . = ALIGN(4); /* 4字節對齊 */  21  22 /* 代碼段 */  23 /* 在代碼段中,必須注意文件的排列順序,這些順序會影響編譯的時候這些 .o 文件在生成的u-boot.bin 中的排列順序 */  24 /* 指定必須放在前面部分的那些文件就是那些必須安排在前4KB內的文件,這些文件中的函數在前4KB會被調用。在后面第二部分(4KB之后)中調用的程序,前后順序就無所謂了。 */  25  .text :  26  {  27 /* 映像文件賦值起始地址,它在文件 arch/arm/lib/sections.c 中定義:  28  * char __image_copy_start[0] __attribute__((section(".__image_copy_start")));*/  29 *(.__image_copy_start)  30 /* arch/arm/lib/vectors.S 里有一句:.section ".vectors" */  31 /* 這里的 vectors 是讓 vector.S 鏈接的二進制文件的開頭部分 */  32 *(.vectors)  33 CPUDIR/start.o (.text*) /* 執行 start.S */  34 *(.text*) /* 其他代碼 */  35  }  36  37 . = ALIGN(4);  38 .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } /* 只讀數據段 */  39  40 . = ALIGN(4);  41 .data : { /* 普通數據段,即可讀寫數據段 */  42 *(.data*)  43  }  44  45 . = ALIGN(4);  46  47 . = .;  48  49 /* 在u-boot的linker_list.h中通過宏定義,讓編譯器在編譯階段生成了一些順序鏈表.u_boot_list*,鏈接階段順序存放到這個.u_boot_list節中。 */  50 /* u-boot啟動過程中,會從這個節讀取模塊驅動,命令行支持的命令等。 */  51 . = ALIGN(4);  52  .u_boot_list : {  53 KEEP(*(SORT(.u_boot_list*)));  54  }  55  56 . = ALIGN(4);  57  58 /* UEFI 段 */  59  .__efi_runtime_start : {  60 *(.__efi_runtime_start)  61  }  62  63  .efi_runtime : {  64 *(efi_runtime_text)  65 *(efi_runtime_data)  66  }  67  68  .__efi_runtime_stop : {  69 *(.__efi_runtime_stop)  70  }  71  72  .efi_runtime_rel_start :  73  {  74 *(.__efi_runtime_rel_start)  75  }  76  77  .efi_runtime_rel : {  78 *(.relefi_runtime_text)  79 *(.relefi_runtime_data)  80  }  81  82  .efi_runtime_rel_stop :  83  {  84 *(.__efi_runtime_rel_stop)  85  }  86 /* UEFI 段結束地方 */  87  88 . = ALIGN(4);  89  90  .image_copy_end :  91  {  92 *(.__image_copy_end)  93  }  94  95 /* .rel_dyn* 段 */  96 /* .rel_dyn_start,.rel.dyn和.rel_dyn_end提供了程序的重定位支持 */  97 /* 重定位:  98      在老的uboot中,如果我們想要uboot啟動后把自己拷貝到內存中的某個地方,只要把要拷貝的地址寫給TEXT_BASE即可,  99      然后boot啟動后就會把自己拷貝到TEXT_BASE內的地址處運行,在拷貝之前的代碼都是相對的,不能出現絕對的跳轉,否則會跑飛。 100      在新版的uboot里,TEXT_BASE的含義改變了。它表示用戶要把這段代碼加載到哪里,通常是通過串口等工具。 101      然后搬移的時候由uboot自己計算一個地址來進行搬移。 102      新版的uboot采用了動態鏈接技術,在lds文件中有__rel_dyn_start和__rel_dyn_end,這兩個符號之間的區域存放着動態鏈接符號, 103      只要給這里面的符號加上一定的偏移,拷貝到內存中代碼的后面相應的位置處,就可以在絕對跳轉中找到正確的函數。*/ 104  .rel_dyn_start : 105  { 106 *(.__rel_dyn_start) 107  } 108 109  .rel.dyn : { 110 *(.rel*) 111  } 112 113  .rel_dyn_end : 114  { 115 *(.__rel_dyn_end) 116  } 117 118  .end : 119  { 120 *(.__end) 121  } 122 123 _image_binary_end = .; 124 125 /* 126  * Deprecated: this MMU section is used by pxa at present but 127  * should not be used by new boards/CPUs. 128 */ 129 /* MMU 表項 */ 130 . = ALIGN(4096); 131  .mmutable : { 132 *(.mmutable) 133  } 134 135 /* 136  * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c 137  * __bss_base and __bss_limit are for linker only (overlay ordering) 138 */ 139 /* bss 段,.bss節包含了程序中所有未初始化的全局變量 */ 140 /* 由鏈接指令(OVERLAY)可見,.bss_start與__rel_dyn_start,.bss與__bss_base,.bss_end與__bss_limit是重疊的。*/ 141  .bss_start __rel_dyn_start (OVERLAY) : { 142 KEEP(*(.__bss_start)); 143 __bss_base = .; 144  } 145 146  .bss __bss_base (OVERLAY) : { 147 *(.bss*) 148 . = ALIGN(4); 149 __bss_limit = .; 150  } 151 152  .bss_end __bss_limit (OVERLAY) : { 153 KEEP(*(.__bss_end)); 154  } 155 156 /* 其他段,這些節都是在編譯鏈接時自動生成的,主要用於動態鏈接或調試使用: */ 157 .dynsym _image_binary_end : { *(.dynsym) } /* 動態符號表`dynamic symbol`,但與`.symtab`不同,`.dynsym`只保存動態鏈接相關的符號,而`.symtab`通常保存了所有的符號; */ 158 .dynbss : { *(.dynbss) } /* 動態未初始化數據表`dynamic bss`; */ 159 .dynstr : { *(.dynstr*) } /* 動態字符串表`dynamic string`,用於保存符號名的字符串表; */ 160 .dynamic : { *(.dynamic*) } /* 保存了動態鏈接所需要的基本信息,例如依賴哪些共享對象,動態鏈接符號表的位置,動態鏈接重定位表的位置,共享對象初始化代碼的地址等; */ 161 .plt : { *(.plt*) } /* 程序連接表`Procddure Linkage Table`,是實現動態鏈接的必要數據; */ 162 .interp : { *(.interp*) } /* 解釋器`interpreter`的縮寫 */ 163 .gnu.hash : { *(.gnu.hash) } 164 .gnu : { *(.gnu*) } 165 .ARM.exidx : { *(.ARM.exidx*) } 166 .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) } 167 /*.gnu.hash .gnu .ARM.exidx`和`.gnu.linkonce.armexidx`是針對`arm`體系專門生成的段,用於調試時函數調用的`backtrace`,如果不需要調試,則可以不用這兩段。 */ 168 }

6.2 其他

  在 u-boot 的編譯過程中會生成 3 個符號表文件:

  • u-boot.map
  • u-boot.sym
  • System.map

  可以通過查看 .uboot.cmd 顯示 uboot 編譯鏈接的數據:

 1 cmd_u-boot := arm-linux-ld.bfd   -pie  --gc-sections -Bstatic  --no-dynamic-linker -Ttext 0x0 -o u-boot 
 2             -T u-boot.lds arch/arm/cpu/arm920t/start.o --start-group  
 3             arch/arm/cpu/built-in.o  
 4             arch/arm/cpu/arm920t/built-in.o  
 5             arch/arm/lib/built-in.o  
 6             board/samsung/common/built-in.o  
 7             board/samsung/jz2440/built-in.o  
 8             cmd/built-in.o  common/built-in.o  
 9             disk/built-in.o  drivers/built-in.o  
10             drivers/dma/built-in.o  
11             drivers/gpio/built-in.o  
12             drivers/i2c/built-in.o  
13             drivers/mtd/built-in.o  
14             drivers/mtd/nand/built-in.o  
15             drivers/mtd/onenand/built-in.o  
16             drivers/mtd/spi/built-in.o  
17             drivers/net/built-in.o  
18             drivers/net/phy/built-in.o  
19             drivers/pci/built-in.o  
20             drivers/power/built-in.o  
21             drivers/power/battery/built-in.o  
22             drivers/power/domain/built-in.o  
23             drivers/power/fuel_gauge/built-in.o  
24             drivers/power/mfd/built-in.o  
25             drivers/power/pmic/built-in.o  
26             drivers/power/regulator/built-in.o  
27             drivers/serial/built-in.o  
28             drivers/spi/built-in.o  
29             drivers/usb/common/built-in.o  
30             drivers/usb/dwc3/built-in.o  
31             drivers/usb/emul/built-in.o  
32             drivers/usb/eth/built-in.o  
33             drivers/usb/gadget/built-in.o  
34             drivers/usb/gadget/udc/built-in.o  
35             drivers/usb/host/built-in.o  
36             drivers/usb/musb-new/built-in.o  
37             drivers/usb/musb/built-in.o  
38             drivers/usb/phy/built-in.o  
39             drivers/usb/ulpi/built-in.o  
40             env/built-in.o  
41             fs/built-in.o  
42             lib/built-in.o  
43             net/built-in.o  
44             test/built-in.o  
45             test/dm/built-in.o 
46             --end-group arch/arm/lib/eabi_compat.o  arch/arm/lib/lib.a -Map u-boot.map;
47             true

  -pic-pie ,一個用於動態庫的位置無關,一個用於動態可執行文件的位置無關。

  -Ttext 用於指定指定鏈接的起始地址

  -T u-boot.lds指定了鏈接使用的腳本文件,實際上,在這個腳本文件的.text節開始前同樣也指定了起始地址:

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM