SECTIONS { |
/* nand.lds */ |
arm-linux-ld –Tnand.lds x.o y.o –o xy.o。也用-Ttext參數直接指定連接地址,如
arm-linux-ld –Ttext 0x30000000 x.o y.o –o xy.o。
relocate: /*
把U-Boot重新定位到RAM */ |
OUTPUT_FORMAT("elf32littlearm", "elf32littlearm", "elf32littlearm") |
xloader是在系統上電之後,執行完ROM中的frimware後最先開始執行的用戶程序,它的體積很小,執行的功能也很簡單,主要是對系統時鐘以及外部SDRAM進行初始化,初始化完成之後就檢查Flash中的uboot image是否準備好,如果準備好了就將Flash中的uboot image根據image header中指定的load address加載到外部SDRAM中,然後就跳轉到uboot執行代碼。
這裏,我試圖從頭開始,在源代碼級別上來分析整個系統的引導過程。
像Xloader或者uboot之類的程序,並不像我們平常寫的應用程序那樣,程序的入口函數直接找main函數就行。對於這種系統程序,在最開始看代碼,尤其是要找到最開始執行的代碼的位置的時候,最好的一個方法就是找到整個工程的.lds文件,也就是鏈接腳本文件(linker loader script)。它定義了整個工程在編譯之後的鏈接過程,以及各個輸入目標文件中的各個段在輸出目標文件中的分佈。詳細的關於lds文件的介紹可以參考 gnu的在線文檔:http://sourceware.org/binutils/docs/ld/index.html。其中的第三節Linker Script對鏈接腳本文件進行了介紹。
現在,我們首先開看一看xloader.lds的代碼:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(XLOADER_ENTRY)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
./obj/init.o (.text)
*(.text)
}
.rodata . :
{
*(.rodata)
}
. = ALIGN(4);
.data : { *(.data) }
. = ALIGN(4);
.got : { *(.got) }
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}
下面,我們對這一段代碼逐句進行分析。
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
在GNU的文檔中,是這麼定義的:
OUTPUT_FORMAT(default, big, little),在鏈接的時候,如果使用了-EB的命令行參數,則使用這裏的big參數指定的字節序,如果使用了-EL的命令行參數,則使用這裏的little參數指定的字節序,如果沒有使用任何命令行參數,則使用這裏的default參數指定的字節序。
由xloader.lds中的定義可見,不管在鏈接的時候使用了何種命令行參數,輸出的目標文件都是使用elf32-littlearm方式的字節序。
OUTPUT_ARCH(arm)
在GNU的文檔中,是這麼定義的:
OUTPUT_ARCH(bfdarch),也就是指定了目標的體系結構,在這裏,SpearPlus內部使用的處理器核是arm926ejs的,因此體系結構也就是arm。
ENTRY(XLOADER_ENTRY)
在GNU的文檔中,是這麼定義的:
ENTRY(symbol)
There are several ways to set the entry point. The linker will set the entry point by trying each of the following methods in order, and stopping when one of them succeeds:
* the `-e' entry command-line option;
* the ENTRY(symbol) command in a linker script;
* the value of the symbol start, if defined;
* the address of the first byte of the `.text' section, if present;
* The address 0.
也就是說,ENTRY(XLOADER_ENTRY)定義了整個程序的入口處,也就是在標號XLOADER_ENTRY處。整個程序將從這裏開始運行。
接下來的部分,是對整個輸出目標文件中各個段的存儲位置的定義。
在GNU的文檔中,是這麼定義的:
SECTIONS
{
sections-command
sections-command
...
}
對於其中的每一個sections-command,其完整的定義如下:
The full description of an output section looks like this:
section [address] [(type)] :
[AT(lma)] [ALIGN(section_align)] [SUBALIGN(subsection_align)]
{
output-section-command
output-section-command
...
} [>region] [AT>lma_region] [:phdr :phdr ...] [=fillexp]
Most output sections do not use most of the optional section attributes.
The whitespace around section is required, so that the section name is unambiguous. The colon and the curly braces are also required. The line breaks and other white space are optional.
下面來看看xloader.lds中SECTIONS的定義:
SECTIONS
{
/* location counter設置爲0x00000000,其實由於在Makefile中的
* 鏈接選項中使用了-Ttext $(TEXT_BASE),而TEXT_BASE=0xD2800B00
* 因此,此處的設置其實是沒有作用的,代碼運行的時候將運行在TEXT_BASE地址
*/
. = 0x00000000;
. = ALIGN(4); /* 四字節對齊 */
/* 將所有輸入目標文件中的.text段即代碼段放在此處,並且,輸出目標文件中的.text段中的
* 開頭部分存放init.o的.text段。也就是運行的第一條代碼,也就是XLOADER_ENTRY
* 標號對應的代碼就在init.o當中
*/
.text :
{
./obj/init.o (.text)
*(.text)
}
/* 緊接着.text段,存放所有輸入目標文件中的.rodata段,也就是
* 只讀數據段。此處注意.rodata後跟着的.,這個.表示當前location counter,
* 對應於上述完整描述sections中的[address]
* 此處表示.rodata段緊接着.text段存放,而不用任何對齊
*/
.rodata . :
{
*(.rodata)
}
. = ALIGN(4); /* 四字節對齊 */
/* 將所有輸入目標文件中的.data讀寫數據段存儲在此處
* 所有全局手動初始化的變量存儲在該段中,並且在輸出目標文件中已經分配了存儲空間
*/
.data : { *(.data) }
. = ALIGN(4); /* 四字節對齊 */
/* .got段是GLOBAL OFFSET TABLE,具體的作用還沒有搞清楚 */
.got : { *(.got) }
. = ALIGN(4); /* 四字節對齊 */
/* .bss段的開始,所有全局未初始化變量的大小等信息存儲在該段中
* 但是在輸出的目標文件中並不爲這些變量分配存儲空間,
* 而是交給操作系統在初始化的時候分配內存,然後緊跟在.data段後面並初始化爲零
* 另外,此處還定義了兩個標號分別表示.bss的開始和結束(也是整個目標文件的結束)
*/
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}
從這裏,我們能夠得到的最關鍵的信息是:整個程序的入口在標號XLOADER_ENTRY處,並且該標號定義在init.o目標文件中,因爲整個最終的鏈接之後的目標文件中,位於最開頭的就是init.o目標文件。
於是,我們可以根據這個線索來繼續追蹤整個的引導過程了。
參考文章:
對.lds連接腳本文件的分析
http://blog.csdn.net/tony821224/archive/2008/01/18/2051755.aspx
Documentation for binutils 2.18--ld
http://sourceware.org/binutils/docs/ld/index.html
.bss段和.data段的區別
http://www.w3china.org/blog/more.asp?name=FoxWolf&id=29997
什麼是bss段
http://blog.csdn.net/bobocheng1231/archive/2008/02/23/2115289.aspx