1. 程式人生 > >詳細分析make uboot 最後的編譯連結的具體執行過程

詳細分析make uboot 最後的編譯連結的具體執行過程

之前分析uboot都是從原始碼分析, 找到一篇好文是從uboot的make資訊來反向分析的.原文連結:

正常編譯uboot過程分兩步:1. make xxxx_config 生成配置檔案  2. make  . 在make之後uboot.bin是如何生成的, 可以分析make的過程:

  1. UNDEF_SYM=`arm-linux-objdump -x board/ams/as3536/libas3536.a lib_generic/libgeneric.a lib_generic/lzma/liblzma.a cpu/arm926ejs/libarm926ejs.a cpu/arm926ejs/ams/libams.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a fs/yaffs2/libyaffs2.a net/libnet.a disk/libdisk.a drivers/bios_emulator/libatibiosemu.a drivers/block/libblock.a drivers/dma/libdma.a drivers/fpga/libfpga.a drivers/gpio/libgpio.a drivers/hwmon/libhwmon.a drivers/i2c/libi2c.a drivers/input/libinput.a drivers/misc/libmisc.a drivers/mmc/libmmc.a drivers/mtd/libmtd.a drivers/mtd/nand/libnand.a drivers/mtd/nand_legacy/libnand_legacy.a drivers/mtd/onenand/libonenand.a drivers/mtd/ubi/libubi.a drivers/mtd/spi/libspi_flash.a drivers/net/libnet.a drivers/net/phy/libphy.a drivers/net/sk98lin/libsk98lin.a drivers/pci/libpci.a drivers/pcmcia/libpcmcia.a drivers/spi/libspi.a drivers/rtc/librtc.a drivers/serial/libserial.a drivers/usb/libusb.a drivers/video/libvideo.a common/libcommon.a libfdt/libfdt.a api/libapi.a post/libpost.a |  
  2. sed  -n -e 's/.*(__u_boot_cmd_.*)/-u1/p'|sort|uniq`;  
  3. cd /home/crifan/develop/uboot/uboot_as3536/u-boot-2009.03_toHome && arm-linux-ld -Bstatic -T /home/crifan/develop/uboot/uboot_as3536/u-boot-2009.03_toHome/board/ams/as3536/u-boot.lds  -Ttext 0x00000000 $UNDEF_SYM cpu/arm926ejs/start.o  
  4. --start-group lib_generic/libgeneric.a lib_generic/lzma/liblzma.a cpu/arm926ejs/libarm926ejs.a cpu/arm926ejs/ams/libams.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a fs/yaffs2/libyaffs2.a net/libnet.a disk/libdisk.a drivers/bios_emulator/libatibiosemu.a drivers/block/libblock.a drivers/dma/libdma.a drivers/fpga/libfpga.a drivers/gpio/libgpio.a drivers/hwmon/libhwmon.a drivers/i2c/libi2c.a drivers/input/libinput.a drivers/misc/libmisc.a drivers/mmc/libmmc.a drivers/mtd/libmtd.a drivers/mtd/nand/libnand.a drivers/mtd/nand_legacy/libnand_legacy.a drivers/mtd/onenand/libonenand.a drivers/mtd/ubi/libubi.a drivers/mtd/spi/libspi_flash.a drivers/net/libnet.a drivers/net/phy/libphy.a drivers/net/sk98lin/libsk98lin.a drivers/pci/libpci.a drivers/pcmcia/libpcmcia.a drivers/spi/libspi.a drivers/rtc/librtc.a drivers/serial/libserial.a drivers/usb/libusb.a drivers/video/libvideo.a common/libcommon.a libfdt/libfdt.a api/libapi.a post/libpost.a board/ams/as3536/libas3536.a --end-group -L /home/crifan/develop/buildroot/buildroot-2009.11/output/staging/usr/bin/../lib/gcc/arm-linux-uclibcgnueabi/4.3.4 -lgcc  
  5. -Map u-boot.map -o u-boot  
  6. arm-linux-objcopy -O srec u-boot u-boot.srec  
  7. arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin  

下面儘可能的具體分析:

一  第一條命令分析

  1. UNDEF_SYM=`arm-linux-objdump -x board/ams/as3536/libas3536.a lib_generic/libgeneric.a lib_generic/lzma/liblzma.a cpu/arm926ejs/libarm926ejs.a cpu/arm926ejs/ams/libams.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a fs/yaffs2/libyaffs2.a net/libnet.a disk/libdisk.a drivers/bios_emulator/libatibiosemu.a drivers/block/libblock.a drivers/dma/libdma.a drivers/fpga/libfpga.a drivers/gpio/libgpio.a drivers/hwmon/libhwmon.a drivers/i2c/libi2c.a drivers/input/libinput.a drivers/misc/libmisc.a drivers/mmc/libmmc.a drivers/mtd/libmtd.a drivers/mtd/nand/libnand.a drivers/mtd/nand_legacy/libnand_legacy.a drivers/mtd/onenand/libonenand.a drivers/mtd/ubi/libubi.a drivers/mtd/spi/libspi_flash.a drivers/net/libnet.a drivers/net/phy/libphy.a drivers/net/sk98lin/libsk98lin.a drivers/pci/libpci.a drivers/pcmcia/libpcmcia.a drivers/spi/libspi.a drivers/rtc/librtc.a drivers/serial/libserial.a drivers/usb/libusb.a drivers/video/libvideo.a common/libcommon.a libfdt/libfdt.a api/libapi.a post/libpost.a |  
  2. sed  -n -e 's/.*(__u_boot_cmd_.*)/-u1/p'|sort|uniq`;  

1. UNDEF_SYM

    UNDEF_SYM=XXX, 這表示將XXX賦值給UNDEF_SYM. 但是在這裡是 UNDEF_SYM=`XXX`, 這裡要做兩點說明 

(1)  字元  ` 叫反引號, 就是數字1左邊那個按鍵, 這個 反引號 表示在shell中,用於要包含的命令, 如果不加 反引號則表示為普通的字串, 所以上邊表示將 arm-linux-objdump.... | sed -n -e ' s/.*(__uboot_cmd_.*)/-ul/p' | sort |unip 執行的結果賦值給UNDDEF_SYM 
(2) 空格加上反斜槓, 表示連線符

2. objdump -x 

先來看下objdump -x中 -x引數的含義: " -x, –all-headers Display the contents of all headers" 顯示(.a庫檔案)所包含全部的頭(資訊).

因此上面的就是把所有的.a庫檔案中的頭資訊都匯出來給那個變數. 而具體的headers是啥樣子的,我們可以以第一個庫libas3536.a為例,來看看結果:  arm-linux-objdump -x board/ams/as3536/libas3536.a

由於結果太長,此處只節選部分顯示:

  1. In archive board/ams/as3536/libas3536.a:  
  2. as3536.o:     file format elf32-littlearm  
  3. rw-r--r-- 1000/1000   5872 Feb 26 23:27 2010 as3536.o  
  4. architecture: arm, flags 0x00000011:  
  5. HAS_RELOC, HAS_SYMS  
  6. start address 0x00000000  
  7. private flags = 600: [APCS-32] [VFP float format] [software FP]  
  8. Sections:  
  9. Idx Name          Size      VMA       LMA       File off  Algn  
  10. 0 .text         000001c8  00000000  00000000  00000034  2**2  
  11. CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE  
  12. 1 .data         00000000  00000000  00000000  000001fc  2**0  
  13. CONTENTS, ALLOC, LOAD, DATA  
  14. 2 .bss          00000000  00000000  00000000  000001fc  2**0  
  15. ALLOC  
  16. 3 .debug_abbrev 00000155  00000000  00000000  000001fc  2**0  
  17. CONTENTS, READONLY, DEBUGGING  
  18. 4 .debug_info   000002b7  00000000  00000000  00000351  2**0  
  19. CONTENTS, RELOC, READONLY, DEBUGGING  
  20. 5 .debug_line   00000127  00000000  00000000  00000608  2**0  
  21. CONTENTS, RELOC, READONLY, DEBUGGING  
  22. 6 .rodata.str1.1 00000011  00000000  00000000  0000072f  2**0  
  23. CONTENTS, ALLOC, LOAD, READONLY, DATA  
  24. 7 .rodata       0000000a  00000000  00000000  00000740  2**0  
  25. CONTENTS, ALLOC, LOAD, READONLY, DATA  
  26. .............  
  27. SYMBOL TABLE:  
  28. 00000000 l    df *ABS*    00000000 as3536.c  
  29. 00000000 l    d  .text    00000000 .text  
  30. 00000000 l    d  .data    00000000 .data  
  31. 00000000 l    d  .bss    00000000 .bss  
  32. 00000000 l    d  .debug_abbrev    00000000 .debug_abbrev  
  33. 00000000 l    d  .debug_info    00000000 .debug_info  
  34. 00000000 l    d  .debug_line    00000000 .debug_line  
  35. 00000000 l    d  .rodata.str1.1    00000000 .rodata.str1.1  
  36. 00000000 l     O .rodata    0000000a __FUNCTION__.2915  
  37. 00000000 l    d  .rodata    00000000 .rodata  
  38. ................  
  39. 00000000         *UND*    00000000 i2cIsMasterBusy  
  40. 00000000         *UND*    00000000 gpioInitialise  
  41. 00000000         *UND*    00000000 uartInitialize  
  42. 00000000         *UND*    00000000 serial_init  
  43. 00000000         *UND*    00000000 mpmcInitialize  
  44. 00000000         *UND*    00000000 mpmcDynamicConfig  
  45. 00000000         *UND*    00000000 icache_enable  
  46. 00000000         *UND*    00000000 dcache_enable  
  47. ...............  
  48. as353x_nand.o:     file format elf32-littlearm  
  49. rw-r--r-- 1000/1000  24080 Feb 26 23:27 2010 as353x_nand.o  
  50. architecture: arm, flags 0x00000011:  
  51. HAS_RELOC, HAS_SYMS  
  52. start address 0x00000000  
  53. private flags = 600: [APCS-32] [VFP float format] [software FP]  
  54. Sections:  
  55. Idx Name          Size      VMA       LMA       File off  Algn  
  56. 0 .text         00000df8  00000000  00000000  00000034  2**2  
  57. CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE  
  58. 1 .data         00000000  00000000  00000000  00000e2c  2**0  
  59. CONTENTS, ALLOC, LOAD, DATA  
  60. 2 .bss          00000000  00000000  00000000  00000e2c  2**0  
  61. ALLOC  
  62. 3 .debug_abbrev 00000286  00000000  00000000  00000e2c  2**0  
  63. CONTENTS, READONLY, DEBUGGING  
  64. ...............  
  65. 6 .rodata.str1.1 00000093  00000000  00000000  00002aab  2**0  
  66. CONTENTS, ALLOC, LOAD, READONLY, DATA  
  67. 7 .rodata       00000185  00000000  00000000  00002b3e  2**0  
  68. CONTENTS, ALLOC, LOAD, READONLY, DATA  
  69. ...................  
  70. SYMBOL TABLE:  
  71. 00000000 l    df *ABS*    00000000 as353x_nand.c  
  72. 00000000 l    d  .text    00000000 .text  
  73. 00000000 l    d  .data    00000000 .data  
  74. ..........................  
  75. 00000ce4 l     F .text    00000114 as353x_nand_read_buf_swbch4  
  76. 00000bd0 l     F .text    00000114 as353x_nand_write_buf_swbch4  
  77. 00000a28 l     F .text    000001a8 as353x_enable_hwecc_swbch4  
  78. 00000a0c l     F .text    0000001c as353x_calculate_ecc  
  79. 00000944 l     F .text    000000c8 as353x_correct_data  
  80. 00000460 l     F .text    00000034 as353x_nand_ready  
  81. .................  
  82. 00000043 l     O .rodata    00000017 __FUNCTION__.3286  
  83. 0000005a l     O .rodata    00000013 __FUNCTION__.3214  
  84. .......................  
  85. 00000000         *UND*    00000000 bchDecode  
  86. 00000000         *UND*    00000000 bchEncodeT4  
  87. 00000000         *UND*    00000000 DebugClrRegBits8  
  88. 00000000         *UND*    00000000 DebugRReg32  
  89. .............  
可以看出來,裡面包含了N個.o目標檔案,而目標檔案,就是我們之前用c檔案編譯出來的. 

(1). 上面的SYMBOL_TABLE中類似於:

  1. 00000a0c l     F .text    0000001c as353x_calculate_ecc  
  2. 00000944 l     F .text    000000c8 as353x_correct_data  
  3. 00000460 l     F .text    00000034 as353x_nand_ready  
的 .text 型別, 都是該 .o 檔案裡面包含的已經實現了的某個函式
(2). 上面SYMBOL_TABLE中類似於:
  1. 00000000         *UND*    00000000 udelay  
  2. 00000000         *UND*    00000000 bchDecode  
  3. 00000000         *UND*    00000000 bchEncodeT4  
都是 *UND* 型別的, 表示未定義型別. 即該函式在本檔案中被呼叫但是在別的檔案(其他的 .c 對應的 .o )中實現的

(3). 類似於

  1. as353x_nand.o:     file format elf32-littlearm  
  2. rw-r--r-- 1000/1000  24080 Feb 26 23:27 2010 as353x_nand.o  
  3. architecture: arm, flags 0x00000011:  
  4. HAS_RELOC, HAS_SYMS  
可以看出來,編譯出的程式是執行在arm平臺上的, 小端序, elf32格式, HAS_RELOC表示可重定位的,即最後的連結之後才最終變成可執行檔案. 

綜上所述, 每個 .a 檔案中都包含了若干個 .o 檔案, 而每個 .o 檔案都對應一個 .c 或者一個 .S 檔案

3.  sed命令

(1)  | 表示將前邊objdump命令生成的內容通過管道送給後邊的 sed 命令去處理

  1. sed  -n -e 's/.*(__u_boot_cmd_.*)/-u1/p'
(2 )sed –help就可以找到:   
-n, –quiet, –silent,     取消自動列印模式空間

(3) sed 預設會列印匹配的每一行,但是可以使用-n選項將其關閉。在這種情況下,只有用P命令顯式說明的行才出現在輸出中。如
sed –n ‘ / 模式 /p ’
sed –n ‘ / 模式 /!p ’

所以,-n的意思就是,預設後面如果有匹配的內容,比如要替換字元子類的,就會列印這些相關資訊,此處加了-n,就no print了.

(4) -e 指令碼, –expression=指令碼,  新增“指令碼”到程式的執行列表, 簡單的來說,就是把-e後面跟的內容,當做要執行的指令碼(命令)放入到命令列表中(以待後面分別執行這些命令去處理字元流/串),具體用法例子所示:

  1. >cat file  
  2. I have three dogs and two cats  
  3. >sed -e ‘s/dog/cat/g’ -e ‘s/cat/elephant/g’ file  
  4. I have three elephants and two elephants  
  1. 上面的例子中,sed,對於字元流:  
  2. I have three dogs and two cats  
  3. 會先用第一個-e後面的’s/dog/cat/g’,即所謂的腳步或者叫做命令,來處理。  
  4. 具體處理結果就是,g代表全域性範圍,s/dog/cat代表把字串dog替換為cat,所以處理後,元字元流就變成:  
  5. I have three cats and two cats  
  6. 然後對於處理後的這個字元流,繼續用後面的’s/cat/elephant/g’來處理,即將其中的cat都替換為elephant,所以處理後的結果為:  
  7. I have three elephants and two elephants  
所以 -e 引數就是當sed執行之後將後續的引數當做命令一條一條來執行, 並且每次執行完的結果當做下一條命令的輸入,直到最後結束
  1. sed  -n -e 's/.*(__u_boot_cmd_.*)/-u1/p'
而本例中加與不加 -e 引數都會獲得一樣的結果, 這又是為什麼呢.?  原來,如果sed中,沒有-e,-f–expression或者–file等引數,那麼就將第一個非選項的引數(即不是那種-n等以-開頭的引數),視為要執行的指令碼(命令), 因此, sed中只有一個指令碼的時候, 有沒有-e都是一樣的, 那麼本例中sed中 -e 之後的指令碼是什麼意思呢?
  1. s/.*(__u_boot_cmd_.*)/-u1/p  
(5) 中間以斜槓/為分隔,屬於 s/regexp/replacement/flag 共四部分:
第一部分 :s,表示substitue,字