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