1 /* 2 * Copyright (C) 2019 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 #ifndef ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_ 18 #define ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_ 19 20 // C++ wrapper for the dex file external API. 21 22 #include <memory> 23 #include <string> 24 25 #include <android-base/macros.h> 26 27 #include "art_api/dex_file_external.h" 28 29 namespace art_api { 30 namespace dex { 31 32 #define FOR_EACH_ADEX_FILE_SYMBOL(MACRO) \ 33 MACRO(ADexFile_Error_toString) \ 34 MACRO(ADexFile_Method_getClassDescriptor) \ 35 MACRO(ADexFile_Method_getCodeOffset) \ 36 MACRO(ADexFile_Method_getName) \ 37 MACRO(ADexFile_Method_getQualifiedName) \ 38 MACRO(ADexFile_create) \ 39 MACRO(ADexFile_destroy) \ 40 MACRO(ADexFile_findMethodAtOffset) \ 41 MACRO(ADexFile_forEachMethod) \ 42 43 #define DEFINE_ADEX_FILE_SYMBOL(DLFUNC) extern decltype(DLFUNC)* g_##DLFUNC; 44 FOR_EACH_ADEX_FILE_SYMBOL(DEFINE_ADEX_FILE_SYMBOL) 45 #undef DEFINE_ADEX_FILE_SYMBOL 46 47 // Returns true if libdexfile.so is already loaded. Otherwise tries to 48 // load it and returns true if successful. Otherwise returns false and sets 49 // *error_msg. Thread safe. 50 bool TryLoadLibdexfile(std::string* error_msg); 51 52 // TryLoadLibdexfile and fatally abort process if unsuccessful. 53 void LoadLibdexfile(); 54 55 // API for reading ordinary dex files and CompactDex files. 56 // It is minimal 1:1 C++ wrapper around the C ABI. 57 // See documentation in dex_file_external.h 58 class DexFile { 59 public: 60 struct Method { 61 size_t GetCodeOffset(size_t* out_size = nullptr) const { 62 return g_ADexFile_Method_getCodeOffset(self, out_size); 63 } 64 65 const char* GetName(size_t* out_size = nullptr) const { 66 return g_ADexFile_Method_getName(self, out_size); 67 } 68 69 const char* GetQualifiedName(bool with_params = false, size_t* out_size = nullptr) const { 70 return g_ADexFile_Method_getQualifiedName(self, with_params, out_size); 71 } 72 73 const char* GetClassDescriptor(size_t* out_size = nullptr) const { 74 return g_ADexFile_Method_getClassDescriptor(self, out_size); 75 } 76 77 const ADexFile_Method* const self; 78 }; 79 80 struct Error { ToStringError81 const char* ToString() const { 82 return g_ADexFile_Error_toString(self); 83 } 84 OkError85 bool Ok() const { 86 return self == ADEXFILE_ERROR_OK; 87 } 88 CodeError89 ADexFile_Error Code() { 90 return self; 91 } 92 93 ADexFile_Error const self; 94 }; 95 Create(const void * address,size_t size,size_t * new_size,const char * location,std::unique_ptr<DexFile> * out_dex_file)96 static Error Create(const void* address, 97 size_t size, 98 size_t* new_size, 99 const char* location, 100 /*out*/ std::unique_ptr<DexFile>* out_dex_file) { 101 LoadLibdexfile(); 102 ADexFile* adex = nullptr; 103 ADexFile_Error error = g_ADexFile_create(address, size, new_size, location, &adex); 104 if (adex != nullptr) { 105 *out_dex_file = std::unique_ptr<DexFile>(new DexFile{adex}); 106 } 107 return Error{error}; 108 } 109 ~DexFile()110 virtual ~DexFile() { 111 g_ADexFile_destroy(self_); 112 } 113 114 template<typename T /* lambda which takes (const DexFile::Method&) as argument */> FindMethodAtOffset(uint32_t dex_offset,T callback)115 inline size_t FindMethodAtOffset(uint32_t dex_offset, T callback) { 116 auto cb = [](void* ctx, const ADexFile_Method* m) { (*reinterpret_cast<T*>(ctx))(Method{m}); }; 117 return g_ADexFile_findMethodAtOffset(self_, dex_offset, cb, &callback); 118 } 119 120 template<typename T /* lambda which takes (const DexFile::Method&) as argument */> ForEachMethod(T callback)121 inline size_t ForEachMethod(T callback) { 122 auto cb = [](void* ctx, const ADexFile_Method* m) { (*reinterpret_cast<T*>(ctx))(Method{m}); }; 123 return g_ADexFile_forEachMethod(self_, cb, &callback); 124 } 125 126 protected: DexFile(ADexFile * self)127 explicit DexFile(ADexFile* self) : self_(self) {} 128 129 ADexFile* const self_; 130 131 DISALLOW_COPY_AND_ASSIGN(DexFile); 132 }; 133 134 } // namespace dex 135 } // namespace art_api 136 137 #endif // ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_ 138