日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

彻底弄懂dalvik字节码【一】

發(fā)布時間:2025/3/15 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 彻底弄懂dalvik字节码【一】 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

之前曾經(jīng)簡單跟蹤過代碼,知道dalvik的字節(jié)碼是可以支持解釋執(zhí)行的,所謂的解釋執(zhí)行,其實就是c/c++編寫的用于解釋并執(zhí)行dalvik字節(jié)碼的程序,說白了就是dalvik字節(jié)碼到cpu字節(jié)碼的轉換。

之前的理解算是囫圇吞棗,最近有時間,好好跟了一遍dalvik的代碼,算是弄明白了細節(jié)。

我們從dvmCallMethod開始來跟一遍dalvik執(zhí)行方法的過程:

void dvmCallMethod(Thread* self, const Method* method, Object* obj,JValue* pResult, ...) {va_list args;va_start(args, pResult);dvmCallMethodV(self, method, obj, false, pResult, args);va_end(args); }

直接調(diào)用dvmCallMethodV:

void dvmCallMethodV(Thread* self, const Method* method, Object* obj,bool fromJni, JValue* pResult, va_list args) {const char* desc = &(method->shorty[1]); // [0] is the return type.int verifyCount = 0;ClassObject* clazz;u4* ins;clazz = callPrep(self, method, obj, false);if (clazz == NULL)return;/* "ins" for new frame start at frame pointer plus locals */ins = ((u4*)self->interpSave.curFrame) +(method->registersSize - method->insSize);//ALOGD(" FP is %p, INs live at >= %p", self->interpSave.curFrame, ins);/* put "this" pointer into in0 if appropriate */if (!dvmIsStaticMethod(method)) { #ifdef WITH_EXTRA_OBJECT_VALIDATIONassert(obj != NULL && dvmIsHeapAddress(obj)); #endif*ins++ = (u4) obj;verifyCount++;}while (*desc != '\0') {switch (*(desc++)) {case 'D': case 'J': {u8 val = va_arg(args, u8);memcpy(ins, &val, 8); // EABI prevents direct storeins += 2;verifyCount += 2;break;}case 'F': {/* floats were normalized to doubles; convert back */float f = (float) va_arg(args, double);*ins++ = dvmFloatToU4(f);verifyCount++;break;}case 'L': { /* 'shorty' descr uses L for all refs, incl array */void* arg = va_arg(args, void*);assert(obj == NULL || dvmIsHeapAddress(obj));jobject argObj = reinterpret_cast<jobject>(arg);if (fromJni)*ins++ = (u4) dvmDecodeIndirectRef(self, argObj);else*ins++ = (u4) argObj;verifyCount++;break;}default: {/* Z B C S I -- all passed as 32-bit integers */*ins++ = va_arg(args, u4);verifyCount++;break;}}}#ifndef NDEBUGif (verifyCount != method->insSize) {ALOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount,method->insSize, clazz->descriptor, method->name);assert(false);goto bail;} #endif//dvmDumpThreadStack(dvmThreadSelf());if (dvmIsNativeMethod(method)) {TRACE_METHOD_ENTER(self, method);/** Because we leave no space for local variables, "curFrame" points* directly at the method arguments.*/(*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult,method, self);TRACE_METHOD_EXIT(self, method);} else {dvmInterpret(self, method, pResult);}#ifndef NDEBUG bail: #endifdvmPopFrame(self); }

解釋一下這個函數(shù):

  • 先分配了棧幀,通過callPrep
  • 參數(shù)入棧
  • 執(zhí)行方法 通過dvmInterpret (暫時只分析普通的method,不考慮jni method)
  • 彈出棧幀
  • 看一下棧幀分配:

    static ClassObject* callPrep(Thread* self, const Method* method, Object* obj,bool checkAccess) {ClassObject* clazz;#ifndef NDEBUGif (self->status != THREAD_RUNNING) {ALOGW("threadid=%d: status=%d on call to %s.%s -",self->threadId, self->status,method->clazz->descriptor, method->name);} #endifassert(self != NULL);assert(method != NULL);if (obj != NULL)clazz = obj->clazz;elseclazz = method->clazz;IF_LOGVV() {char* desc = dexProtoCopyMethodDescriptor(&method->prototype);LOGVV("thread=%d native code calling %s.%s %s", self->threadId,clazz->descriptor, method->name, desc);free(desc);}if (checkAccess) {/* needed for java.lang.reflect.Method.invoke */if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->interpSave.curFrame),method)){/* note this throws IAException, not IAError */dvmThrowIllegalAccessException("access to method denied");return NULL;}}/** Push a call frame on. If there isn't enough room for ins, locals,* outs, and the saved state, it will throw an exception.** This updates self->interpSave.curFrame.*/if (dvmIsNativeMethod(method)) {/* native code calling native code the hard way */if (!dvmPushJNIFrame(self, method)) {assert(dvmCheckException(self));return NULL;}} else {/* native code calling interpreted code */if (!dvmPushInterpFrame(self, method)) {assert(dvmCheckException(self));return NULL;}}return clazz; }

    核心是dvmPushInterpFrame:

    static bool dvmPushInterpFrame(Thread* self, const Method* method) {StackSaveArea* saveBlock;StackSaveArea* breakSaveBlock;int stackReq;u1* stackPtr;assert(!dvmIsNativeMethod(method));assert(!dvmIsAbstractMethod(method));stackReq = method->registersSize * 4 // params + locals+ sizeof(StackSaveArea) * 2 // break frame + regular frame+ method->outsSize * 4; // args to other methodsif (self->interpSave.curFrame != NULL)stackPtr = (u1*) SAVEAREA_FROM_FP(self->interpSave.curFrame);elsestackPtr = self->interpStackStart;if (stackPtr - stackReq < self->interpStackEnd) {/* not enough space */ALOGW("Stack overflow on call to interp ""(req=%d top=%p cur=%p size=%d %s.%s)",stackReq, self->interpStackStart, self->interpSave.curFrame,self->interpStackSize, method->clazz->descriptor, method->name);dvmHandleStackOverflow(self, method);assert(dvmCheckException(self));return false;}/** Shift the stack pointer down, leaving space for the function's* args/registers and save area.*/stackPtr -= sizeof(StackSaveArea);breakSaveBlock = (StackSaveArea*)stackPtr;stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);saveBlock = (StackSaveArea*) stackPtr;#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)/* debug -- memset the new stack, unless we want valgrind's help */memset(stackPtr - (method->outsSize*4), 0xaf, stackReq); #endif #ifdef EASY_GDBbreakSaveBlock->prevSave =(StackSaveArea*)FP_FROM_SAVEAREA(self->interpSave.curFrame);saveBlock->prevSave = breakSaveBlock; #endifbreakSaveBlock->prevFrame = self->interpSave.curFrame;breakSaveBlock->savedPc = NULL; // not requiredbreakSaveBlock->xtra.localRefCookie = 0; // not requiredbreakSaveBlock->method = NULL;saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);saveBlock->savedPc = NULL; // not requiredsaveBlock->xtra.currentPc = NULL; // not required?saveBlock->method = method;LOGVV("PUSH frame: old=%p new=%p (size=%d)",self->interpSave.curFrame, FP_FROM_SAVEAREA(saveBlock),(u1*)self->interpSave.curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));self->interpSave.curFrame = FP_FROM_SAVEAREA(saveBlock);return true; }

    這段代碼比較長,我分析了一下,繪制了一張圖幫助理解:



    即分配一個棧幀時,會從棧頂方向向下依次分配breakSaveBlock、registers(其中又依次是params和本地變量)、saveBlock,然后將curFrame指向saveBlock的高邊緣地址。同時還建立一些prevFrame的索引關系,參見圖。

    當棧幀分配后,回到dvmCallMethodV,依次將參數(shù)壓入剛剛分配的棧幀的registers中的params處,參數(shù)序號和地址依次升高。

    當壓入?yún)?shù)后,調(diào)用dvmInterpret開啟對方法的解釋執(zhí)行,執(zhí)行完后結果通過pResult獲取,最后調(diào)用dvmPopFrame彈出之前分配的棧幀。

    從dvmInterpret開始就是重點了,通過跟一遍代碼,我們可以知道字節(jié)碼的格式,以及dalvik的解釋執(zhí)行過程。

    內(nèi)容有點多,分幾篇來寫。



    作者:difcareer
    鏈接:http://www.jianshu.com/p/02250d7f9ff4
    來源:簡書
    著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。

    總結

    以上是生活随笔為你收集整理的彻底弄懂dalvik字节码【一】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲精品国产欧美 | 亚洲清色| 涩av| 午夜视频免费 | 国产精品美女在线 | www.亚洲天堂 | 亚洲一二三不卡 | 美女一区 | 自拍偷拍一区 | 成人女同av免费观看 | 久久午夜夜伦鲁鲁片无码免费 | 麻豆中文字幕 | 93久久精品日日躁夜夜躁欧美 | 久久欲 | 人人色网 | 91桃色视频 | 波多野吉衣av在线 | 欧美久久久久久久久久久 | 久久国语对白 | 免费成人深夜在线观看 | 撸啊撸av | 亚洲精品lv | 国产色视频在线 | 草逼视频免费看 | 天天性综合 | av看片资源 | 亚洲综合涩 | 久久久久亚洲日日精品 | 又色又爽又黄gif动态图 | 青娱乐福利视频 | 精品播放| 一区二区三区在线视频播放 | 日韩国产一级 | 久久久久亚洲av成人网人人网站 | 波多野结衣视频观看 | 性色av一区二区三区免费 | 91精品国产成人 | 日日摸日日添日日碰9学生露脸 | 欧美日韩视频在线 | 污视频在线观看免费 | 日韩123| 日韩美女在线 | 姐姐你真棒插曲快来救救我电影 | 久久成年 | 午夜亚洲国产 | 包射屋 | 国产女主播一区二区 | 一区二区视频免费在线观看 | 黄色大片91| 日韩欧美日本 | 欧美999 | 黄色三级三级三级 | 亚洲综合av一区 | 兄弟兄弟全集免费观看 | 最新的黄色网址 | 先锋影音一区二区 | 少妇av网 | 免费一区二区视频 | 久久久久成人精品 | 国产精品99久久免费黑人人妻 | 少妇一级淫片免费放播放 | 艳妇乳肉豪妇荡乳av无码福利 | 一级v片| 大象传媒成人在线观看 | 亚洲午夜精品福利 | 另一种灿烂生活 | 艳妇臀荡乳欲伦交换在线看 | 午夜色网 | 杨幂一区二区三区免费看视频 | 日韩精品一区三区 | 玖玖五月 | 国产精品资源 | 精品国产一区二区在线观看 | 久操社区| 日本一区二区三区四区在线观看 | 久久久久久久久久久久Av | 国产精品久久久久久久久免费相片 | xxxwww18| 少妇系列在线观看 | 中文日韩 | 天天摸天天碰天天爽天天弄 | 欧美色图亚洲自拍 | 欧美猛交免费 | 日韩毛片大全 | 黄免费在线观看 | 三级亚洲 | 奇米影视网 | 亚洲欧美另类综合 | 一区二区三区四区精品 | 秘密基地电影免费版观看国语 | 中文字幕免费中文 | 日韩精品无码一区二区三区久久久 | 国产一区二区久久精品 | 久久久久久久久久99精品 | 在线视频观看国产 | 美女视频久久久 | 福利一区福利二区 | av天天看| 中国挤奶哺乳午夜片 |