| /* |
| * 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 |