xref: /aosp_15_r20/art/libdexfile/external/dex_file_ext.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "art_api/dex_file_external.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <inttypes.h>
20*795d594fSAndroid Build Coastguard Worker #include <stdint.h>
21*795d594fSAndroid Build Coastguard Worker #include <sys/stat.h>
22*795d594fSAndroid Build Coastguard Worker #include <sys/types.h>
23*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker #include <algorithm>
26*795d594fSAndroid Build Coastguard Worker #include <cerrno>
27*795d594fSAndroid Build Coastguard Worker #include <cstring>
28*795d594fSAndroid Build Coastguard Worker #include <deque>
29*795d594fSAndroid Build Coastguard Worker #include <map>
30*795d594fSAndroid Build Coastguard Worker #include <memory>
31*795d594fSAndroid Build Coastguard Worker #include <string>
32*795d594fSAndroid Build Coastguard Worker #include <utility>
33*795d594fSAndroid Build Coastguard Worker #include <vector>
34*795d594fSAndroid Build Coastguard Worker 
35*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
36*795d594fSAndroid Build Coastguard Worker #include <android-base/macros.h>
37*795d594fSAndroid Build Coastguard Worker #include <android-base/mapped_file.h>
38*795d594fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker #include <dex/class_accessor-inl.h>
41*795d594fSAndroid Build Coastguard Worker #include <dex/code_item_accessors-inl.h>
42*795d594fSAndroid Build Coastguard Worker #include <dex/dex_file-inl.h>
43*795d594fSAndroid Build Coastguard Worker #include <dex/dex_file_loader.h>
44*795d594fSAndroid Build Coastguard Worker 
45*795d594fSAndroid Build Coastguard Worker extern "C" {
46*795d594fSAndroid Build Coastguard Worker 
47*795d594fSAndroid Build Coastguard Worker struct ADexFile_Method {
48*795d594fSAndroid Build Coastguard Worker   ADexFile* adex;
49*795d594fSAndroid Build Coastguard Worker   uint32_t index;
50*795d594fSAndroid Build Coastguard Worker   size_t offset;
51*795d594fSAndroid Build Coastguard Worker   size_t size;
52*795d594fSAndroid Build Coastguard Worker };
53*795d594fSAndroid Build Coastguard Worker 
54*795d594fSAndroid Build Coastguard Worker // Opaque implementation of ADexFile for the C interface.
55*795d594fSAndroid Build Coastguard Worker struct ADexFile {
ADexFileADexFile56*795d594fSAndroid Build Coastguard Worker   explicit ADexFile(std::unique_ptr<const art::DexFile> dex_file)
57*795d594fSAndroid Build Coastguard Worker       : dex_file_(std::move(dex_file)) {}
58*795d594fSAndroid Build Coastguard Worker 
FindMethodADexFile59*795d594fSAndroid Build Coastguard Worker   inline bool FindMethod(uint32_t dex_offset, /*out*/ ADexFile_Method* result) {
60*795d594fSAndroid Build Coastguard Worker     uint32_t class_def_index;
61*795d594fSAndroid Build Coastguard Worker     if (GetClassDefIndex(dex_offset, &class_def_index)) {
62*795d594fSAndroid Build Coastguard Worker       art::ClassAccessor accessor(*dex_file_, class_def_index);
63*795d594fSAndroid Build Coastguard Worker       for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
64*795d594fSAndroid Build Coastguard Worker         art::CodeItemInstructionAccessor code = method.GetInstructions();
65*795d594fSAndroid Build Coastguard Worker         if (!code.HasCodeItem()) {
66*795d594fSAndroid Build Coastguard Worker           continue;
67*795d594fSAndroid Build Coastguard Worker         }
68*795d594fSAndroid Build Coastguard Worker         size_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
69*795d594fSAndroid Build Coastguard Worker         size_t size = code.InsnsSizeInBytes();
70*795d594fSAndroid Build Coastguard Worker         if (offset <= dex_offset && dex_offset < offset + size) {
71*795d594fSAndroid Build Coastguard Worker           *result = ADexFile_Method {
72*795d594fSAndroid Build Coastguard Worker             .adex = this,
73*795d594fSAndroid Build Coastguard Worker             .index = method.GetIndex(),
74*795d594fSAndroid Build Coastguard Worker             .offset = offset,
75*795d594fSAndroid Build Coastguard Worker             .size = size,
76*795d594fSAndroid Build Coastguard Worker           };
77*795d594fSAndroid Build Coastguard Worker           return true;
78*795d594fSAndroid Build Coastguard Worker         }
79*795d594fSAndroid Build Coastguard Worker       }
80*795d594fSAndroid Build Coastguard Worker     }
81*795d594fSAndroid Build Coastguard Worker     return false;
82*795d594fSAndroid Build Coastguard Worker   }
83*795d594fSAndroid Build Coastguard Worker 
CreateClassCacheADexFile84*795d594fSAndroid Build Coastguard Worker   void CreateClassCache() {
85*795d594fSAndroid Build Coastguard Worker     // Create binary search table with (end_dex_offset, class_def_index) entries.
86*795d594fSAndroid Build Coastguard Worker     // That is, we don't assume that dex code of given class is consecutive.
87*795d594fSAndroid Build Coastguard Worker     std::deque<std::pair<uint32_t, uint32_t>> cache;
88*795d594fSAndroid Build Coastguard Worker     for (art::ClassAccessor accessor : dex_file_->GetClasses()) {
89*795d594fSAndroid Build Coastguard Worker       for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
90*795d594fSAndroid Build Coastguard Worker         art::CodeItemInstructionAccessor code = method.GetInstructions();
91*795d594fSAndroid Build Coastguard Worker         if (code.HasCodeItem()) {
92*795d594fSAndroid Build Coastguard Worker           int32_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
93*795d594fSAndroid Build Coastguard Worker           DCHECK_NE(offset, 0);
94*795d594fSAndroid Build Coastguard Worker           cache.emplace_back(offset + code.InsnsSizeInBytes(), accessor.GetClassDefIndex());
95*795d594fSAndroid Build Coastguard Worker         }
96*795d594fSAndroid Build Coastguard Worker       }
97*795d594fSAndroid Build Coastguard Worker     }
98*795d594fSAndroid Build Coastguard Worker     std::sort(cache.begin(), cache.end());
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker     // If two consecutive methods belong to same class, we can merge them.
101*795d594fSAndroid Build Coastguard Worker     // This tends to reduce the number of entries (used memory) by 10x.
102*795d594fSAndroid Build Coastguard Worker     size_t num_entries = cache.size();
103*795d594fSAndroid Build Coastguard Worker     if (cache.size() > 1) {
104*795d594fSAndroid Build Coastguard Worker       for (auto it = std::next(cache.begin()); it != cache.end(); it++) {
105*795d594fSAndroid Build Coastguard Worker         if (std::prev(it)->second == it->second) {
106*795d594fSAndroid Build Coastguard Worker           std::prev(it)->first = 0;  // Clear entry with lower end_dex_offset (mark to remove).
107*795d594fSAndroid Build Coastguard Worker           num_entries--;
108*795d594fSAndroid Build Coastguard Worker         }
109*795d594fSAndroid Build Coastguard Worker       }
110*795d594fSAndroid Build Coastguard Worker     }
111*795d594fSAndroid Build Coastguard Worker 
112*795d594fSAndroid Build Coastguard Worker     // The cache is immutable now. Store it as continuous vector to save space.
113*795d594fSAndroid Build Coastguard Worker     class_cache_.reserve(num_entries);
114*795d594fSAndroid Build Coastguard Worker     auto pred = [](auto it) { return it.first != 0; };  // Entries to copy (not cleared above).
115*795d594fSAndroid Build Coastguard Worker     std::copy_if(cache.begin(), cache.end(), std::back_inserter(class_cache_), pred);
116*795d594fSAndroid Build Coastguard Worker   }
117*795d594fSAndroid Build Coastguard Worker 
GetClassDefIndexADexFile118*795d594fSAndroid Build Coastguard Worker   inline bool GetClassDefIndex(uint32_t dex_offset, uint32_t* class_def_index) {
119*795d594fSAndroid Build Coastguard Worker     if (class_cache_.empty()) {
120*795d594fSAndroid Build Coastguard Worker       CreateClassCache();
121*795d594fSAndroid Build Coastguard Worker     }
122*795d594fSAndroid Build Coastguard Worker 
123*795d594fSAndroid Build Coastguard Worker     // Binary search in the class cache. First element of the pair is the key.
124*795d594fSAndroid Build Coastguard Worker     auto comp = [](uint32_t value, const auto& it) { return value < it.first; };
125*795d594fSAndroid Build Coastguard Worker     auto it = std::upper_bound(class_cache_.begin(), class_cache_.end(), dex_offset, comp);
126*795d594fSAndroid Build Coastguard Worker     if (it != class_cache_.end()) {
127*795d594fSAndroid Build Coastguard Worker       *class_def_index = it->second;
128*795d594fSAndroid Build Coastguard Worker       return true;
129*795d594fSAndroid Build Coastguard Worker     }
130*795d594fSAndroid Build Coastguard Worker     return false;
131*795d594fSAndroid Build Coastguard Worker   }
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker   // The underlying ART object.
134*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<const art::DexFile> dex_file_;
135*795d594fSAndroid Build Coastguard Worker 
136*795d594fSAndroid Build Coastguard Worker   // Binary search table with (end_dex_offset, class_def_index) entries.
137*795d594fSAndroid Build Coastguard Worker   std::vector<std::pair<uint32_t, uint32_t>> class_cache_;
138*795d594fSAndroid Build Coastguard Worker 
139*795d594fSAndroid Build Coastguard Worker   // Used as short lived temporary when needed. Avoids alloc/free.
140*795d594fSAndroid Build Coastguard Worker   std::string temporary_qualified_name_;
141*795d594fSAndroid Build Coastguard Worker };
142*795d594fSAndroid Build Coastguard Worker 
ADexFile_create(const void * _Nonnull address,size_t size,size_t * _Nullable new_size,const char * _Nonnull location,ADexFile * _Nullable * _Nonnull out_dex_file)143*795d594fSAndroid Build Coastguard Worker ADexFile_Error ADexFile_create(const void* _Nonnull address,
144*795d594fSAndroid Build Coastguard Worker                                size_t size,
145*795d594fSAndroid Build Coastguard Worker                                size_t* _Nullable new_size,
146*795d594fSAndroid Build Coastguard Worker                                const char* _Nonnull location,
147*795d594fSAndroid Build Coastguard Worker                                /*out*/ ADexFile* _Nullable * _Nonnull out_dex_file) {
148*795d594fSAndroid Build Coastguard Worker   *out_dex_file = nullptr;
149*795d594fSAndroid Build Coastguard Worker 
150*795d594fSAndroid Build Coastguard Worker   if (size < sizeof(art::DexFile::Header)) {
151*795d594fSAndroid Build Coastguard Worker     if (new_size != nullptr) {
152*795d594fSAndroid Build Coastguard Worker       *new_size = sizeof(art::DexFile::Header);
153*795d594fSAndroid Build Coastguard Worker     }
154*795d594fSAndroid Build Coastguard Worker     return ADEXFILE_ERROR_NOT_ENOUGH_DATA;
155*795d594fSAndroid Build Coastguard Worker   }
156*795d594fSAndroid Build Coastguard Worker 
157*795d594fSAndroid Build Coastguard Worker   const art::DexFile::Header* header = reinterpret_cast<const art::DexFile::Header*>(address);
158*795d594fSAndroid Build Coastguard Worker   if (size < header->header_size_) {
159*795d594fSAndroid Build Coastguard Worker     if (new_size != nullptr) {
160*795d594fSAndroid Build Coastguard Worker       *new_size = header->header_size_;
161*795d594fSAndroid Build Coastguard Worker     }
162*795d594fSAndroid Build Coastguard Worker     return ADEXFILE_ERROR_NOT_ENOUGH_DATA;
163*795d594fSAndroid Build Coastguard Worker   }
164*795d594fSAndroid Build Coastguard Worker 
165*795d594fSAndroid Build Coastguard Worker   uint32_t dex_size = header->file_size_;  // Size of "one dex file" excluding any shared data.
166*795d594fSAndroid Build Coastguard Worker   uint32_t full_size = dex_size;           // Includes referenced shared data past the end of dex.
167*795d594fSAndroid Build Coastguard Worker   if (art::CompactDexFile::IsMagicValid(header->magic_)) {
168*795d594fSAndroid Build Coastguard Worker     // Compact dex files store the data section separately so that it can be shared.
169*795d594fSAndroid Build Coastguard Worker     // Therefore we need to extend the read memory range to include it.
170*795d594fSAndroid Build Coastguard Worker     // TODO: This might be wasteful as we might read data in between as well.
171*795d594fSAndroid Build Coastguard Worker     //       In practice, this should be fine, as such sharing only happens on disk.
172*795d594fSAndroid Build Coastguard Worker     uint32_t computed_file_size;
173*795d594fSAndroid Build Coastguard Worker     if (__builtin_add_overflow(header->data_off_, header->data_size_, &computed_file_size)) {
174*795d594fSAndroid Build Coastguard Worker       return ADEXFILE_ERROR_INVALID_HEADER;
175*795d594fSAndroid Build Coastguard Worker     }
176*795d594fSAndroid Build Coastguard Worker     if (computed_file_size > full_size) {
177*795d594fSAndroid Build Coastguard Worker       full_size = computed_file_size;
178*795d594fSAndroid Build Coastguard Worker     }
179*795d594fSAndroid Build Coastguard Worker   } else if (art::StandardDexFile::IsMagicValid(header->magic_)) {
180*795d594fSAndroid Build Coastguard Worker     full_size = header->ContainerSize() - header->HeaderOffset();
181*795d594fSAndroid Build Coastguard Worker   } else {
182*795d594fSAndroid Build Coastguard Worker     return ADEXFILE_ERROR_INVALID_HEADER;
183*795d594fSAndroid Build Coastguard Worker   }
184*795d594fSAndroid Build Coastguard Worker 
185*795d594fSAndroid Build Coastguard Worker   if (size < full_size) {
186*795d594fSAndroid Build Coastguard Worker     if (new_size != nullptr) {
187*795d594fSAndroid Build Coastguard Worker       *new_size = full_size;
188*795d594fSAndroid Build Coastguard Worker     }
189*795d594fSAndroid Build Coastguard Worker     return ADEXFILE_ERROR_NOT_ENOUGH_DATA;
190*795d594fSAndroid Build Coastguard Worker   }
191*795d594fSAndroid Build Coastguard Worker 
192*795d594fSAndroid Build Coastguard Worker   std::string loc_str(location);
193*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
194*795d594fSAndroid Build Coastguard Worker   art::DexFileLoader loader(static_cast<const uint8_t*>(address), full_size, loc_str);
195*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<const art::DexFile> dex_file = loader.OpenOne(/*header_offset=*/0,
196*795d594fSAndroid Build Coastguard Worker                                                                 header->checksum_,
197*795d594fSAndroid Build Coastguard Worker                                                                 /*oat_dex_file=*/nullptr,
198*795d594fSAndroid Build Coastguard Worker                                                                 /*verify=*/false,
199*795d594fSAndroid Build Coastguard Worker                                                                 /*verify_checksum=*/false,
200*795d594fSAndroid Build Coastguard Worker                                                                 &error_msg);
201*795d594fSAndroid Build Coastguard Worker   if (dex_file == nullptr) {
202*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Can not open dex file " << loc_str << ": " << error_msg;
203*795d594fSAndroid Build Coastguard Worker     return ADEXFILE_ERROR_INVALID_DEX;
204*795d594fSAndroid Build Coastguard Worker   }
205*795d594fSAndroid Build Coastguard Worker 
206*795d594fSAndroid Build Coastguard Worker   *out_dex_file = new ADexFile(std::move(dex_file));
207*795d594fSAndroid Build Coastguard Worker   return ADEXFILE_ERROR_OK;
208*795d594fSAndroid Build Coastguard Worker }
209*795d594fSAndroid Build Coastguard Worker 
ADexFile_destroy(ADexFile * self)210*795d594fSAndroid Build Coastguard Worker void ADexFile_destroy(ADexFile* self) {
211*795d594fSAndroid Build Coastguard Worker   delete self;
212*795d594fSAndroid Build Coastguard Worker }
213*795d594fSAndroid Build Coastguard Worker 
ADexFile_findMethodAtOffset(ADexFile * self,size_t dex_offset,ADexFile_MethodCallback * callback,void * callback_data)214*795d594fSAndroid Build Coastguard Worker size_t ADexFile_findMethodAtOffset(ADexFile* self,
215*795d594fSAndroid Build Coastguard Worker                                    size_t dex_offset,
216*795d594fSAndroid Build Coastguard Worker                                    ADexFile_MethodCallback* callback,
217*795d594fSAndroid Build Coastguard Worker                                    void* callback_data) {
218*795d594fSAndroid Build Coastguard Worker   const art::DexFile* dex_file = self->dex_file_.get();
219*795d594fSAndroid Build Coastguard Worker   if (!dex_file->IsInDataSection(dex_file->Begin() + dex_offset)) {
220*795d594fSAndroid Build Coastguard Worker     return 0;  // The DEX offset is not within the bytecode of this dex file.
221*795d594fSAndroid Build Coastguard Worker   }
222*795d594fSAndroid Build Coastguard Worker 
223*795d594fSAndroid Build Coastguard Worker   if (dex_file->IsCompactDexFile()) {
224*795d594fSAndroid Build Coastguard Worker     // The data section of compact dex files might be shared.
225*795d594fSAndroid Build Coastguard Worker     // Check the subrange unique to this compact dex.
226*795d594fSAndroid Build Coastguard Worker     const art::CompactDexFile::Header& cdex_header =
227*795d594fSAndroid Build Coastguard Worker         dex_file->AsCompactDexFile()->GetHeader();
228*795d594fSAndroid Build Coastguard Worker     uint32_t begin = cdex_header.data_off_ + cdex_header.OwnedDataBegin();
229*795d594fSAndroid Build Coastguard Worker     uint32_t end = cdex_header.data_off_ + cdex_header.OwnedDataEnd();
230*795d594fSAndroid Build Coastguard Worker     if (dex_offset < begin || dex_offset >= end) {
231*795d594fSAndroid Build Coastguard Worker       return 0;  // The DEX offset is not within the bytecode of this dex file.
232*795d594fSAndroid Build Coastguard Worker     }
233*795d594fSAndroid Build Coastguard Worker   }
234*795d594fSAndroid Build Coastguard Worker 
235*795d594fSAndroid Build Coastguard Worker   ADexFile_Method info;
236*795d594fSAndroid Build Coastguard Worker   if (!self->FindMethod(dex_offset, &info)) {
237*795d594fSAndroid Build Coastguard Worker     return 0;
238*795d594fSAndroid Build Coastguard Worker   }
239*795d594fSAndroid Build Coastguard Worker 
240*795d594fSAndroid Build Coastguard Worker   callback(callback_data, &info);
241*795d594fSAndroid Build Coastguard Worker   return 1;
242*795d594fSAndroid Build Coastguard Worker }
243*795d594fSAndroid Build Coastguard Worker 
ADexFile_forEachMethod(ADexFile * self,ADexFile_MethodCallback * callback,void * callback_data)244*795d594fSAndroid Build Coastguard Worker size_t ADexFile_forEachMethod(ADexFile* self,
245*795d594fSAndroid Build Coastguard Worker                               ADexFile_MethodCallback* callback,
246*795d594fSAndroid Build Coastguard Worker                               void* callback_data) {
247*795d594fSAndroid Build Coastguard Worker   size_t count = 0;
248*795d594fSAndroid Build Coastguard Worker   for (art::ClassAccessor accessor : self->dex_file_->GetClasses()) {
249*795d594fSAndroid Build Coastguard Worker     for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
250*795d594fSAndroid Build Coastguard Worker       art::CodeItemInstructionAccessor code = method.GetInstructions();
251*795d594fSAndroid Build Coastguard Worker       if (code.HasCodeItem()) {
252*795d594fSAndroid Build Coastguard Worker         size_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - self->dex_file_->Begin();
253*795d594fSAndroid Build Coastguard Worker         ADexFile_Method info {
254*795d594fSAndroid Build Coastguard Worker           .adex = self,
255*795d594fSAndroid Build Coastguard Worker           .index = method.GetIndex(),
256*795d594fSAndroid Build Coastguard Worker           .offset = offset,
257*795d594fSAndroid Build Coastguard Worker           .size = code.InsnsSizeInBytes(),
258*795d594fSAndroid Build Coastguard Worker         };
259*795d594fSAndroid Build Coastguard Worker         callback(callback_data, &info);
260*795d594fSAndroid Build Coastguard Worker         count++;
261*795d594fSAndroid Build Coastguard Worker       }
262*795d594fSAndroid Build Coastguard Worker     }
263*795d594fSAndroid Build Coastguard Worker   }
264*795d594fSAndroid Build Coastguard Worker   return count;
265*795d594fSAndroid Build Coastguard Worker }
266*795d594fSAndroid Build Coastguard Worker 
ADexFile_Method_getCodeOffset(const ADexFile_Method * self,size_t * out_size)267*795d594fSAndroid Build Coastguard Worker size_t ADexFile_Method_getCodeOffset(const ADexFile_Method* self,
268*795d594fSAndroid Build Coastguard Worker                                      size_t* out_size) {
269*795d594fSAndroid Build Coastguard Worker   if (out_size != nullptr) {
270*795d594fSAndroid Build Coastguard Worker     *out_size = self->size;
271*795d594fSAndroid Build Coastguard Worker   }
272*795d594fSAndroid Build Coastguard Worker   return self->offset;
273*795d594fSAndroid Build Coastguard Worker }
274*795d594fSAndroid Build Coastguard Worker 
ADexFile_Method_getName(const ADexFile_Method * self,size_t * out_size)275*795d594fSAndroid Build Coastguard Worker const char* ADexFile_Method_getName(const ADexFile_Method* self,
276*795d594fSAndroid Build Coastguard Worker                                     size_t* out_size) {
277*795d594fSAndroid Build Coastguard Worker   const char* name = self->adex->dex_file_->GetMethodName(self->index);
278*795d594fSAndroid Build Coastguard Worker   if (out_size != nullptr) {
279*795d594fSAndroid Build Coastguard Worker     *out_size = strlen(name);
280*795d594fSAndroid Build Coastguard Worker   }
281*795d594fSAndroid Build Coastguard Worker   return name;
282*795d594fSAndroid Build Coastguard Worker }
283*795d594fSAndroid Build Coastguard Worker 
ADexFile_Method_getQualifiedName(const ADexFile_Method * self,int with_params,size_t * out_size)284*795d594fSAndroid Build Coastguard Worker const char* ADexFile_Method_getQualifiedName(const ADexFile_Method* self,
285*795d594fSAndroid Build Coastguard Worker                                              int with_params,
286*795d594fSAndroid Build Coastguard Worker                                              size_t* out_size) {
287*795d594fSAndroid Build Coastguard Worker   std::string& temp = self->adex->temporary_qualified_name_;
288*795d594fSAndroid Build Coastguard Worker   temp.clear();
289*795d594fSAndroid Build Coastguard Worker   self->adex->dex_file_->AppendPrettyMethod(self->index, with_params, &temp);
290*795d594fSAndroid Build Coastguard Worker   if (out_size != nullptr) {
291*795d594fSAndroid Build Coastguard Worker     *out_size = temp.size();
292*795d594fSAndroid Build Coastguard Worker   }
293*795d594fSAndroid Build Coastguard Worker   return temp.data();
294*795d594fSAndroid Build Coastguard Worker }
295*795d594fSAndroid Build Coastguard Worker 
ADexFile_Method_getClassDescriptor(const ADexFile_Method * self,size_t * out_size)296*795d594fSAndroid Build Coastguard Worker const char* ADexFile_Method_getClassDescriptor(const ADexFile_Method* self,
297*795d594fSAndroid Build Coastguard Worker                                                size_t* out_size) {
298*795d594fSAndroid Build Coastguard Worker   const art::dex::MethodId& method_id = self->adex->dex_file_->GetMethodId(self->index);
299*795d594fSAndroid Build Coastguard Worker   const char* name = self->adex->dex_file_->GetMethodDeclaringClassDescriptor(method_id);
300*795d594fSAndroid Build Coastguard Worker   if (out_size != nullptr) {
301*795d594fSAndroid Build Coastguard Worker     *out_size = strlen(name);
302*795d594fSAndroid Build Coastguard Worker   }
303*795d594fSAndroid Build Coastguard Worker   return name;
304*795d594fSAndroid Build Coastguard Worker }
305*795d594fSAndroid Build Coastguard Worker 
ADexFile_Error_toString(ADexFile_Error self)306*795d594fSAndroid Build Coastguard Worker const char* ADexFile_Error_toString(ADexFile_Error self) {
307*795d594fSAndroid Build Coastguard Worker   switch (self) {
308*795d594fSAndroid Build Coastguard Worker     case ADEXFILE_ERROR_OK: return "Ok";
309*795d594fSAndroid Build Coastguard Worker     case ADEXFILE_ERROR_INVALID_DEX: return "Dex file is invalid.";
310*795d594fSAndroid Build Coastguard Worker     case ADEXFILE_ERROR_NOT_ENOUGH_DATA: return "Not enough data. Incomplete dex file.";
311*795d594fSAndroid Build Coastguard Worker     case ADEXFILE_ERROR_INVALID_HEADER: return "Invalid dex file header.";
312*795d594fSAndroid Build Coastguard Worker   }
313*795d594fSAndroid Build Coastguard Worker   return nullptr;
314*795d594fSAndroid Build Coastguard Worker }
315*795d594fSAndroid Build Coastguard Worker 
316*795d594fSAndroid Build Coastguard Worker }  // extern "C"
317