Linker

Android Linker:程序員

          http://geek.csdn.net/news/detail/104860?locationNum=11&fps=1數組

關於load_bias_: SO 能夠指定加載基址,可是 SO 指定的加載基址可能不是頁對齊的,這種狀況會致使實際映射地址和指定的加載地址有一個誤差,這個誤差即是 load_bias_,以後在針對虛擬地址進行計算時須要使用 load_bias_ 修正。普通的 SO 都不會指定加載基址,這時min_vaddr = 0,則 load_bias_ = load_start_,即load_bias_ 等於加載基址,下文會將 load_bias_ 直接稱爲基址。函數

 

Section Header:測試

  • .text:已編譯程序的機器代碼。
  • .rodata:只讀數據,好比printf語句中的格式串和開關(switch)語句的跳轉表。
  • .data:已初始化的全局C變量。局部C變量在運行時被保存在棧中,既不出如今.data中,也不出如今.bss節中。
  • .bss:未初始化的全局C變量。在目標文件中這個節不佔據實際的空間,它僅僅是一個佔位符。目標文件格式區分初始化未初始化變量是爲了空間效率在:在目標文件中,未初始化變量不須要佔據任何實際的磁盤空間。
  • .symtab:一個符號表(symbol table),它存放在程序中被定義和引用的函數和全局變量的信息。一些程序員錯誤地認爲必須經過-g選項來編譯一個程序,獲得符號表信息。實際上,每一個可重定位目標文件在.symtab中都有一張符號表。然而和編譯器中的符號表不一樣,.symtab符號表不包含局部變量的表目。
  • .rel.text:當連接噐把這個目標文件和其餘文件結合時,.text節中的許多位置都須要修改。通常而言,任何調用外部函數或者引用全局變量的指令都須要修改。另外一方面調用本地函數的指令則不須要修改。注意,可執行目標文件中並不須要重定位信息,所以一般省略,除非使用者顯式地指示連接器包含這些信息。
  • .rel.data:被模塊定義或引用的任何全局變量的信息。通常而言,任何已初始化全局變量的初始值是全局變量或者外部定義函數的地址都須要被修改
  • .debug:一個調試符號表,其有些表目是程序中定義的局部變量和類型定義,有些表目是程序中定義和引用的全局變量,有些是原始的C源文件。只有以-g選項調用編譯驅動程序時,纔會獲得這張表。
  • .line:原始C源程序中的行號和.text節中機器指令之間的映射。只有以-g選項調用編譯驅動程序時,纔會獲得這張表。
  • .strtab:一個字符串表,其內容包括.symtab和.debug節中的符號表,以及節頭部中的節名字。字符串表就是以null結尾的字符串序列。

 

.data保存初始化過的數據,這是普通程序數據的一部分,能夠在程序運行期間修改。spa

 

.rodata保存了只讀數據,能夠讀取但不能修改,例如printf語句中的全部靜態字符串封裝到該節。.net

.init.fini保存了進程初始化和結束所用的代碼,這一般是由編譯器自動添加的。debug

.hash是一個散列表,容許在不對全表元素進行線性搜索的狀況下,快速訪問全部符號表項。指針

 

符號表機制radelf調試

符號表保存了程序實現或使用的全部全局變量和函數;若是程序引用一個自身代碼未定義的符號,則稱之爲未定義符號,這類引用必須在靜態連接期間用其餘目標模塊或庫解決,或在加載時經過動態連接過程解決。code

實現:

.symtab肯定符號的名稱與其值之間的關聯,其中名稱不是直接以字符串形式出現的,而是表示爲某一字符串數組(.strtab)的索引。

.strtab保存了字符串數組(.shstrtab包含了節名稱字符串表)。

.hash保存了一個散列表,以幫助快速查找符號。

 

Symbol table:

上圖對應下面的結構:

Num Value SIze Type Bind Vis Ndx Name
  ELF64_sym.st_value ELF64_sym.st_size ELF64_sym.st_info ELF64_sym.st_info   ELF64_sym.st_shndx strtab[ELF64_sym.st_name]

 

 

typedef struct elf64_sym {

Elf64_Word st_name;            // 符號名稱,字符串表中的索引

unsigned char st_info;         // 類型:NOTYPE,OBJECT,FUNC和綁定屬性:STB_LOCAL/STB_GLOBAL/STB_WEAK;

unsigned char st_other;        // 語義未定義,0

Elf64_Half st_shndx;           // section header index 相關節的索引,符號將綁定到該節,此外SHN_ABS指定符號是絕對值,不因重定位而改變,SHN_UNDEF標識未定義符號。

Elf64_Addr st_value;           // 符號的值

Elf64_Xword st_size;           // 符號的長度,如一個指針的長度或struct對象中包含的字節數。

}Elf64_Sym;

 

dlopen RTLD_XXX 解析:

RTLD_LAZY:在dlopen返回前,對於動態庫中的未定義的符號不執行解析(只對函數引用有效,對於變量引用老是當即解析)。

RTLD_NOW: 須要在dlopen返回前,解析出全部未定義符號,若是解析不出來,在dlopen會返回NULL,錯誤爲:: undefined symbol: xxxx.......

二、做用範圍,可與解析方式經過「|」組合使用。

RTLD_GLOBAL:動態庫中定義的符號可被其後打開的其它庫解析。

RTLD_LOCAL: 與RTLD_GLOBAL做用相反,動態庫中定義的符號不能被其後打開的其它庫重定位。若是沒有指明是RTLD_GLOBAL仍是RTLD_LOCAL,則缺省爲RTLD_LOCAL。

三、做用方式

RTLD_NODELETE: 在dlclose()期間不卸載庫,而且在之後使用dlopen()從新加載庫時不初始化庫中的靜態變量。這個flag不是POSIX-2001標準。

RTLD_NOLOAD: 不加載庫。可用於測試庫是否已加載(dlopen()返回NULL說明未加載,不然說明已加載),也可用於改變已加載庫的flag,如:先前加載庫的flag爲RTLD_LOCAL,用dlopen(RTLD_NOLOAD|RTLD_GLOBAL)後flag將變成RTLD_GLOBAL。這個flag不是POSIX-2001標準。

 

一、解析方式

RTLD_LAZY:在dlopen返回前,對於動態庫中的未定義的符號不執行解析(只對函數引用有效,對於變量引用老是當即解析)。

RTLD_NOW: 須要在dlopen返回前,解析出全部未定義符號,若是解析不出來,在dlopen會返回NULL,錯誤爲:: undefined symbol: xxxx.......

二、做用範圍,可與解析方式經過「|」組合使用。

RTLD_GLOBAL:動態庫中定義的符號可被其後打開的其它庫解析。

RTLD_LOCAL: 與RTLD_GLOBAL做用相反,動態庫中定義的符號不能被其後打開的其它庫重定位。若是沒有指明是RTLD_GLOBAL仍是RTLD_LOCAL,則缺省爲RTLD_LOCAL。

三、做用方式

RTLD_NODELETE: 在dlclose()期間不卸載庫,而且在之後使用dlopen()從新加載庫時不初始化庫中的靜態變量。這個flag不是POSIX-2001標準。

RTLD_NOLOAD: 不加載庫。可用於測試庫是否已加載(dlopen()返回NULL說明未加載,不然說明已加載),也可用於改變已加載庫的flag,如:先前加載庫的flag爲RTLD_LOCAL,用dlopen(RTLD_NOLOAD|RTLD_GLOBAL)後flag將變成RTLD_GLOBAL。這個flag不是POSIX-2001標準。

相關文章
相關標籤/搜索