1. 程式人生 > >常用交叉編譯工具整理(arm-linux-gcc)

常用交叉編譯工具整理(arm-linux-gcc)

一、arm-linux-gcc

  1. 編譯部分:

   -o : 後面接的是輸出檔名(arm-linux-gcc -o hello hello.c)            

   -v : 可以觀看編譯細節         (arm-linux-gcc -v -o hello hello.c)

   -c : 預編譯,編譯和彙編原始檔,不做連線 [裸板程式一般先不做連線,最後一起做連結](arm-linux-gcc -o hello.o -c hello.c)

  -S : 編譯後停止,不進行彙編(arm-linux-gcc -S -o hello.s hello.c)

  -E : 預編譯後即頂著,不進行編譯(arm-linux-gcc -E hello.c)

  -g  : 產生除錯資訊

  -Wall : 開啟所有需要注意的警告資訊

  2. 優化部分

     (注可以指定多個"-O"選項,不管帶不帶數字,生效的是最後一個)

       -O or -O1 : 不使用-O/-O1時,可以減少編譯的開銷,使編譯結果能夠除錯,語句是獨立的,只有聲明瞭register的變數才分配使用暫存器;

                         使用-O/-O1時,編譯器試圖減少目標碼的大小和執行時間。

       -O2          : 多優化一些,除了涉及空間和速度交換的優化選項,執行幾乎所有優化工作,例如不進行迴圈展開和函式內嵌;

       -O3          : 優化的更多,除了-O2, 還開啟"-finline-functions"

       -O0          : 不作優化

  3.  連結部分

       -llibrary_name  :  連結名為library的庫檔案,真正的名字為liblibrary.a,如要連結libtest.a or libtest.so ,則寫成-ltest,如果有動態庫,則會優先連結動態庫。

       -Llibpath            : 指定連結庫搜尋路徑,如庫都放在/prj/libs/下面,則-L/prj/libs

      -nostartfiles         : 不連線系統標準啟動檔案,標準庫檔案仍然正常使用(編譯bootloader,kernel時用到)

      -nostdlib             : 不連線系統標準啟動檔案和標準庫檔案,只把指定的檔案傳遞給聯結器(編譯bootloader,kernel時用到)

                                   [與-nostartfiles的區別是,-nostartfiles只是不包含啟動檔案]

      -static                 : 在支援dynamic linking的系統上阻止連線共享庫[預設情況下會優先選擇連線動態庫,使用了static會直接連線靜態庫] (gcc-static -o main main.c func.c)              

      -shared             :生成共享OBJ檔案 (gcc -shared -o libfunc.so -c func.c; gcc -o main main.c -lfunc -L.)

      -fPIC                 :編譯成位置無關,當編譯多個檔案為動態庫是,必須使用這個選項

                                   (gcc-shared -fPIC -o libfunc.so func1.c func2.c func3.c)

      -Xlinkeroption    : 把選項option傳遞給聯結器,如果要帶引數,必須使用兩次"-Xlinker"  (-Xlinker -assert -Xliner definitions)

     -Wl,option           : 把選項option傳遞給聯結器,如果option有逗號,則傳遞多個選項。常見有(-Wl,--start-group  ... -Wl, --end-group)

4.  目錄部分

     -Iinclude_dir : 在標頭檔案中搜索路徑列表中新增include_dir

    -Llibpath        : 指定連結庫搜尋路徑,如庫都放在/prj/libs/下面,則-L/prj/libs

二、arm-linux-ld

-T : 用於指定程式碼段,資料段,bss段的起始地址 or 指定一個連線指令碼

1.   用於指定程式碼段,資料段,bss段的起始地址

     -Ttext startaddr               //text 指的是程式碼段, startaddr指的是起始地址

     -Tdata startaddr             //data指的是資料段

     -Tbss startaddr              //bss通常指全域性未初始化變數

     如下:指定程式碼段的執行地址為0x00000000,沒有定義資料段,bss段的起始地址,被依次放在程式碼段後面

arm-linux-ld-Ttext 0x00000000 -g led_on.o -o led_on.elf 
     注:位置無關碼和位置相關碼

     bootloader,kernel剛開始執行時所處的位置通常不等於執行地址, 在程式開頭使用b,bl,mov等"位置無關"指令

     將程式碼從Flash中copy到sdram中,然後再用位置相關碼ldr pc, =addr跳轉到相應位置執行。

2. 指定一個連線指令碼

arm-linux-ld -Tlink.lds  -o led_on.elf len_on.S

link.lds:

/*
 *OUTPUT_FORMAT 指定輸出格式,elf32-littlearm的意思是指定輸出可執行檔案是elf格式,32位ARM指令,小端
 *OUTPUI_ARCH   指定輸出可執行檔案的平臺為ARM
 *ENTRY         指定程式入口地址
 *_start        等於SECTIONS裡面.=0x30000000, 即目的碼的起始地址
 */
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS{
           .= 0x30000000;
           .text: { *(.text) }
           .rodata ALIGN(4) : { *(.rodata) }
           .data ALIGN(4) : { *(.data) }
           .bss ALIGN(4) : { *(.bss) *(COMMON) }
}

section格式為:      

SECTIONS{
           ...
           secname start ALIGN(align) (NOLOAD) : AT(ldadr)
           { contexts } > region : phdr = fill
  }
secname       : 用來命名這個段; 如 .bss

contexts         : 用來確定什麼部分放在這個段;

start                : 重定位地址,執行地址,如果程式碼中有位置無關指令,程式在執行時,這個段必須放在這個地址上

ALGIN(align) : 雖然start指定執行地址,但是仍然可以指定對齊要求,對齊後的才是真正執行地址

NOLOAD       : 用來告訴載入器,在執行時不用載入這個段,只有在作業系統的情況下才有意義

AT(ldadr)       : 編譯出來映像檔案中的地址-載入地址load address, 如果不使用這個選項,

                          載入地址等於執行地址。A段放在A處,B段放在B處,執行前再把A,B讀出來組裝成一個完整的執行程式

在程式碼中指定某個section:

  格式:__attribute__((unused,section (".section-name")))

  如:
   C語言中:__attribute__((unused,section (".u_boot_cmd")))
   link-ds中:
           .= .;
           __u_boot_cmd_start= .;
           .u_boot_cmd: { *(.u_boot_cmd) }
           __u_boot_cmd_end= .;

三、arm-linux-objcopy

1. input-file, out-file                                                 

          : 表示輸入目標檔案(源目標檔案)和輸出目標檔案(目的目標檔案)

2. -I bfdname or --input-target=bfdname                  

          :  input-file檔案BFD庫中描述的標準格式名,如果不指定,則arm-linux-objcopy自己去分析原始檔的格式

3. -Obfdname or --output-target=bdfname                

          :  輸出格式

4. -F bfdname or --target=bfdname                          

          : 源目標檔案是什麼格式,目標檔案就是什麼格式,只複製不做格式轉換

5.-R sectionname or--remove-section=sectionname

          : 從輸出檔案中刪掉所有名為sectionname的段

6.-S or --strip-all                                                      

          : 不從原始檔中複製重定位資訊和符號資訊到目標檔案中去(bootloader,kernel等裸板程式用到)

7.-g or --strip-debug                                                

          : 不從原始檔中複製除錯符號到目標檔案中去

在編譯bootloader, kernel時,常用arm-linux-objcopy將ELF格式生成結果轉化為二進位制檔案:

// binary表示輸出格式為二進位制檔案

// file.elf表示ELF格式檔名

// file.bin表示二進位制檔名

#arm-linux-objcopy -O binary -S file.elf file.bin

bfdname 有以下幾個格式:ELF檔案格式(elf32-littlearm, elf32-bigarm)、S-record檔案格式(srec)、HEX檔案格式(ihex)、bin檔案格式(binary)

                BIN檔案格式(binary): 原始的二進位制格式,內部沒地址標記,直接照二進位制格式下載,並且照絕對地址燒寫到Flash中,

                                         就可以啟動了,而如果下載執行,則下載到編譯時的地址即可。

               ELF檔案格式 : 是Linux系統下的一種常用、可移植目標檔案(objectfile)格式

               S-Record檔案格式

               HEX檔案格式

四、 arm-linux-objdump (反彙編程式碼)

1. -b bfdname or --target=bfdname   : 指定目標碼格式,

2. --infoor -i                                        : 檢視目標碼格式列表

3. --disassemble or -d                       : 反彙編可執行段(executablesections)

4. -D or --disassemble-all                  : 反彙編所有段

5. --file-headers or -f                          : 顯示檔案的整體頭部摘要資訊

6. --section-headers, --headers or -h : 顯示目標檔案各個段頭部摘要資訊

7. --section=nameor -j name              : 僅顯示指定section的資訊

//ELF格式的檔案轉換成為反彙編檔案,arm-linux-objdump預設格式elf

#arm-linux-objdump -D file.elf > file.dis   

//將二進位制檔案轉換成反彙編檔案

#arm-linux-objdump -D -b binary -m arm file.bin > file.bin   

五、arm-linux-readelf  (檢視當前檔案or庫是由什麼編譯器所編譯 )

#arm-linux-readelf–h libxxx.so


六、arm-linux-ar (生成.a  or 把.a拆分成.o)

1. -x : 把.a拆分成.o

#arm-linux-ar -x libfunc.a

2.生成靜態庫.a檔案

   -c : 建立一個文件

  -s : 在文件中新增索引

  -r :  插入檔案成員

/* libfunc.a一定在.o檔案前面 */
#arm-linux-ar -rcs libfun.a fun1.o fun2.o fun3.o 

七、arm-linux-strip (去掉其中的除錯資訊,執行檔案大小or動態庫將小的多)

arm-linux-strip libfunc.so