Makefile學習(1) arm-linux-ld arm-linux-objcopy arm-linux-objdump


記錄自己所學的點點滴滴O(∩_∩)O哈哈~

 

 

makefile:  

link.bin: start.o main.o
arm-linux-ld -Tlink.lds -o link.elf $^
arm-linux-objcopy -O binary link.elf link.bin
arm-linux-objdump -D link.elf > link_elf.dis
gcc mkv210_image.c -o mkmini210
./mkmini210 link.bin 210.bin

%.o : %.S
arm-linux-gcc -o $@ $< -c

%.o : %.c
arm-linux-gcc -o $@ $< -c

clean:
rm *.o *.elf *.bin *.dis mkmini210 -f

 

解釋:

 


ld:

GNU的鏈接器.

用來把一定量的目標文件跟檔案文件鏈接在一起,並重新定位它們的數據,鏈接符號引用.

一般編譯一個程序時,最后一步就是運行ld進行鏈接

每一個鏈接都被一個鏈接腳本所控制,這個腳本是用鏈接命令語言書寫的.

二、鏈接腳本

鏈接腳本的一個主要目的是描述輸入文件中的各個段(數據段,代碼段,堆,棧,bss)如何被映射到輸出文件中,並控制輸出文件的內存排布.

鏈接器總是使用鏈接腳本的,如果你不提供,則鏈接器會使用一個缺省的腳本,這個腳本是被編譯進鏈接器可執行文件的.

可以使用--verbose命令行顯示缺省的鏈接器腳本的內容.

你可以使用-T命令行來提供你自己的鏈接腳本來替換缺省的鏈接腳本.

三、簡單的鏈接腳本示例.

許多腳本是相當簡單的.

可能最簡單的腳本只含有一個命令:’SECTIONS’.

你可以使用’SECTIONS’來描述輸出文件的內存布局.

‘SECTIONS’是一個功能很強大的命令.

假設你的程序只有代碼段,初始化過的數據段,和未初始化過的數據段.這些會存在於’.text’,’data’,’bss’段中.

對於這個例子,假設代碼應該被載入到地址0x1000處,而數據應該從0x8000000開始,如下是實現這個功能的腳本:

SECTIONS

{

.=0x1000;

.text:{*(.text)}

.=0x8000000;

.data:{*(.data)}

.bss:{*(.bss)}

}

具體分析:

關鍵字’SECTIONS’開始於這個配置.后面跟有一串放在花括號中的符號賦值和輸出端描述的內容.

第一行是對一個特殊的符號’.’賦值,這是一個定位標識器.如果你沒有以其他的方式制定輸出段的地址,那地址值就會被設為定位標識器的現有值,即0x1000.

第二行定義一個輸出段,’.text’.冒號’:’是語法需要,現在可以被忽略.段后面的花括號中,應該列出所有應該放入這個輸出段中的輸入端的名字.’*’是通配符,匹配所有文件名.即將所有輸入文件中的.text段都保存在此段中.

余下的是.data和.bss段,同理,鏈接器會把所有.data段從地址0x8000000開始處放置.

最后,定位標識器的值變為0x8000000加上所有.data段的地址.此時鏈接器把所有.bss放在此處開始的地址.

 

四、簡單的鏈接腳本命令

設置入口點

在運行一個程序時,第一個被執行到的指令成為”入口點”.你可以使用”ENTRY”鏈接腳本命令來設置入口點.參數是一個符號名,如下:

ENTRY(SYMBOL)

有很多不同的方法來設置入口點.鏈接器會通過按順序嘗試一下方法來設置入口點,如果成功了,就會停止.

1,’-e’ 入口命令行選項

2,鏈接腳本中的ENTRY(SYMBOL)命令

3,如果定義了start,就使用start的值

4,如果存在就使用’.text’段的首地址

5,地址’0’

 

 

 

五、命令行設置鏈接地址

ld用於將多個obj或者so(庫)文件鏈接成可執行文件.

使用-T選項可以指定數據段,代碼段,bss段起始位置.(-T只用於鏈接bootloader、內核等沒有底層軟件支持的軟件.鏈接運行於操作系統之上的應用程序時,一般使用默認方式鏈接).

1,直接指定代碼段、數據段、bss段起始地址

如下:

-Ttext startaddr

-Tdata startaddr

-Tbss startaddr

例如:

ld –Ttext 0x00000000 –g led_on.o –o led_on_elf

2,直接使用鏈接腳本來設置起始地址

ld –Ttimer.lds –o timer_elf a.o b.o

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

SECTIONS{

.=0x30000000;

.text : {*(.text)}

.rodata ALIGN(4) : {*(.rodata)}

.data ALIGN(4) : {*(.data)}

.bss ALIGN(4) : {*(.bss) *(COMMON)}

}

一個SECTIONS命令內部包含一個或多個段,段(section)是連接腳本的基本單元,它表示輸入文件中的某部分怎么放置.

完整的鏈接腳本

 

 

arm-linux-ld 是連接器,它把一些目標和歸檔文件結合在一起,重定位數據,並連接符號引用。通常,建立一個新編譯程序的最后一步就是調用ld。

arm-linux-gcc -wall -O2 -c -o $@ $<
-o 只激活預處理,編譯,和匯編,也就是他只把程序做成obj文件
-Wall 指定產生全部的警告信息
-O2 編譯器對程序提供的編譯優化選項,在編譯的時候使用該選項,可以使生成的執行文件的執行效率提高
-c 表示只要求編譯器進行編譯,而不要進行鏈接,生成以源文件的文件名命名但把其后綴由 .c 或 .cc 變成 .o 的目標文件
-S 只激活預處理和編譯,就是指把文件編譯成為匯編代碼
arm-linux-ld 直接指定代碼段,數據段,BSS段的起始地址
-Tbss ADDRESS Set address of .bss section

-Tdata ADDRESS Set address of .data section

-Ttext ADDRESS Set address of .text section
示例:
${CROSS}ld -Ttext=0x33000000 led.o -o led.elf
使用連接腳本設置地址:
arm-linux-ld -Tbeep.lds start.o beep.o -o beep.elf
其中beep.lds 為連接腳本如下:
arm-linux-objcopy被用來復制一個目標文件的內容到另一個文件中,可用於不同源文件的之間的格式轉換
示例:
arm-linux-objcopy –o binary –S elf_file bin_file
常用的選項:
input-file , outflie
輸入和輸出文件,如果沒有outfile,則輸出文件名為輸入文件名
2.-l bfdname或—input-target=bfdname
用來指明源文件的格式,bfdname是BFD庫中描述的標准格式名,如果沒指明,則arm-linux-objcopy自己分析
3.-O bfdname 輸出的格式
4.-F bfdname 同時指明源文件,目的文件的格式
5.-R sectionname 從輸出文件中刪除掉所有名為sectionname的段
6.-S 不從源文件中復制重定位信息和符號信息到目標文件中
7.-g 不從源文件中復制調試符號到目標文件中

 

arm-linux-objdump
查看目標文件(.o文件)和庫文件(.a文件)信息
arm-linux-objdump -D -m arm beep.elf > beep.dis
-D 顯示文件中所有匯編信息
-m machine


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM