cpp/profiler/DalvikUtils.cpp (128 lines of code) (raw):

/** * Copyright 2004-present, Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "DalvikUtils.h" #include <string.h> namespace facebook { namespace profilo { namespace profiler { const DexProtoId* getProtoId(const DexProto* pProto) { return &pProto->dexFile->pProtoIds[pProto->protoIdx]; } const DexTypeList* dexGetProtoParameters( const DexFile* pDexFile, const DexProtoId* pProtoId) { if (pProtoId->parametersOff == 0) { return nullptr; } return (const DexTypeList*)(pDexFile->baseAddr + pProtoId->parametersOff); } u4 dexTypeListGetIdx(const DexTypeList* pList, u4 idx) { const DexTypeItem* pItem = &pList->list[idx]; return pItem->typeIdx; } const char* dexStringById(const DexFile* pDexFile, u4 idx) { const DexStringId* pStringId = &pDexFile->pStringIds[idx]; const u1* str = pDexFile->baseAddr + pStringId->stringDataOff; // Skip the uleb128 length. while (*(str++) > 0x7f) ; /* empty */ return (const char*)str; } const char* dexStringByTypeIdx(const DexFile* pDexFile, u4 idx) { const DexTypeId* pTypeId = &pDexFile->pTypeIds[idx]; return dexStringById(pDexFile, pTypeId->descriptorIdx); } int dexProtoCompare(const DexProto* pProto1, const DexProto* pProto2) { if (pProto1 == pProto2) { return 0; } else { const DexFile* dexFile1 = pProto1->dexFile; const DexProtoId* protoId1 = getProtoId(pProto1); const DexTypeList* typeList1 = dexGetProtoParameters(dexFile1, protoId1); int paramCount1 = (typeList1 == nullptr) ? 0 : typeList1->size; const DexFile* dexFile2 = pProto2->dexFile; const DexProtoId* protoId2 = getProtoId(pProto2); const DexTypeList* typeList2 = dexGetProtoParameters(dexFile2, protoId2); int paramCount2 = (typeList2 == nullptr) ? 0 : typeList2->size; if (protoId1 == protoId2) { return 0; } int result = strcmp( dexStringByTypeIdx(dexFile1, protoId1->returnTypeIdx), dexStringByTypeIdx(dexFile2, protoId2->returnTypeIdx)); if (result != 0) { return result; } int minParam = (paramCount1 > paramCount2) ? paramCount2 : paramCount1; int i; for (i = 0; i < minParam; i++) { u4 idx1 = dexTypeListGetIdx(typeList1, i); u4 idx2 = dexTypeListGetIdx(typeList2, i); result = strcmp( dexStringByTypeIdx(dexFile1, idx1), dexStringByTypeIdx(dexFile2, idx2)); if (result != 0) { return result; } } if (paramCount1 < paramCount2) { return -1; } else if (paramCount1 > paramCount2) { return 1; } else { return 0; } } } int compareMethodStr(DexFile* pDexFile, u4 methodIdx, const Method* method) { const DexMethodId* pMethodId = &pDexFile->pMethodIds[methodIdx]; const char* str = dexStringByTypeIdx(pDexFile, pMethodId->classIdx); int result = strcmp(str, method->clazz->descriptor); if (result == 0) { str = dexStringById(pDexFile, pMethodId->nameIdx); result = strcmp(str, method->name); if (result == 0) { DexProto proto; proto.dexFile = pDexFile; proto.protoIdx = pMethodId->protoIdx; result = dexProtoCompare(&proto, &method->prototype); } } return result; } u4 getMethodIdx(const Method* method) { ClassObject* cls = method->clazz; DvmDex* dvmDex = cls->pDvmDex; // Can be null for VM-generated classes: e.g. arrays and Proxy classes. if (dvmDex == nullptr) { return 0; } DexFile* pDexFile = dvmDex->pDexFile; u4 hi = pDexFile->pHeader->methodIdsSize - 1; u4 lo = 0; u4 cur; while (hi >= lo) { int cmp; cur = (lo + hi) / 2; cmp = compareMethodStr(pDexFile, cur, method); if (cmp < 0) { lo = cur + 1; } else if (cmp > 0) { hi = cur - 1; } else { break; } } return cur; } u4 getDexSignatureFromMethod(const Method* method) { DvmDex* dvmDex = method->clazz->pDvmDex; if (dvmDex == nullptr) { return 0; } return *((u4*)dvmDex->pHeader->signature); } int64_t dalvikGetMethodIdForSymbolication(const Method* method) { u8 methodId = (u8)getMethodIdx(method); u4 dexSignature = getDexSignatureFromMethod(method); return methodId << 32 | dexSignature; } } // namespace profiler } // namespace profilo } // namespace facebook