日韩性视频-久久久蜜桃-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)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 成人在线国产视频 | 四虎免费久久 | 最近中文字幕免费mv视频7 | 成人精品国产免费网站 | 天堂国产 | 午夜免费看视频 | 国产人妻大战黑人20p | 51热门大瓜今日大瓜 | 揉我啊嗯~喷水了h视频 | 日韩欧美aaa| 91射| 欧美做受视频 | 亚洲综合精品一区 | 日韩av电影手机在线观看 | 天天草天天操 | 日韩av成人网 | 亚洲黄在线观看 | 日本一区二区精品 | 福利小视频在线观看 | 亚洲精品国产精品乱码视色 | 亚洲小说网| 免费成人深夜夜行p站 | 高清乱码免费看污 | 午夜精品福利在线观看 | 武侠古典av | aa视频网站 | 成人性做爰aaa片免费看不忠 | 欧美成人国产精品高潮 | 火影忍者羞羞漫画 | 国产a∨精品一区二区三区仙踪林 | 亚洲伊人精品 | 日韩中文字幕网 | 长篇乱肉合集乱500小说日本 | 日本aaa视频 | 男女视频一区二区 | 久久男人的天堂 | 影音先锋在线看 | kk视频在线观看 | 天天av综合| 欧美日韩精品一区二区在线播放 | 日日干日日摸 | 中文字幕xxxx | 日韩色资源 | 一本之道av| 91天天看| 精人妻无码一区二区三区 | 国产精品综合久久久 | 丁香亚洲 | 日本福利一区二区三区 | 美女扒开尿口来摸 | 在线播放免费av | 九色自拍 | 91av在| 人妖一级片 | 亚洲少妇精品 | 日本网站在线免费观看 | 性色av一区二区 | 成人自拍网| 亚洲成人黄色小说 | 精品视频免费在线观看 | 色婷婷av一区二区 | 天天躁日日躁狠狠躁喷水 | 国产一区黄 | 夜夜操夜夜 | 日本69熟| 青娱乐最新视频 | 一级黄av | 台湾三级伦理片 | 成人免费播放 | 超碰色人阁| 正在播放老肥熟妇露脸 | 日韩aaaaa| 国产精品suv一区二区 | 欧美一区二区三区小说 | 天天干网址 | 播五月婷婷| 欧美成人三级 | 久久一级片| 美女黄色真播 | 亚洲制服在线观看 | 丝袜av电影| 青青草手机在线观看 | 亚洲成人7777| 中文字幕99 | 在线观看视频福利 | 欧美成人黄 | 精品中文字幕在线播放 | 日韩视频一区在线观看 | 日韩字幕在线观看 | 91精品国产91久久久久久黑人 | 高h奶汁双性受1v1 | 国产免费激情视频 | av中文字幕一区 | 亚洲色图在线观看 | 亚洲视频一区 | 久久伊人中文字幕 | 中文字幕日韩专区 | 九热这里只有精品 | 国产一区二区久久 |