/* * Copyright (C) 2008 The Android Open Source Project * * 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. */ /* * Functions to deal with class definition structures in DEX files */ #ifndef _LIBDEX_DEXCLASS #define _LIBDEX_DEXCLASS #include "DexFile.h" #include "Leb128.h" /* expanded form of a class_data_item header */ typedef struct DexClassDataHeader { u4 staticFieldsSize; u4 instanceFieldsSize; u4 directMethodsSize; u4 virtualMethodsSize; } DexClassDataHeader; /* expanded form of encoded_field */ typedef struct DexField { u4 fieldIdx; /* index to a field_id_item */ u4 accessFlags; } DexField; /* expanded form of encoded_method */ typedef struct DexMethod { u4 methodIdx; /* index to a method_id_item */ u4 accessFlags; u4 codeOff; /* file offset to a code_item */ } DexMethod; /* expanded form of class_data_item. Note: If a particular item is * absent (e.g., no static fields), then the corresponding pointer * is set to NULL. */ typedef struct DexClassData { DexClassDataHeader header; DexField* staticFields; DexField* instanceFields; DexMethod* directMethods; DexMethod* virtualMethods; } DexClassData; /* Read and verify the header of a class_data_item. This updates the * given data pointer to point past the end of the read data and * returns an "okay" flag (that is, false == failure). */ bool dexReadAndVerifyClassDataHeader(const u1** pData, const u1* pLimit, DexClassDataHeader *pHeader); /* Read and verify an encoded_field. This updates the * given data pointer to point past the end of the read data and * returns an "okay" flag (that is, false == failure). * * The lastIndex value should be set to 0 before the first field in * a list is read. It is updated as fields are read and used in the * decode process. * * The verification done by this function is of the raw data format * only; it does not verify that access flags or indices * are valid. */ bool dexReadAndVerifyClassDataField(const u1** pData, const u1* pLimit, DexField* pField, u4* lastIndex); /* Read and verify an encoded_method. This updates the * given data pointer to point past the end of the read data and * returns an "okay" flag (that is, false == failure). * * The lastIndex value should be set to 0 before the first method in * a list is read. It is updated as fields are read and used in the * decode process. * * The verification done by this function is of the raw data format * only; it does not verify that access flags, indices, or offsets * are valid. */ bool dexReadAndVerifyClassDataMethod(const u1** pData, const u1* pLimit, DexMethod* pMethod, u4* lastIndex); /* Read, verify, and return an entire class_data_item. This updates * the given data pointer to point past the end of the read data. This * function allocates a single chunk of memory for the result, which * must subsequently be free()d. This function returns NULL if there * was trouble parsing the data. If this function is passed NULL, it * returns an initialized empty DexClassData structure. * * The verification done by this function is of the raw data format * only; it does not verify that access flags, indices, or offsets * are valid. */ DexClassData* dexReadAndVerifyClassData(const u1** pData, const u1* pLimit); /* * Get the DexCode for a DexMethod. Returns NULL if the class is native * or abstract. */ DEX_INLINE const DexCode* dexGetCode(const DexFile* pDexFile, const DexMethod* pDexMethod) { if (pDexMethod->codeOff == 0) return NULL; return (const DexCode*) (pDexFile->baseAddr + pDexMethod->codeOff); } /* Read the header of a class_data_item without verification. This * updates the given data pointer to point past the end of the read * data. */ DEX_INLINE void dexReadClassDataHeader(const u1** pData, DexClassDataHeader *pHeader) { pHeader->staticFieldsSize = readUnsignedLeb128(pData); pHeader->instanceFieldsSize = readUnsignedLeb128(pData); pHeader->directMethodsSize = readUnsignedLeb128(pData); pHeader->virtualMethodsSize = readUnsignedLeb128(pData); } /* Read an encoded_field without verification. This updates the * given data pointer to point past the end of the read data. * * The lastIndex value should be set to 0 before the first field in * a list is read. It is updated as fields are read and used in the * decode process. */ DEX_INLINE void dexReadClassDataField(const u1** pData, DexField* pField, u4* lastIndex) { u4 index = *lastIndex + readUnsignedLeb128(pData); pField->accessFlags = readUnsignedLeb128(pData); pField->fieldIdx = index; *lastIndex = index; } /* Read an encoded_method without verification. This updates the * given data pointer to point past the end of the read data. * * The lastIndex value should be set to 0 before the first method in * a list is read. It is updated as fields are read and used in the * decode process. */ DEX_INLINE void dexReadClassDataMethod(const u1** pData, DexMethod* pMethod, u4* lastIndex) { u4 index = *lastIndex + readUnsignedLeb128(pData); pMethod->accessFlags = readUnsignedLeb128(pData); pMethod->codeOff = readUnsignedLeb128(pData); pMethod->methodIdx = index; *lastIndex = index; } #endif