uboot的編譯及連接過程

前言

  想讀懂uboot的鏈接腳本,以及瞭解鏈接腳本的使用方法,需要掌握以下基本知識。

1、gcc程序段介紹

  一個可執行程序主要包含text段(代碼),data段(初始化的全局變量),以及bss段(未初始化的全局變量)。局部變量是在運行過程中分配的,不佔用可執行程序的大小。下面舉一個例子說明

#include <stdio.h>
#include <string.h>


int a = 0;            //全局未初始化變量,系統默認賦值成0,bss段,4個字節
int b = 5, c = 6; //全局已初始化變量, data段,8個字節

int main()
{
    int i = 0; //局部變量

    i++;
    a++;
    printf("i = %d, a = %d\n", i, a);

    return 0;
}

  將上面代碼保存成main.c,並將其編譯成.o文件:arm-fsl-linux-gnueabi-gcc -c main.c,-c參數說明只進行編譯不進行鏈接。然後使用以下命令查看各種段的大小

root@silent:/home/lianxi/test# arm-fsl-linux-gnueabi-size main.o
   text    data     bss     dec     hex filename
    120       8       4     132      84 main.o
root@silent:/home/lianxi/test# 

  可以看到代碼段大小120個字節,data段大小8個字節(變量b和c的大小),bss段的大小4個字節(變量a的大小),可執行程序的總大小爲120+8+4=132。局部變量i,是在代碼運行的時候分配的,不影響bin文件的大小!

2、鏈接腳本的使用

  爲了說明uboot的編譯及鏈接過程,這裏寫兩個簡單的彙編源文件,然後使用自己寫的鏈接腳本將它們鏈接起來。兩個源文件分別是mystart.s,mylowlevel_init.s,鏈接腳本是myboot.lds,其內容及註釋如下。
  mystart.s彙編文件內容如下:

b reset
b reset
b reset
b reset
b reset
b reset
b reset
b reset

reset:
    mov r0, r1
    bl mytest  /*在另一個文件中定義*/
    mov r1, r2
    mov r2, r3
    mov r3, r4
loop:
    b loop

  mylowlevel_init.s彙編文件內容如下:

.global mytest
mytest:
    mov r0, r1
    mov r1, r2
    mov pc, lr

  myboot.lds鏈接腳本內容如下:

SECTIONS
{
    /********************************************
    *編譯地址從0地址開始,
    *這個地址可以使用連接器的-Ttext參數重新修改,
    *在uboot裏面是重新定位到了TEXT_BASE這個內存地址。
    ********************************************/
    . = 0x00000000; 

    /******************************************
    *代碼段,把mystart.o放在最前面,其他.o的順序
    *不管,使用* (.text)通配!
    ******************************************/
    .text : {
        mystart.o
        * (.text)
    }

    /*****************************************
    *已經初始化的全局變量
    ******************************************
    .data : {
        * (.data)
    }

    /****************************************
    *未初始化全局變量,這裏放兩個標號bss_start
    *和bss_end,在程序中可以引用,比如可以用來
    *計算整個二進制文件的大小。
    ****************************************/
    .bss_start = .;
    .bss : {
        * (.bss)
    }
    .bss_end = .;
}

  然後使用如下命令就可以對以上兩個源文件進行編譯和鏈接:

root@silent:/home/lianxi/uboot_lds# arm-fsl-linux-gnueabi-gcc -c mystart.s
root@silent:/home/lianxi/uboot_lds# arm-fsl-linux-gnueabi-gcc -c mylowlevel_init.s
root@silent:/home/lianxi/uboot_lds# arm-fsl-linux-gnueabi-ld -Tmyboot.lds -o myboot mylowlevel_init.o mystart.o  //使用鏈接腳本進行鏈接
root@silent:/home/lianxi/uboot_lds# ls
myboot  myboot.bin  myboot.lds  mylowlevel_init.o  mylowlevel_init.s  mystart.o  mystart.s
root@silent:/home/lianxi/uboot_lds# 

  鏈接完成後生成myboot文件,該文件格式爲ELF,需要使用如下命令將其轉換成bin文件

arm-fsl-linux-gnueabi-objcopy -O binary myboot myboot.bin

  可以使用hexdump命令查看myboot.bin和其他.o文件的內容,如:hexdump -C myboot.bin,對比鏈接前後的差異。如果想在開發板上跑起來,還需要根據具體的cpu,將myboot.bin製作成相應的格式(一般在前面加個一個頭),cpu的類型千千萬萬種,這裏不說了,具體格式應該查看該cpu的datasheet。

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