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:測試
.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標準。