1. 程式人生 > >連結指令碼

連結指令碼

指令碼的主要目的是描述如何把輸入檔案中的節(sections)對映到輸出檔案中,並控制

輸出檔案的儲存佈局。

1:輸出什麼

2:輸入是什麼,那麼obj檔案

3:要用什麼庫,庫放在什麼地方

4:記憶體分佈地址

5:提供啟動程式碼一些全域性地址變數

——————————————————————————————————————————

1:設定入口函式

2:定義一個變數並賦值

3:描述輸入輸出檔案的連結規則

————————————1:設定入口函式—2:定義一個變數並賦值—————————

對於arm-gcc-ld指令碼來說設定入口函式和定義變數可以在SECTIONS命令大括號裡,也可以在外面。

語法是: ENTRY(symbol)

symbol應該是某個函式,或者是彙編程式碼裡的一個入口。然而,其實ARM-GCC-LD有很多種方式定義入口,

1:在連線的時候使用-e引數。

2:在腳本里使用ENTRY

3:如果定義過start這個入口(如果在彙編裡如果本身就有這個名字叫start的入口,那麼不用特別的宣告也可以)

4SECTION.text的第一個入口函式

5:地址為0的指令

其實看了這個我們可以理解是ARM對入口的一個選擇優先順序,12是一樣的,顯示的指明入口,這也是推薦的方法,沒人會覺得程式設計師故弄玄虛是什麼好事情。3是聯結器的智慧吧,而45就是無奈的選擇了,程式設計師沒幹好的事情

CPU只要猜著來處理了,有.text段的話就從它開始執行吧,連.text都沒有的就從0x00000000開始執行

關於定義變數,其實一般的指令碼都會有的,目的只有一個,給彙編啟動程式碼提地址資訊。

比如說,一段需要清零的區域在腳本里定義了,而指令碼自己不是變形金剛,他不能主動給你清零的,需要你自己的啟動程式碼來清零,清零的程式碼當然在彙編的啟動程式碼裡,它怎麼知道需要清零的記憶體在什麼地方?就靠腳本里定義的變量了。沒錯,事情就是這樣的,那也就說一定會有一個提取地址的方法將地址賦給變量了哦,yes!就是小小的一個點"."

RAM_START= .;

定義了一個RAM_START變數,地址是當前的地址,什麼是當前的地址啊?就是連結器在連線的時候根據前面的段排列後的當前位置。當然也可以設定當前位置的值,不過最好不要小於前面排列需要的最小記憶體。

.= 0x00000000

定義當前地址為0x0

—————————————3:描述輸入輸出檔案的連結規則——————————

MEMORY

它是用來補充SECTIONS命令的,用來描述目標CPU中可用的記憶體區域。它是可選的,如果沒有這個命令,LD會認為SECTIONS描述的相鄰的記憶體塊之間有足夠可用的記憶體。其實很容易理解但是卻很少用(我沒用過,嘿嘿),在SECTIONS中每個段的分佈都沒有考慮ARM能夠定址的地址中,ROMRAMFLASH是不是連續的。如果不是連續的怎麼辦?MEMORY就是設定各個區的起始位置,大小,屬性的命令,在一個指令碼中只能有一個。

舉一個例子:

如果你的板子有兩段儲存,而且很遺憾的是不是連續的,一段是從0x0開始,大小為256K,另一段是從0x40000000開始的大小為4M,你可以在指令碼中寫入如下的程式碼來描述你的板子的記憶體資訊。

MEMORY

{

rom(rx) : ORIGIN = 0, LENGTH = 256K

ram(!rx) : org = 0x40000000, l = 4M

}

MEMORY命令的語法是:

MEMORY
{
     name (attr) : ORIGIN = origin, LENGTH = len
     ...
}

name:一個使用者定義的名字,Linker將在內部使用它,所以別把它和SECTIONS裡用到的檔名,段名等搞重複了,它要求是獨一無二的。

attr :如同它的名字一樣,這是記憶體段的屬性描述。

`R'   Read-only sections.
`W'   Read/write sections.
`X'   Sections containing executable code.
`A'   Allocated sections.
`I'     Initializedsections.
`L'    Same as I.
`!'   Invert the sense of any of the following attributes.

ORIGIN:這是起始地址

LENGTH:段長

由此可見上面那段例項顯示ROMRAM的明確位置,而且還顯示了他們的職能,一個存程式碼,一個除了存程式碼什麼都可以。

SECTIONS

它是指令碼檔案中最重要的元素,不可預設。它的作用就是用來描述輸出檔案的佈局。

SECTIONS命令的語法:

SECTIONS

{
      ...
      secname start BLOCK(align)(NOLOAD) : AT ( ldadr )
      { contents} >region :phdr =fill
      ...
}

這麼多的引數中,只有secnamecontents是必須的,其他都是可選的引數。也就說它的最簡單的格式就是:

SECTIONS

{
      ...
      secname  : {

contents


     ...
}

但是注意:secname前後的兩個空格是必須的,否則就是不合法輸入。

secname定義了段名,其實最開始就忽略了一個重要的因素,arm-gcc-ld指令碼需要描述輸入和輸出,而表面上一看卻看不出來什麼是輸入什麼事輸入,其實secnamecontents就是描述這兩個資訊的引數。secname是輸出檔案的段,即輸出檔案有哪些段,而contents就是描述輸出檔案的這個段從哪些檔案裡抽取而來。明確這個了就不難理解為什麼SECTIONS命令什麼都可以不要就是不能沒有這兩個引數了。

secname:定義段,但是別以為定義的段一定要是教科書上寫的.data.text這些科班的必須品,你甚至可以建立一個段來放一個美女的圖片。

contents:它的語法開始複雜起來了,但是你可以簡單的把輸入檔案寫到程式碼中:

.data: { main.o led.o}

但是結果被列的目標檔案中所有的程式碼都被連結到.data中去了,顯然不大符合我們的要求啊。那麼還有一種寫法:

.data: {

main.o.data

main.o.text//也可以這樣寫main.o(.data .text)或者main.o(.data, .text)

led.o.data

}

這個寫法讓只有被選中的檔案的特殊段被連結到輸出檔案的.data段了。當然,我們似乎還有更好的寫法:

.data: {

*.data

}

這樣的話,所有目標檔案的.data段都被連線到了輸出檔案中了(這似乎是最常用的方法)。

start:強制連結地址。在SECTIONS中,各個段是按次序排列的,前一個段用到什麼地方下一個段接著用,而start就是強迫連結器將當前的段連線到指定的地址中。

.data 0x400000000 : { ..... }

BLOCK(align):用的比較多的是ALIGN4)這樣的標記,表示排列地址的時候按4的倍數排列,這樣做的理由很簡單,系統會快。

ATaddr):實現存放地址和載入地址不一致的功能,AT表示在檔案中存放的位置,而在記憶體裡呢,按照普通方式儲存。

>region:好戲來了,這個region就是前面說的MEMORY命令定義的位置資訊。表明當前section所放置的mem有什麼特點

註釋:

 和c語言一樣,/**/

SECTIONS

{

.=0x30000000;

.text: { *(.text) }

.data: { *(.data) }

.rodata: { *(.rodata) }

Image_ZI_Base= .;

.bss: { *(.bss) }

Image_ZI_Limit= .;

.debug_info 0 : { *(.debug_info) }

.debug_line 0 : { *(.debug_line) }

.debug_abbrev 0 : { *(.debug_abbrev)}

.debug_frame 0 : { *(.debug_frame) }

}
PROVIDE(__stack = .);

end= .;

_end= .;

__bss_start__= .;

__bss_end__= .;

__EH_FRAME_BEGIN__= .;

__EH_FRAME_END__= .;

Image_RO_Limit= .;

Image_RW_Base= .;

Image_RO_Base= .;

Image_RW_Limit= .;

相關推薦

連結指令碼與重定位

目錄 連結指令碼與重定位 總結 連結指令碼格式 COMM段BSS段 elf和bin檔案 獲得連結指令碼的值 重定位 1-直接指定資料段位置(程式碼黑洞) 2-分散載入(資料段) 3-全域性重定位(一體式

Link.ld 連結指令碼記憶體解析

#include <stdio.h> #include <string.h> #include <stdlib.h> unsigned int  bss_test_array[1024 * 1024]; unsigned int 

簡單的ld連結指令碼學習

一、 連結指令碼的整體認識 什麼是連結檔案呢?作用是什麼呢? 當編寫了多個C檔案時,我們將他們編譯連結成一個可執行的檔案,此時就需要用到連結指令碼檔案(ld)。ld指令碼主要功能就是:將多個目標檔案(.o)和庫檔案(.a)連結成一個可執行的檔案。 連結指令碼檔案

gnu連結指令碼lds介紹

因為這篇文章被轉載了好多手,已經不知道原文在哪裡了,覺的看中文比較舒適,就轉過來了,感謝原文作者。 連線指令碼的格式 ==================== 連線指令碼是文字檔案. 你寫了一系列的命令作為一個連線指令碼. 每一個命令是一個帶有引數的關鍵字,或者是一個對

IAR ILINK 連結指令碼

sections在地址空間中的存放是由ILINK連結器來實現的,而ILINK連結器是按照使用者在ICF檔案中的規定來放置sections的,所以理 解ICF檔案的內容尤其重要。 一個標準的ICF檔案可包括下面這些內容: 1.     &n

Linux之lds連結指令碼學習筆記

簡單例子 以下指令碼將輸出檔案的text section定位在0x10000,data section定位在0x800000: SECTIONS { . = 0×10000; .text : { *(.text) } . = 0×8000000; .dat

imx6q 平臺2016版 u-boot連結指令碼詳解

醞釀許久,關於uboot終於開篇;因為最近一直在使用imx6q平臺進行Linux應用開發,但是我對imx6q的外圍不是很熟悉,而且系統也不是我從頭搭建的,總感覺心裡沒底,這樣做事不是我的風格;所以有點空閒之後,決定把imx6平臺的uboot、Linux整體再捋一遍,這樣我睡覺都踏實一點;同時

uboot.lds 連結指令碼語法規則

 這是網上找到一篇關於連結指令碼語法規則非常詳細的介紹,儲存到部落格內,以便日後需要時查閱。以下是正文: 連線指令碼的格式 ==================== 連線指令碼是文字檔案. 你寫了一系列的命令作為一個連線指令碼. 每一個命令是一個帶有引數的關鍵字,

爬取網易雲音樂MP3連結指令碼

程式碼部分 #Python 3.5 #Author: A_lPha #Blog: http://blog.csdn.net/a_lpha import json from urllib.request import urlopen from ur

arm-linux-ld命令 ld連結指令碼(不錯,推薦可以學習一些lds連結指令碼檔案)

OUTPUT_FORMAT("elf32&shy;littlearm", "elf32&shy;littlearm", "elf32&shy;littlearm") ;指定輸出可執行檔案是elf格式,32位ARM指令,小端 OUTPUT_ARCH(arm) ;指定輸出可執行檔案的平臺為

Uboot之u-boot.lds的連結指令碼

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) //指定程式的入口點,在start.s中的_start。

連結指令碼檔案的寫法

對於.lds檔案,它定義了整個程式編譯之後的連線過程,決定了一個可執行程式的各個段的儲存位置。雖然現在我還沒怎麼用它,但感覺還是挺重要的,有必要了解一下。 先看一下對.lds檔案形式的完整描述: SECTIONS {... secname start BLOCK(al

ARM:Makefile編寫、連結指令碼編寫、裸板shell框架

《Makefile編寫、連結指令碼編寫、裸板shell框架》<tips>' 工具:UtraEdit 程式碼編輯工具// 此工具裡面 Ctrl + h 檢視ASCII碼<tips>vi中命令模式下:':e main.c   // 開啟main.c':b

連結指令碼

指令碼的主要目的是描述如何把輸入檔案中的節(sections)對映到輸出檔案中,並控制 輸出檔案的儲存佈局。 1:輸出什麼 2:輸入是什麼,那麼obj檔案 3:要用什麼庫,庫放在什麼地方 4:記憶體分佈地址 5:提供啟動程式碼一些全域性地址變數 —————

LD說明文件--3.LD連結指令碼

原文 注:文中大部分文章參考引用都是自身的引用,為了不產生混淆,各個章節標題使用英文原稱,同時參考引用也用英文原稱。 每個連結都由一個連結指令碼控制。這個指令碼由連結命令語言編寫。 連結指令碼的主要目的是描述輸入檔案中的段應當如何對映到輸出檔案中,並控制輸

GNU-ld連結指令碼淺析

0. Contents1. 概論2. 基本概念3. 指令碼格式4. 簡單例子5. 簡單指令碼命令6. 對符號的賦值7. SECTIONS命令8. MEMORY命令9. PHDRS命令10. VERSION命令11. 指令碼內的表示式12. 暗含的連線指令碼1. 概論 每一個連

嵌入式程式設計第三篇:MDK中連結指令碼解析

     微控制器程式設計使用 MDK時不可避免的要涉及到連結指令碼檔案。在連結指令碼中可以指定程式

用shell實現一個小指令碼,用來同來統計自己某個檔案下的程式碼,總的程式碼行數,總的註釋量,總的空行量?支援遍歷查詢,支援軟連結查詢

[[email protected] yunwei]# cat sum_code_row_version1.4.sh #!/bin/bash # File Name: sum_code_row.sh # Author: Liwqiang # mail: [email

Linux操作入門練習之shell指令碼附答案(點選文末連結

資料共享與整合技術 練習5 1、編寫shell指令碼,計算1-100的和; 指令碼: 結果驗證: 2、將一目錄下所有檔案的副檔名改為bak 指令碼: 驗證; 3、寫一個指令碼,統計/etc目錄下共有多少個目錄檔案 驗證: 4、寫一個指令碼, 依次向/etc/p

推薦《LinuxShell命令列及指令碼程式設計例項詳解》附下載連結

本書較全面地介紹了LinuxShell的知識點,以Bash為基礎,從LinuxShell的起源開始,到Shell中常用的命令,然後講述了Shell指令碼程式設計的基礎知識和Shell的條件語句、迴圈語句、函式、正則表示式、Shell指令碼中的輸入處理、重定向和Shell管道及