編譯器下載
- arm-linux-gcc下載 https://www.linaro.org/downloads/
- 解壓添加bin到環境變量
gcc組件
c++ |
gcc 的一個版本,默認語言設置爲 C++,而且在連接的時候自動包含標準 C++庫。這和g++一樣 |
g++ |
gcc 的一個版本,默認語言設置爲 C++,而且在鏈接的時候自動包含標準 C++庫。這和 c++ 是一樣的 |
gcc |
該驅動程序用於執行編譯程序和連接程序以產生需要的輸出 |
gcc使用
gcc參數
選項 |
描述 |
-c |
只編譯不鏈接。 會明確指示 GCC 去編譯源代碼,在硬盤上留下目標文件,且跳過將目標文件連接到可執行程序這一步。 缺省情況下, GCC通過用`.o'替換源文件名後綴`.c', `.i', `.s',等產生目標文件名.可以使用-o選項選擇其他名字. GCC忽略-c選項後面任何無法識別的輸入文件(他們不需要編譯或彙編). 如:gcc -c hello.c |
-Dmacro | 定義指定的宏,使它能夠通過源碼中的#ifdef進行檢驗 |
-o file |
指定輸出的文件名 如果沒有使用 `-o' 選項,默認的輸出結果是:可執行文件爲`a.out'。如gcc -c hello.c -o hello.o |
-S |
指示編譯程序生成彙編語言代碼,然後停止。 缺省情況下, GCC通過用 `.o' 替換源文件名後綴 `.c'、`.i' 等等,產生 目標文件名。可以使用-o選項選擇其他名字。 彙編語言的形式依賴於編譯程序的目標平臺。如果編譯多個源文件,會爲每個源文件都生成一個彙編語言模塊。 GCC忽略任何不需要編譯的輸入文件。 gcc -S helloworld.c |
-E |
預處理後即停止,不進行編譯。預處理後的代碼送往標準輸出 GCC忽略任何不需要預處理的輸入文件. gcc -E helloworld.c gcc -E helloworld.c -o helloworld.i |
-C |
告訴預處理器不要丟棄註釋,配合 `-E' 選項使用。 |
-P |
告訴預處理器不要產生 `#line' 命令,配合 `-E' 選項使用 |
-v |
(在標準錯誤)顯示執行編譯階段的命令.同時顯示編譯器驅動程序,預處理器,編譯器的版本號. |
-ldl |
表示生成的對象模塊需要用到共享庫:$ gcc say.c -ldl -o say 主要是用到了 dlopen 等函數需要用到此選項 |
-I |
指定頭文件路徑 |
-e name |
指定 name 爲程序的入口地址 |
-ffreestanding |
編譯獨立的程序,不會自動鏈接 C 運行庫、啓動文件等;他隱含聲明瞭 `-fno-builtin' 選項,而且對main函數沒有特別要求。 |
-finline-functions -fno-inline-funcitons |
啓用內聯函數 關閉內聯函數 |
-g |
以操作系統的本地格式(stabs,COFF,XCOFF 或 DWARF)產生調試信息,GDB能夠使用這些調試信息。 |
-ggdb |
以本地格式(如果支持)輸出調試信息,儘可能包括GDB擴展。 |
-L <directory> |
指定鏈接時查找路徑,多個路徑之間用冒號隔開 |
-static |
在支持動態連接(dynamic linking)的系統上阻止連接共享庫。即只能使用靜態鏈接。 |
-shared |
生成一個共享目標文件,他可以和其他目標文件鏈接產生可執行文件。 |
-O |
優化。對於大函數,優化編譯佔用稍微多的時間和相當大的內存。 不使用 `-O' 選項時,編譯器的目標是減少編譯的開銷,使編譯結果能夠調試。 語句是獨立的:如果在兩條語句之間用斷點中止程序,可以對任何變量重新賦值,或者在函數體內把程序計數器指到其他語句,以及從源程序中精確地獲取你期待的結果。 不使用 `-O' 選項時,只有聲明瞭register的變量才分配使用寄存器。編譯結果比不用 `-O' 選項的GCC要略遜一籌. 使用了 `-O' 選項,編譯器會試圖減少目標碼的大小和執行時間。 如果指定了`-O'選項,,`-fthread-jumps' 和 `-fdefer-pop' 選項將被打開。 |
-O2 |
多優化一些。 除了涉及空間和速度交換的優化選項,執行幾乎所有的優化工作。例如不進行循環展開(loop unrolling)和函數內嵌(inlining)。 和 -O 選項比較,這個選項既增加了編譯時間,也提高了生成代碼的運行效果。 |
-O3 |
優化的更多。除了打開 -O2所做的一切,它還打開了-finline-functions選項。 |
-O0 |
不優化。如果指定了多個 -O選項,不管帶不帶數字,最後一個選項纔是生效的選項。 |
-Wall |
對源代碼中的多數編譯警告進行啓用 |
-fpic |
如果支持這種目標機,編譯器就生成位置無關目標碼。適用於共享庫(shared library)。 |
-fPIC |
如果支持這種目標機,編譯器就輸出位置無關目標碼。適用於動態連接(dynamic linking),即使分支需要大範圍轉移。 |
-fPIE |
使用地址無關代碼模式編譯可執行文件 隨機分配地址 |
-Xlinker option |
把選項option傳遞給連接器,可以用他傳遞系統特定的連接選項, GNU CC無法識別這些選項。 如果需要傳遞攜帶參數的選項,必須使用兩次 `-Xlinker',一次傳遞選項,另一次傳遞他的參數。 例如,如果傳遞 `-assert definitions',必須寫成 `-Xlinker -assert -Xlinker definitions',而不能寫成 `-Xlinker "-assert definitions"',因爲這樣會把整個字符串當做一個參數傳遞,顯然這不是連接器期待的。 |
-Wl option |
把選項option傳遞給連接器。如果option中含有逗號,就在逗號處分割成多個選項。 |
-ffunction-sections |
將每個函數編譯到獨立的代碼段 |
-fdata-sections |
將全局/靜態變量編譯到獨立的數據段 |
動態庫
//單文件
gcc -fPIC -shared xxx.c -o libxxx.so
//多文件
gcc -fPIC -shared xxx1.c xxx2.c xxx3.c -o libxxx.so
使用
編譯:
gcc -fPIC -shared hello.c -o libhello.so
gcc main.c -L. -lhello -o main
靜態庫
1 gcc hello.c -o hello.o #這裏沒有使用-shared
2 ar -crv libhello.a hello.o #這裏的ar相當於tar的作用,將多個目標打包。
gcc main.c libhello.a -L. -o main
或
gcc main.c -lhello -L. -static -o main
gcc工具集
addr2line |
給出一個可執行文件的內部地址,addr2line 使用文件中的調試信息將地址翻譯成源代碼文件名和行號。 |
ar |
這是一個程序,可通過從文檔中增加、刪除和析取文件來維護庫文件。通常使用該工具是爲了創建和管理連接程序使用的目標庫文檔。 |
as |
GNU 彙編器。實際上它是一族彙編器,因爲它可以被編譯或能夠在各種不同平臺上工作。 |
c++filt |
程序接受被 C++編譯程序轉換過的名字(不是被重載的) ,而且將該名字翻譯成初始形式。 |
elfedit |
更新 ELF 文件的 ELF 頭。 |
gprof |
該程序會監督編譯程序的執行過程,並報告程序中各個函數的運行時間,可以根據所提供的配置文件來優化程序。 |
ld |
GNU 連接程序。該程序將目標文件的集合組合成可執行程序。 |
ld.bfd |
到 ld 的硬鏈接。 |
libbfd |
二進制文件描述器庫。該程序是 binutils 包的一部分 |
libiberty |
包含多個 GNU 程序會使用的途徑,包括 getopt、obstack、strerror、strtol 和 strtoul。 |
libopcodes |
一個庫,用於處理 opcodes——處理器指令的 "可讀文本" 版本;用於編制 objdump 這樣的工具。 |
nlmconv |
將可重定位的目標文件轉換成 NetWare 可加載模塊(NetWare Loadable Module,NLM) 。 |
nm |
列出目標文件中定義的符號。 |
objcopy |
將目標文件從一種二進制格式複製和翻譯到另外一種。 |
objdump |
顯示一個或多個目標文件中保存的多種不同信息。 |
ranlib |
創建和添加到 ar 文檔的索引。該索引被 ld 使用來定位庫中的模塊。 |
readelf |
從 ELF 格式的目標文件顯示信息 |
size |
列出目標文件中每個部分的名字和尺寸。 |
strings |
瀏覽所有類型的文件,析取出用於顯示的字符串。 |
strip |
從目標文件或文檔庫中去掉符號表,以及其他調試所需的信息。 |
windres |
Window 資源文件編譯程序。 |
ld -Ttext 0x4000000 -c -o led.o led.c 指定text段地址
查看對應地址函數名 行號
addrline2 4005100 -e a.out -f
查看elf頭信息
readelf -h a.out
查看所有信息
readelf -a a.out
列出文件中符號
nm main.o
objdump -d a.out 反彙編
objdump -D a.out 列出詳細內容
objdump -x a.out 顯示所有頭文件信息
objdump -f a.out 查看入口文件
反匯bin格式文件
objdump -D -b binary -m i386 test.bin
objdump -D -b binary -m arm text.bin
objcopy目標格式轉化
轉化u-boot爲二進制
objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
size a.out 列出文件個段大小
strings a.out 列出可打印信息
strip a.out 瘦身
file a.out 列出文件信息
鏈接腳本
描述
SECTIONS {
...
secname start BLOCK(align) (NOLOAD):AT(ldard)
{
contents
} > region:phdr=fill
}
secname段名
contents 決定哪些內容放在本段,可以是整個目標文件,也可以是目標文件中的某段(代碼段、數據段等)
start 運行地址
AT(ldadr) 定義本段加載地址
例子
SECTIONS {
firtst 0x00000000 : { head.o init.o }
second 0x30000000 : AT(4096) { main.o }
}
main.o放在4096(0x1000,是AT指定的,存儲地址)開始處,但是它的運行地址在0x30000000,運行之前需要從0x1000(加載處)複製到0x30000000(運行處),此過程也就用到了讀取Nand flash。
ld -Txxx.lds
ld -Ttext 0x300000000
OUTPUT_FORMAT(DEFAULT,BIG,LITTLE) : 定義三種輸出文件的格式(大小端)
OUTPUT_FORMAT("elf32­littlearm", "elf32­littlearm", "elf32­littlearm")
;指定輸出可執行文件是elf格式,32位ARM指令,小端
OUTPUT_ARCH(arm)
;指定輸出可執行文件的平臺爲ARM
ENTRY(_start)
指定輸出可執行文件的起始代碼段爲_start.
SECTIONS
{
. = 0x00000000 ; 從0x0位置開始
. = ALIGN(4) ; 代碼以4字節對齊
.text : ;指定代碼段
{
cpu/arm920t/start.o (.text) ; 代碼的第一個代碼部分
*(.text) ;其它代碼部分
}
. = ALIGN(4)
.rodata : { *(.rodata) } ;指定只讀數據段
. = ALIGN(4);
.data : { *(.data) } ;指定讀/寫數據段
. = ALIGN(4);
.got : { *(.got) } ;指定got段, got段式是uboot自定義的一個段, 非標準段
__u_boot_cmd_start = . ;把__u_boot_cmd_start賦值爲當前位置, 即起始位置
.u_boot_cmd : { *(.u_boot_cmd) } ;指定u_boot_cmd段, uboot把所有的uboot命令放在該段.
__u_boot_cmd_end = .;把__u_boot_cmd_end賦值爲當前位置,即結束位置
. = ALIGN(4);
__bss_start = .; 把__bss_start賦值爲當前位置,即bss段的開始位置
.bss : { *(.bss) }; 指定bss段
_end = .; 把_end賦值爲當前位置,即bss段的結束位置
}
//內存區域描述
MEMORY
{
rom (rx) : ORIGIN = 0, LENGTH = 256K
ram (!rx) : org = 0×40000000, l = 4M
}