u-boot分析 三 (u-boot.lds腳本)

原文鏈接:https://blog.csdn.net/itxiebo/article/details/50938753

 

________________________________________

目的,

瞭解鏈接器用到的腳本文件u-boot.lds。

________________________________________

在開始這篇博文之前,需要先了解一些GNU linker script的基本知識,可以參考博主的另外一篇分享《GNU linker script,ld script,GNU鏈接腳本》

________________________________________

在《u-boot分析 二》中,我們分析u-boot的目錄結構,提及到了程序入口start.S,但在開始瞭解start.S之前,我們先聊聊鏈接器ld程序的腳本文件u-boot.lds。

下面我們就來品味一下UT4418開發板的u-boot.lds腳本,即u-boot/arch/arm/cpu/slsiap/u-boot.lds。如果讀者正好需要看source code,可以參看之前的文章《u-boot分析 一》中的源碼分享。

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

/*指定輸出可執行文件是elf格式,32位ARM指令,小端*/

OUTPUT_ARCH(arm)

/*指定輸出可執行文件的平臺爲ARM*/

ENTRY(_stext)

/*指定輸出可執行文件的起始代碼段爲_stext*/

SECTIONS

{

/*指定可執行文件的全局入口點,通常這個地址都放在ROM(flash)0x0位置。必須使編譯器知道這個地址,通常都是修改此處來完成*/

    . = 0x00000000;

    /*從0x0位置開始*/

    . = ALIGN(4);

    /*代碼以4字節對齊*/

    .text :

    /*代碼段*/

    {

        *(.__image_copy_start)

        /*u-boot將自己copy到RAM,此爲需要copy的程序的start*/

        SOCDIR/start.o (.text*)

        /*./arch/arm/cpu/slsiap/s5p4418/start.S*/

        SOCDIR/vectors.o (.text*)

        /*./arch/arm/cpu/slsiap/s5p4418/vectors.S,異常向量表*/

        *(.text*)

        /*其他的代碼段放在這裏,即start.S/vector.S之後*/

    }

 

    . = ALIGN(4);

    /*代碼段結束後,有可能4bytes不對齊了,此時做好4bytes對齊,以開始後面的.rodata段*/

    .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

    /*在代碼段之後,存放read only數據段*/

    . = ALIGN(4);

    /*和前面一樣,4bytes對齊,以開始接下來的.data段*/

    .data : {

        *(.data*)

        /*可讀寫數據段*/

    }

 

    . = ALIGN(4);

    /*和前面一樣,4bytes對齊*/

    . = .;

 

    . = ALIGN(4);

    .u_boot_list : {

        KEEP(*(SORT(.u_boot_list*)));

        /*.data段結束後,緊接着存放u-boot自有的一些function,例如u-boot command等*/

    }

 

    . = ALIGN(4);

 

    .image_copy_end :

    {

        *(.__image_copy_end)

        /*至此,u-boot需要自拷貝的內容結束,總結一下,包括代碼段,數據段,以及u_boot_list*/

    }

 

    .rel_dyn_start :

    /*在老的uboot中,如果我們想要uboot啓動後把自己拷貝到內存中的某個地方,只要把要拷貝的地址寫給TEXT_BASE即可,然後boot啓動後就會把自己拷貝到TEXT_BASE內的地址處運行,在拷貝之前的代碼都是相對的,不能出現絕對的跳轉,否則會跑飛。在新版的uboot裏(2013.07),TEXT_BASE的含義改變了。它表示用戶要把這段代碼加載到哪裏,通常是通過串口等工具。然後搬移的時候由uboot自己計算一個地址來進行搬移。新版的uboot採用了動態鏈接技術,在lds文件中有__rel_dyn_start和__rel_dyn_end,這兩個符號之間的區域存放着動態鏈接符號,只要給這裏面的符號加上一定的偏移,拷貝到內存中代碼的後面相應的位置處,就可以在絕對跳轉中找到正確的函數。*/

    {

        *(.__rel_dyn_start)

    }

 

    .rel.dyn : {

        *(.rel*)

        /*動態鏈接符存放在的段*/

    }

 

    .rel_dyn_end :

    {

        *(.__rel_dyn_end)

        /*動態鏈接符段結束*/

    }

 

    .end :

    {

        *(.__end)

    }

 

    _image_binary_end = .;

    /*bin文件結束*/

 

    /*

     * Deprecated: this MMU section is used by pxa at present but

     * should not be used by new boards/CPUs.

     */

    . = ALIGN(4096);

    .mmutable : {  /*for MMU*/

        *(.mmutable)

    }

 

    /*

     * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c

     * __bss_base and __bss_limit are for linker only (overlay ordering)

     */

    /*bss段的描述*/

    .bss_start (OVERLAY) : {

        KEEP(*(.__bss_start));

        __bss_base = .;

    }

 

    .bss __bss_base (OVERLAY) : {

        *(.bss*)

         . = ALIGN(4);

         __bss_limit = .;

    }

 

    .bss_end __bss_limit (OVERLAY) : {

        KEEP(*(.__bss_end));

    }

    /*bss段的描述結束*/

    .dynsym _image_binary_end : { *(.dynsym) }

    .dynbss : { *(.dynbss) }

    .dynstr : { *(.dynstr*) }

    .dynamic : { *(.dynamic*) }

    .plt : { *(.plt*) }

    .interp : { *(.interp*) }

    .gnu.hash : { *(.gnu.hash) }

    .gnu : { *(.gnu*) }

    .ARM.exidx : { *(.ARM.exidx*) }

    .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }

}

________________________________________

總結一下,u-boot.lds腳本文件告訴鏈接器linker如何佈局代碼段、數據段、bss段等,已經配置了u-boot自拷貝(從flash到RAM的copy)的內容。另外,還簡要的涉及了動態鏈接技術等。

在多個地方都存有u-boot.lds文件,例如u-boot/u-boot.lds,u-boot/arch/arm/cpu/u-boot.lds,u-boot/arch/arm/cup/slsiap/u-boot.lds。那麼,我們會問一個問題,鏈接器到底是參照哪個script呢? 要找到這個問題的答案,我們需要看看u-boot/Makefile,其中有這樣一段: ifndef LDSCRIPT ifeq ($(wildcard $(LDSCRIPT)),) LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot.lds endif ifeq ($(wildcard $(LDSCRIPT)),) LDSCRIPT := $(srctree)/$(CPUDIR)/u-boot.lds endif ifeq ($(wildcard $(LDSCRIPT)),) LDSCRIPT := $(srctree)/arch/$(ARCH)/cpu/u-boot.lds endif endif 由上面的這段Makefile分析,我們可以知道u-boot/arch/arm/cpu/u-boot.lds纔是linker使用到的script

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章