GNU GCC

編譯器下載

  1. arm-linux-gcc下載  https://www.linaro.org/downloads/
  2. 解壓添加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
-O1

優化。對於大函數,優化編譯佔用稍微多的時間和相當大的內存。

不使用 `-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 程序會使用的途徑,包括 getoptobstackstrerrorstrtol 和 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&shy;littlearm", "elf32&shy;littlearm", "elf32&shy;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
}


 

 

 

 

 

 

 

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