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