[實踐] Android5.1.1源碼,android5.1.1源碼

來源:互聯網
上載者:User

[實踐] Android5.1.1源碼,android5.1.1源碼
[實踐] Android5.1.1源碼 - 讓某個APP以解釋執行模式運行 作者:尋禹@阿里聚安全 前言

本文的實踐修改了Android5.1.1的源碼。

本文只簡單的講了一下原理。在“實踐”一節講了具體做法。

本文的內容涉及Art模式下dex載入的知識,想要詳細瞭解這部分知識可以去看老羅的文章: 

Android運行時ART簡要介紹和學習計劃 

Android運行時ART載入OAT檔案的過程分析 

Android運行時ART載入類和方法的過程分析 

Android運行時ART執行類方法的過程分析

 

本文的內容涉及zygote,如果不知道zygote是什麼,或者好奇zygote如何啟動,可以去看老羅的文章: 
Android系統進程Zygote啟動過程的原始碼分析

 

老羅的文章分析的是Android2.3的源碼,所以下面提到的與zygote有關的函數在老羅的文章裡面可能沒有,如果想要對下面提到的與zygote有關的函數有一個簡單的瞭解可以看我的文章:Android5.1.1源碼 - zygote fork出的子進程如何許可權降級

 

原理簡介怎麼才能讓方法解釋執行

在函數ClassLinker::LinkCode中會連結dex中的方法代碼,這個函數的定義在檔案”art/runtime/class_linker.cc”中,下面是它的源碼(這裡只列出了與本文有關的部分):

在這個函數中調用了NeedsInterpreter函數判斷當前方法是否要解釋執行,如果傳回值為true,即局部變數enter_interpreter被賦值為true,那麼調用ArtMethod類中的SetEntryPointFromQuickCompiledCode函數並將GetQuickToInterpreterBridge()的傳回值傳入,GetQuickToInterpreterBridge()函數返回用於解釋執行的函數的入口地址,這個入口函數解釋執行dex中的方法。

 

那麼現在來看看NeedsInterpreter函數,這個函數的定義在檔案”art/runtime/class_linker.cc”中,下面是它的源碼:

 

當”Runtime::Current()->GetInstrumentation()->InterpretOnly()”返回true且不是本地方法和代理方法,那麼這個函數就會返回true,否則返回false。

 

InterpretOnly函數是Instrumentation類的成員函數,它的函數定義在檔案”art/runtime/instrumentation.h”中,下面是它的源碼:

interpret_only_是類Instrumentation的成員變數,是布爾類型。可以發現InterpretOnly函數僅僅是將”interpret_only_”返回,如果將interpret_only_設定為true,那麼根據上文分析,所有“非本地且非代理”方法都將被解釋執行。

 

那麼如何將interpret_only_設定為true哪,在Instrumentation類中有一個ForceInterpretOnly函數,下面是這個函數的源碼:

 

這個函數是Instrumentation類的公有成員函數,所以直接調用這個函數即可將interpret_only_設定為true。

 

這裡有一個問題,將interpret_only_設定為true,那麼“非本地且非代理”方法在連結代碼時都將被設定成解釋執行,那麼會不會影響到其他的APP進程?不會,因為ClassLinker::LinkCode函數對方法的連結是在APP進程的記憶體中進行的,所以這個操作並不會影響到其他進程。

這裡進行一個小節,當執行”Runtime::Current()->GetInstrumentation()->ForceInterpretOnly()”語句時,會把Instrumentation對象的interpret_only_成員變數設定為true。那麼當方法是“非本地且非代理”方法時,NeedsInterpreter函數將返回true,那麼在ClassLinker::LinkCode函數中會將這個方法設定為解釋執行。

如果要將APP中所有方法都設定為解釋執行,那麼就需要在連結APP的dex中的方法代碼之前執行”Runtime::Current()->GetInstrumentation()->ForceInterpretOnly()”語句。

調用ForceInterpretOnly函數的時機

我的辦法是在EnableDebugFeatures函數中調用ForceInterpretOnly函數,在這一節中會先說明Android如何執行到EnableDebugFeatures函數,然後會說明在EnableDebugFeatures函數中調用ForceInterpretOnly函數的好處。

所有的Android應用進程都是zygote fork出來的,fork APP進程時的函數調用路徑:

調用完ForkAndSpecializeCommon函數後APP進程就被fork出來了。

 

ForkAndSpecializeCommon函數定義在檔案”frameworks/base/core/jni/com_android_internal_os_Zygote.cpp”中,下面它的源碼:

gCallPostForkChildHooks是一個全域變數,它在com_android_internal_os_Zygote.cpp檔案的register_com_android_internal_os_Zygote函數中被初始化。

env->CallStaticVoidMethod(…)語句調用了Java方法”Zygote.callPostForkChildHooks”。

 

下面是Zygote.callPostForkChildHooks方法的源碼,這個方法在檔案”frameworks/base/core/java/com/android/internal/os/Zygote.java”中:

 

VM_HOOKS是Zygote類的成員變數,下面是它的定義:

 

VM_HOOKS.postForkChild調用的就是ZygoteHooks類中的成員方法postForkChild,這個方法在檔案”libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java”中,下面是它的源碼:

 

這個方法中調用了native函數nativePostForkChild,nativePostForkChild函數的C層代碼在檔案”/home/sowuy/android/system/art/runtime/native/dalvik_system_ZygoteHooks.cc”中,下面是它的源碼:

 

我將在EnableDebugFeatures函數中調用ForceInterpretOnly函數,原因有三點:

 

實踐修改Zygote.java中的代碼

Zygote.java檔案的位置是:frameworks/base/core/java/com/android/internal/os/Zygote.java,在Zygote類中添加一個成員變數:

 

在Zygote類forkAndSpecialize方法的開始部分添加下面的代碼:

 修改dalvik_system_ZygoteHooks.cc中的代碼

dalvik_system_ZygoteHooks.cc檔案的位置是:art/runtime/native/dalvik_system_ZygoteHooks.cc,修改這個檔案中的EnableDebugFeatures函數的代碼。

向這個函數中添加下面的代碼:

 

下面是對這個函數修改後的完整代碼:

 

作者:尋禹@阿里聚安全,更多安全技術文章,請訪問阿里聚安全部落格

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.