1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * Functions to deal with class definition structures in DEX files
19  */
20 
21 #ifndef LIBDEX_DEXCLASS_H_
22 #define LIBDEX_DEXCLASS_H_
23 
24 #include "DexFile.h"
25 #include "Leb128.h"
26 
27 /* expanded form of a class_data_item header */
28 struct DexClassDataHeader {
29     u4 staticFieldsSize;
30     u4 instanceFieldsSize;
31     u4 directMethodsSize;
32     u4 virtualMethodsSize;
33 };
34 
35 /* expanded form of encoded_field */
36 struct DexField {
37     u4 fieldIdx;    /* index to a field_id_item */
38     u4 accessFlags;
39 };
40 
41 /* expanded form of encoded_method */
42 struct DexMethod {
43     u4 methodIdx;    /* index to a method_id_item */
44     u4 accessFlags;
45     u4 codeOff;      /* file offset to a code_item */
46 };
47 
48 /* expanded form of class_data_item. Note: If a particular item is
49  * absent (e.g., no static fields), then the corresponding pointer
50  * is set to NULL. */
51 struct DexClassData {
52     DexClassDataHeader header;
53     DexField*          staticFields;
54     DexField*          instanceFields;
55     DexMethod*         directMethods;
56     DexMethod*         virtualMethods;
57 };
58 
59 /* Read and verify the header of a class_data_item. This updates the
60  * given data pointer to point past the end of the read data and
61  * returns an "okay" flag (that is, false == failure). */
62 bool dexReadAndVerifyClassDataHeader(const u1** pData, const u1* pLimit,
63         DexClassDataHeader *pHeader);
64 
65 /* Read and verify an encoded_field. This updates the
66  * given data pointer to point past the end of the read data and
67  * returns an "okay" flag (that is, false == failure).
68  *
69  * The lastIndex value should be set to 0 before the first field in
70  * a list is read. It is updated as fields are read and used in the
71  * decode process.
72  *
73  * The verification done by this function is of the raw data format
74  * only; it does not verify that access flags or indices
75  * are valid. */
76 bool dexReadAndVerifyClassDataField(const u1** pData, const u1* pLimit,
77         DexField* pField, u4* lastIndex);
78 
79 /* Read and verify an encoded_method. This updates the
80  * given data pointer to point past the end of the read data and
81  * returns an "okay" flag (that is, false == failure).
82  *
83  * The lastIndex value should be set to 0 before the first method in
84  * a list is read. It is updated as fields are read and used in the
85  * decode process.
86  *
87  * The verification done by this function is of the raw data format
88  * only; it does not verify that access flags, indices, or offsets
89  * are valid. */
90 bool dexReadAndVerifyClassDataMethod(const u1** pData, const u1* pLimit,
91         DexMethod* pMethod, u4* lastIndex);
92 
93 /* Read, verify, and return an entire class_data_item. This updates
94  * the given data pointer to point past the end of the read data. This
95  * function allocates a single chunk of memory for the result, which
96  * must subsequently be free()d. This function returns NULL if there
97  * was trouble parsing the data. If this function is passed NULL, it
98  * returns an initialized empty DexClassData structure.
99  *
100  * The verification done by this function is of the raw data format
101  * only; it does not verify that access flags, indices, or offsets
102  * are valid. */
103 DexClassData* dexReadAndVerifyClassData(const u1** pData, const u1* pLimit);
104 
105 /*
106  * Get the DexCode for a DexMethod.  Returns NULL if the class is native
107  * or abstract.
108  */
dexGetCode(const DexFile * pDexFile,const DexMethod * pDexMethod)109 DEX_INLINE const DexCode* dexGetCode(const DexFile* pDexFile,
110     const DexMethod* pDexMethod)
111 {
112     if (pDexMethod->codeOff == 0)
113         return NULL;
114     return (const DexCode*) (pDexFile->baseAddr + pDexMethod->codeOff);
115 }
116 
117 
118 /* Read the header of a class_data_item without verification. This
119  * updates the given data pointer to point past the end of the read
120  * data. */
dexReadClassDataHeader(const u1 ** pData,DexClassDataHeader * pHeader)121 DEX_INLINE void dexReadClassDataHeader(const u1** pData,
122         DexClassDataHeader *pHeader) {
123     pHeader->staticFieldsSize = readUnsignedLeb128(pData);
124     pHeader->instanceFieldsSize = readUnsignedLeb128(pData);
125     pHeader->directMethodsSize = readUnsignedLeb128(pData);
126     pHeader->virtualMethodsSize = readUnsignedLeb128(pData);
127 }
128 
129 /* Read an encoded_field without verification. This updates the
130  * given data pointer to point past the end of the read data.
131  *
132  * The lastIndex value should be set to 0 before the first field in
133  * a list is read. It is updated as fields are read and used in the
134  * decode process.
135  */
dexReadClassDataField(const u1 ** pData,DexField * pField,u4 * lastIndex)136 DEX_INLINE void dexReadClassDataField(const u1** pData, DexField* pField,
137         u4* lastIndex) {
138     u4 index = *lastIndex + readUnsignedLeb128(pData);
139 
140     pField->accessFlags = readUnsignedLeb128(pData);
141     pField->fieldIdx = index;
142     *lastIndex = index;
143 }
144 
145 /* Read an encoded_method without verification. This updates the
146  * given data pointer to point past the end of the read data.
147  *
148  * The lastIndex value should be set to 0 before the first method in
149  * a list is read. It is updated as fields are read and used in the
150  * decode process.
151  */
dexReadClassDataMethod(const u1 ** pData,DexMethod * pMethod,u4 * lastIndex)152 DEX_INLINE void dexReadClassDataMethod(const u1** pData, DexMethod* pMethod,
153         u4* lastIndex) {
154     u4 index = *lastIndex + readUnsignedLeb128(pData);
155 
156     pMethod->accessFlags = readUnsignedLeb128(pData);
157     pMethod->codeOff = readUnsignedLeb128(pData);
158     pMethod->methodIdx = index;
159     *lastIndex = index;
160 }
161 
162 #endif  // LIBDEX_DEXCLASS_H_
163