入門ART虛擬機(7)——TLS Entry Points

Android安全交流群:478084054

前面筆記貼過老羅博客的一段話(非原文,簡化了一下):

“ART運行時會為類方法生成相應的本地機器指令,這些本地機器指令可能會調(diào)用外部函數(shù),這就涉及到模塊依賴問題,就好像我們在編寫程序時,需要依賴C庫提供的接口一樣。ART運行時支持兩種類型的Backend:Portable和Quick。Portable類型的Backend通過靜態(tài)鏈接器生成本地機器指令,通過重定位技術(shù)來處理模塊依賴問題。這對熟悉linker動態(tài)加載過程的程序員來說很容易理解。而Quick類型的Backend生成的本地機器指令用另外一種方式來處理模塊之間的依賴關系。簡單的說,就是ART運行時會在每一個線程的TLS(線程本地區(qū)域)提供一個函數(shù)表,本地機器指令通過它來調(diào)用其它模塊的函數(shù)。這使得生成的OAT文件在加載時不需要再處理模塊之間的依賴關系,也就省去了重定位,不需要通過系統(tǒng)的動態(tài)鏈接器提供的dlopen來加載。這樣OAT文件在加載時就會更快,這也是稱其為Quick的緣由?!?/p>

本篇筆記就看看這段話中提到的TLS函數(shù)表(還是以6.0源碼為例)。

在ART初始化過程中的Runtime::Init函數(shù)中,有如下代碼:

作用是將當前線程注冊到ART運行時的線程列表中。

繼續(xù)看Thread::Init函數(shù)。

最后調(diào)用thread_list->Register(this),就是將當前線程注冊到ART運行時的線程列表中去。

在這之前,還有一步:InitTlsEntryPoints(),在InitTlsEntryPoints中調(diào)用InitEntryPoints。

調(diào)用InitEntryPoints時傳入的:interpreter_entrypoints、jni_entrypoints、quick_entrypoints三個參數(shù),就是老羅那段話中提到的TLS保存的用于解決模塊依賴關系的函數(shù)表。

這些函數(shù)表在InitEntryPoints函數(shù)中被初始化。

繼續(xù)看InitEntryPoints(以arm版本為例)。

首先初始化interpreter_entrypoints,保存的是解釋器要用到的跳轉(zhuǎn)函數(shù)。

只包含兩項,分別是artInterpreterToInterpreterBridge和artInterpreterToCompiledCodeBridge。前者用于從一個解釋執(zhí)行的類方法跳到另一個也是解釋執(zhí)行的類方法去執(zhí)行,后者用于從一個解釋執(zhí)行的類方法跳到另一個以本地機器指令執(zhí)行的類方法去執(zhí)行。

然后初始化jni_entrypoints,保存的是JNI調(diào)用相關的跳轉(zhuǎn)函數(shù)。

如果在生成的本地機器指令中,需要調(diào)用一個JNI函數(shù),那么就需要先通過art_jni_dlsym_lookup_stub找到正確的JNI函數(shù),然后再執(zhí)行。

剩下的就都是quick_entrypoints的初始化了,覆蓋了所有的Quick后端生成的本地機器指令要用到的跳轉(zhuǎn)函數(shù)。

其中包含了art_quick_to_interpreter_bridge,用于從一個以本地機器指令執(zhí)行的類方法跳到另一個解釋執(zhí)行的類方法去執(zhí)行。

這些跳轉(zhuǎn)表中有很多bridge和trampoline函數(shù),我很想知道它們到底是怎么工作的。后面再去看吧。

感謝老羅博客。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容