一、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