今天研究了下elf格式和鏈結過程,權且自己理解,以便備忘,諸多問題,還值得商榷。
目前自己用過的elf不外乎兩種:編譯生成的可重定位檔案,連線生成的可執行檔案。對於elf檔案,結構輪廓為
不過就目前看來,似乎用ld連線出來的可執行檔案都有節區頭部表,應該是為了附帶一些資訊。對於elf檔案可用工具對其結構進行分析,這樣比直接分析其二進位製碼檔案方便些。
(上圖為可重定位檔案結構)
(上圖為可執行檔案結構)
對於elf檔案各個子項都有其含義,較為繁瑣,可檢視《elf 檔案格式分析》幫助理解。
接下來分析下關於對於目標檔案為elf檔案的連線過程:
對於聯結器而言,其連線的基本單位為各個可重定位檔案的節區,也就是說聯結器可以為可重定位檔案的節區(section)指定其在連線後生成的目標檔案(可執行檔案)中的位置,包括其在檔案內的位置和當其載入到記憶體後的位置,當確定好各個節區的位置後,聯結器便可根據其位置和符號表,重定位表等資訊,填入確定的位址資訊,變生成可執行檔案。這也就是聯結器的工作。
對於ld來說,在linux下可用lds檔案來指定連線具體過程,例:
entry(_start)
sections
second 0xb0004000 : at(2048)
}
這裡指定了檔案的入口點為_start,它表示在這幾個可重定位檔案的原始檔內有乙個_start的標號,當載入生成的可執行檔案後,其入口點便為_start處的位址,這一點體現在elf檔案的elf header裡,其表項有乙個e_entry,該值便指定了入口位址,至於該值的的得出,是由於當指定好了各個區段的位置後,_start處**載入到記憶體的位置可以計算得出,當解決好入口位址後,便是具體指定各個節區的位置了。
在sections裡面,指定了兩項,便是可執行檔案一共有兩個程式段(仍然可以有節表和節表頭,往往乙個程式段便是乙個節表項,上圖節表項1,2便是first,second,節表0是指elf頭,無意義,後面的節表項,實際意義不大),並且也指定了,載入到記憶體後的位址和檔案內部偏移,此處易誤解的地方為後面是*.o檔案,而不是節區,個人實驗來看,當後面是檔案,而不是節區時,意味著,把該檔案的所有需要在「記憶體申請空間」的節區(個人理解,一般來說就是.text和.data)放在一起,接下來又放第二個檔案的節區,這裡需要注意的是,將各個檔案的節區任意擺布,只要正確的設定了入口點,那麼程式都會正確按照程式邏輯執行,這是因為無論節區如何擺布,聯結器總會用根據指定的位址,計算出應該跳轉到的位址,也即是說,只要按照程式段頭的資訊載入該程式,然後設定正確的入口點,那麼程式便可以正確執行。
個人認為,若在pc上執行程式,並無必要自己來指定程式應擺布在何處,主要是由於在嵌入式開發時,需要在向ram中移動**或進行mmu等操作時,才需要指定連線位址,以便容易直接操作。另外需要注意的是,對於ld聯結器,沒有提供lds檔案鏈結檔案時,ld有自己預設的lds,其中**較為複雜,不作分析。
DTS結構及其編譯方法
dts 結構及其編譯方法 一 主要問題 1,需要了解dtsi 與dts 的關係2,dts 的結構模型 3,dts 是如何被編譯的,以及編譯後會生成乙個什麼檔案.二 參考文字 dts 檔案是一種ascii 文字格式的devicetree 描述。基本上,在armlinux 內,乙個.dts 檔案對應乙個...
dts 編譯過程 DTS結構及其編譯方法
一 主要問題 1,需要了解dtsi與dts的關係 2,dts的結構模型 3,dts是如何被編譯的,以及編譯後會生成乙個什麼檔案.二 參考文字 1,dts device tree source dts檔案是一種ascii文字格式的devicetree描述。基本上,在armlinux內,乙個.dts檔案...
DT系列一 DTS結構及其編譯方法
dts 結構及其編譯方法 一 主要問題 1,需要了解dtsi 與dts 的關係2,dts 的結構模型 3,dts 是如何被編譯的,以及編譯後會生成乙個什麼檔案.二 參考文字 dts 檔案是一種ascii 文字格式的devicetree 描述。基本上,在armlinux 內,乙個.dts 檔案對應乙個...