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 for dealing with method prototypes
19 */
20
21 #ifndef _LIBDEX_DEXPROTO
22 #define _LIBDEX_DEXPROTO
23
24 #include "DexFile.h"
25
26 /*
27 * Single-thread single-string cache. This structure holds a pointer to
28 * a string which is semi-automatically manipulated by some of the
29 * method prototype functions. Functions which use in this struct
30 * generally return a string that is valid until the next
31 * time the same DexStringCache is used.
32 */
33 typedef struct DexStringCache {
34 char* value; /* the latest value */
35 size_t allocatedSize; /* size of the allocated buffer, if allocated */
36 char buffer[120]; /* buffer used to hold small-enough results */
37 } DexStringCache;
38
39 /*
40 * Initialize the given DexStringCache. Use this function before passing
41 * one into any other function.
42 */
43 void dexStringCacheInit(DexStringCache* pCache);
44
45 /*
46 * Release the allocated contents of the given DexStringCache, if any.
47 * Use this function after your last use of a DexStringCache.
48 */
49 void dexStringCacheRelease(DexStringCache* pCache);
50
51 /*
52 * If the given DexStringCache doesn't already point at the given value,
53 * make a copy of it into the cache. This always returns a writable
54 * pointer to the contents (whether or not a copy had to be made). This
55 * function is intended to be used after making a call that at least
56 * sometimes doesn't populate a DexStringCache.
57 */
58 char* dexStringCacheEnsureCopy(DexStringCache* pCache, const char* value);
59
60 /*
61 * Abandon the given DexStringCache, and return a writable copy of the
62 * given value (reusing the string cache's allocation if possible).
63 * The return value must be free()d by the caller. Use this instead of
64 * dexStringCacheRelease() if you want the buffer to survive past the
65 * scope of the DexStringCache.
66 */
67 char* dexStringCacheAbandon(DexStringCache* pCache, const char* value);
68
69 /*
70 * Method prototype structure, which refers to a protoIdx in a
71 * particular DexFile.
72 */
73 typedef struct DexProto {
74 const DexFile* dexFile; /* file the idx refers to */
75 u4 protoIdx; /* index into proto_ids table of dexFile */
76 } DexProto;
77
78 /*
79 * Set the given DexProto to refer to the prototype of the given MethodId.
80 */
dexProtoSetFromMethodId(DexProto * pProto,const DexFile * pDexFile,const DexMethodId * pMethodId)81 DEX_INLINE void dexProtoSetFromMethodId(DexProto* pProto,
82 const DexFile* pDexFile, const DexMethodId* pMethodId)
83 {
84 pProto->dexFile = pDexFile;
85 pProto->protoIdx = pMethodId->protoIdx;
86 }
87
88 /*
89 * Get the short-form method descriptor for the given prototype. The
90 * prototype must be protoIdx-based.
91 */
92 const char* dexProtoGetShorty(const DexProto* pProto);
93
94 /*
95 * Get the full method descriptor for the given prototype.
96 */
97 const char* dexProtoGetMethodDescriptor(const DexProto* pProto,
98 DexStringCache* pCache);
99
100 /*
101 * Get a copy of the descriptor string associated with the given prototype.
102 * The returned pointer must be free()ed by the caller.
103 */
104 char* dexProtoCopyMethodDescriptor(const DexProto* pProto);
105
106 /*
107 * Get the parameter descriptors for the given prototype. This is the
108 * concatenation of all the descriptors for all the parameters, in
109 * order, with no other adornment.
110 */
111 const char* dexProtoGetParameterDescriptors(const DexProto* pProto,
112 DexStringCache* pCache);
113
114 /*
115 * Return the utf-8 encoded descriptor string from the proto of a MethodId.
116 */
dexGetDescriptorFromMethodId(const DexFile * pDexFile,const DexMethodId * pMethodId,DexStringCache * pCache)117 DEX_INLINE const char* dexGetDescriptorFromMethodId(const DexFile* pDexFile,
118 const DexMethodId* pMethodId, DexStringCache* pCache)
119 {
120 DexProto proto;
121
122 dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);
123 return dexProtoGetMethodDescriptor(&proto, pCache);
124 }
125
126 /*
127 * Get a copy of the utf-8 encoded method descriptor string from the
128 * proto of a MethodId. The returned pointer must be free()ed by the
129 * caller.
130 */
dexCopyDescriptorFromMethodId(const DexFile * pDexFile,const DexMethodId * pMethodId)131 DEX_INLINE char* dexCopyDescriptorFromMethodId(const DexFile* pDexFile,
132 const DexMethodId* pMethodId)
133 {
134 DexProto proto;
135
136 dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);
137 return dexProtoCopyMethodDescriptor(&proto);
138 }
139
140 /*
141 * Get the type descriptor for the return type of the given prototype.
142 */
143 const char* dexProtoGetReturnType(const DexProto* pProto);
144
145 /*
146 * Get the parameter count of the given prototype.
147 */
148 size_t dexProtoGetParameterCount(const DexProto* pProto);
149
150 /*
151 * Compute the number of parameter words (u4 units) required by the
152 * given prototype. For example, if the method takes (int, long) and
153 * returns double, this would return 3 (one for the int, two for the
154 * long, and the return type isn't relevant).
155 */
156 int dexProtoComputeArgsSize(const DexProto* pProto);
157
158 /*
159 * Compare the two prototypes. The two prototypes are compared
160 * with the return type as the major order, then the first arguments,
161 * then second, etc. If two prototypes are identical except that one
162 * has extra arguments, then the shorter argument is considered the
163 * earlier one in sort order (similar to strcmp()).
164 */
165 int dexProtoCompare(const DexProto* pProto1, const DexProto* pProto2);
166
167 /*
168 * Compare the two prototypes. The two prototypes are compared
169 * with the first argument as the major order, then second, etc. If two
170 * prototypes are identical except that one has extra arguments, then the
171 * shorter argument is considered the earlier one in sort order (similar
172 * to strcmp()).
173 */
174 int dexProtoCompareParameters(const DexProto* pProto1, const DexProto* pProto2);
175
176 /*
177 * Compare a prototype and a string method descriptor. The comparison
178 * is done as if the descriptor were converted to a prototype and compared
179 * with dexProtoCompare().
180 */
181 int dexProtoCompareToDescriptor(const DexProto* proto, const char* descriptor);
182
183 /*
184 * Single-thread prototype parameter iterator. This structure holds a
185 * pointer to a prototype and its parts, along with a cursor.
186 */
187 typedef struct DexParameterIterator {
188 const DexProto* proto;
189 const DexTypeList* parameters;
190 int parameterCount;
191 int cursor;
192 } DexParameterIterator;
193
194 /*
195 * Initialize the given DexParameterIterator to be at the start of the
196 * parameters of the given prototype.
197 */
198 void dexParameterIteratorInit(DexParameterIterator* pIterator,
199 const DexProto* pProto);
200
201 /*
202 * Get the type_id index for the next parameter, if any. This returns
203 * kDexNoIndex if the last parameter has already been consumed.
204 */
205 u4 dexParameterIteratorNextIndex(DexParameterIterator* pIterator);
206
207 /*
208 * Get the type descriptor for the next parameter, if any. This returns
209 * NULL if the last parameter has already been consumed.
210 */
211 const char* dexParameterIteratorNextDescriptor(
212 DexParameterIterator* pIterator);
213
214
215
216 #endif /*_LIBDEX_DEXPROTO*/
217