• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 #include "dex_file.h"
18 
19 #include <fcntl.h>
20 #include <limits.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/file.h>
25 #include <sys/stat.h>
26 #include <memory>
27 
28 #include "base/logging.h"
29 #include "base/stringprintf.h"
30 #include "class_linker.h"
31 #include "dex_file-inl.h"
32 #include "dex_file_verifier.h"
33 #include "globals.h"
34 #include "leb128.h"
35 #include "mirror/art_field-inl.h"
36 #include "mirror/art_method-inl.h"
37 #include "mirror/string.h"
38 #include "os.h"
39 #include "safe_map.h"
40 #include "ScopedFd.h"
41 #include "handle_scope-inl.h"
42 #include "thread.h"
43 #include "utf-inl.h"
44 #include "utils.h"
45 #include "well_known_classes.h"
46 #include "zip_archive.h"
47 
48 namespace art {
49 
50 const byte DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
51 const byte DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
52 
OpenAndReadMagic(const char * filename,uint32_t * magic,std::string * error_msg)53 static int OpenAndReadMagic(const char* filename, uint32_t* magic, std::string* error_msg) {
54   CHECK(magic != NULL);
55   ScopedFd fd(open(filename, O_RDONLY, 0));
56   if (fd.get() == -1) {
57     *error_msg = StringPrintf("Unable to open '%s' : %s", filename, strerror(errno));
58     return -1;
59   }
60   int n = TEMP_FAILURE_RETRY(read(fd.get(), magic, sizeof(*magic)));
61   if (n != sizeof(*magic)) {
62     *error_msg = StringPrintf("Failed to find magic in '%s'", filename);
63     return -1;
64   }
65   if (lseek(fd.get(), 0, SEEK_SET) != 0) {
66     *error_msg = StringPrintf("Failed to seek to beginning of file '%s' : %s", filename,
67                               strerror(errno));
68     return -1;
69   }
70   return fd.release();
71 }
72 
GetChecksum(const char * filename,uint32_t * checksum,std::string * error_msg)73 bool DexFile::GetChecksum(const char* filename, uint32_t* checksum, std::string* error_msg) {
74   CHECK(checksum != NULL);
75   uint32_t magic;
76 
77   // Strip ":...", which is the location
78   const char* zip_entry_name = kClassesDex;
79   const char* file_part = filename;
80   std::string file_part_storage;
81 
82   if (DexFile::IsMultiDexLocation(filename)) {
83     file_part_storage = GetBaseLocation(filename);
84     file_part = file_part_storage.c_str();
85     zip_entry_name = filename + file_part_storage.size() + 1;
86     DCHECK_EQ(zip_entry_name[-1], kMultiDexSeparator);
87   }
88 
89   ScopedFd fd(OpenAndReadMagic(file_part, &magic, error_msg));
90   if (fd.get() == -1) {
91     DCHECK(!error_msg->empty());
92     return false;
93   }
94   if (IsZipMagic(magic)) {
95     std::unique_ptr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(fd.release(), filename, error_msg));
96     if (zip_archive.get() == NULL) {
97       *error_msg = StringPrintf("Failed to open zip archive '%s'", file_part);
98       return false;
99     }
100     std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(zip_entry_name, error_msg));
101     if (zip_entry.get() == NULL) {
102       *error_msg = StringPrintf("Zip archive '%s' doesn't contain %s (error msg: %s)", file_part,
103                                 zip_entry_name, error_msg->c_str());
104       return false;
105     }
106     *checksum = zip_entry->GetCrc32();
107     return true;
108   }
109   if (IsDexMagic(magic)) {
110     std::unique_ptr<const DexFile> dex_file(DexFile::OpenFile(fd.release(), filename, false, error_msg));
111     if (dex_file.get() == NULL) {
112       return false;
113     }
114     *checksum = dex_file->GetHeader().checksum_;
115     return true;
116   }
117   *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename);
118   return false;
119 }
120 
Open(const char * filename,const char * location,std::string * error_msg,std::vector<const DexFile * > * dex_files)121 bool DexFile::Open(const char* filename, const char* location, std::string* error_msg,
122                    std::vector<const DexFile*>* dex_files) {
123   uint32_t magic;
124   ScopedFd fd(OpenAndReadMagic(filename, &magic, error_msg));
125   if (fd.get() == -1) {
126     DCHECK(!error_msg->empty());
127     return false;
128   }
129   if (IsZipMagic(magic)) {
130     return DexFile::OpenZip(fd.release(), location, error_msg, dex_files);
131   }
132   if (IsDexMagic(magic)) {
133     std::unique_ptr<const DexFile> dex_file(DexFile::OpenFile(fd.release(), location, true,
134                                                               error_msg));
135     if (dex_file.get() != nullptr) {
136       dex_files->push_back(dex_file.release());
137       return true;
138     } else {
139       return false;
140     }
141   }
142   *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename);
143   return false;
144 }
145 
GetPermissions() const146 int DexFile::GetPermissions() const {
147   if (mem_map_.get() == NULL) {
148     return 0;
149   } else {
150     return mem_map_->GetProtect();
151   }
152 }
153 
IsReadOnly() const154 bool DexFile::IsReadOnly() const {
155   return GetPermissions() == PROT_READ;
156 }
157 
EnableWrite() const158 bool DexFile::EnableWrite() const {
159   CHECK(IsReadOnly());
160   if (mem_map_.get() == NULL) {
161     return false;
162   } else {
163     return mem_map_->Protect(PROT_READ | PROT_WRITE);
164   }
165 }
166 
DisableWrite() const167 bool DexFile::DisableWrite() const {
168   CHECK(!IsReadOnly());
169   if (mem_map_.get() == NULL) {
170     return false;
171   } else {
172     return mem_map_->Protect(PROT_READ);
173   }
174 }
175 
OpenFile(int fd,const char * location,bool verify,std::string * error_msg)176 const DexFile* DexFile::OpenFile(int fd, const char* location, bool verify,
177                                  std::string* error_msg) {
178   CHECK(location != nullptr);
179   std::unique_ptr<MemMap> map;
180   {
181     ScopedFd delayed_close(fd);
182     struct stat sbuf;
183     memset(&sbuf, 0, sizeof(sbuf));
184     if (fstat(fd, &sbuf) == -1) {
185       *error_msg = StringPrintf("DexFile: fstat '%s' failed: %s", location, strerror(errno));
186       return nullptr;
187     }
188     if (S_ISDIR(sbuf.st_mode)) {
189       *error_msg = StringPrintf("Attempt to mmap directory '%s'", location);
190       return nullptr;
191     }
192     size_t length = sbuf.st_size;
193     map.reset(MemMap::MapFile(length, PROT_READ, MAP_PRIVATE, fd, 0, location, error_msg));
194     if (map.get() == nullptr) {
195       DCHECK(!error_msg->empty());
196       return nullptr;
197     }
198   }
199 
200   if (map->Size() < sizeof(DexFile::Header)) {
201     *error_msg = StringPrintf(
202         "DexFile: failed to open dex file '%s' that is too short to have a header", location);
203     return nullptr;
204   }
205 
206   const Header* dex_header = reinterpret_cast<const Header*>(map->Begin());
207 
208   const DexFile* dex_file = OpenMemory(location, dex_header->checksum_, map.release(), error_msg);
209   if (dex_file == nullptr) {
210     *error_msg = StringPrintf("Failed to open dex file '%s' from memory: %s", location,
211                               error_msg->c_str());
212     return nullptr;
213   }
214 
215   if (verify && !DexFileVerifier::Verify(dex_file, dex_file->Begin(), dex_file->Size(), location,
216                                          error_msg)) {
217     return nullptr;
218   }
219 
220   return dex_file;
221 }
222 
223 const char* DexFile::kClassesDex = "classes.dex";
224 
OpenZip(int fd,const std::string & location,std::string * error_msg,std::vector<const DexFile * > * dex_files)225 bool DexFile::OpenZip(int fd, const std::string& location, std::string* error_msg,
226                       std::vector<const  DexFile*>* dex_files) {
227   std::unique_ptr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(fd, location.c_str(), error_msg));
228   if (zip_archive.get() == nullptr) {
229     DCHECK(!error_msg->empty());
230     return false;
231   }
232   return DexFile::OpenFromZip(*zip_archive, location, error_msg, dex_files);
233 }
234 
OpenMemory(const std::string & location,uint32_t location_checksum,MemMap * mem_map,std::string * error_msg)235 const DexFile* DexFile::OpenMemory(const std::string& location,
236                                    uint32_t location_checksum,
237                                    MemMap* mem_map,
238                                    std::string* error_msg) {
239   return OpenMemory(mem_map->Begin(),
240                     mem_map->Size(),
241                     location,
242                     location_checksum,
243                     mem_map,
244                     error_msg);
245 }
246 
Open(const ZipArchive & zip_archive,const char * entry_name,const std::string & location,std::string * error_msg,ZipOpenErrorCode * error_code)247 const DexFile* DexFile::Open(const ZipArchive& zip_archive, const char* entry_name,
248                              const std::string& location, std::string* error_msg,
249                              ZipOpenErrorCode* error_code) {
250   CHECK(!location.empty());
251   std::unique_ptr<ZipEntry> zip_entry(zip_archive.Find(entry_name, error_msg));
252   if (zip_entry.get() == NULL) {
253     *error_code = ZipOpenErrorCode::kEntryNotFound;
254     return nullptr;
255   }
256   std::unique_ptr<MemMap> map(zip_entry->ExtractToMemMap(location.c_str(), entry_name, error_msg));
257   if (map.get() == NULL) {
258     *error_msg = StringPrintf("Failed to extract '%s' from '%s': %s", entry_name, location.c_str(),
259                               error_msg->c_str());
260     *error_code = ZipOpenErrorCode::kExtractToMemoryError;
261     return nullptr;
262   }
263   std::unique_ptr<const DexFile> dex_file(OpenMemory(location, zip_entry->GetCrc32(), map.release(),
264                                                error_msg));
265   if (dex_file.get() == nullptr) {
266     *error_msg = StringPrintf("Failed to open dex file '%s' from memory: %s", location.c_str(),
267                               error_msg->c_str());
268     *error_code = ZipOpenErrorCode::kDexFileError;
269     return nullptr;
270   }
271   if (!dex_file->DisableWrite()) {
272     *error_msg = StringPrintf("Failed to make dex file '%s' read only", location.c_str());
273     *error_code = ZipOpenErrorCode::kMakeReadOnlyError;
274     return nullptr;
275   }
276   CHECK(dex_file->IsReadOnly()) << location;
277   if (!DexFileVerifier::Verify(dex_file.get(), dex_file->Begin(), dex_file->Size(),
278                                location.c_str(), error_msg)) {
279     *error_code = ZipOpenErrorCode::kVerifyError;
280     return nullptr;
281   }
282   *error_code = ZipOpenErrorCode::kNoError;
283   return dex_file.release();
284 }
285 
OpenFromZip(const ZipArchive & zip_archive,const std::string & location,std::string * error_msg,std::vector<const DexFile * > * dex_files)286 bool DexFile::OpenFromZip(const ZipArchive& zip_archive, const std::string& location,
287                           std::string* error_msg, std::vector<const DexFile*>* dex_files) {
288   ZipOpenErrorCode error_code;
289   std::unique_ptr<const DexFile> dex_file(Open(zip_archive, kClassesDex, location, error_msg,
290                                                &error_code));
291   if (dex_file.get() == nullptr) {
292     return false;
293   } else {
294     // Had at least classes.dex.
295     dex_files->push_back(dex_file.release());
296 
297     // Now try some more.
298     size_t i = 2;
299 
300     // We could try to avoid std::string allocations by working on a char array directly. As we
301     // do not expect a lot of iterations, this seems too involved and brittle.
302 
303     while (i < 100) {
304       std::string name = StringPrintf("classes%zu.dex", i);
305       std::string fake_location = location + kMultiDexSeparator + name;
306       std::unique_ptr<const DexFile> next_dex_file(Open(zip_archive, name.c_str(), fake_location,
307                                                         error_msg, &error_code));
308       if (next_dex_file.get() == nullptr) {
309         if (error_code != ZipOpenErrorCode::kEntryNotFound) {
310           LOG(WARNING) << error_msg;
311         }
312         break;
313       } else {
314         dex_files->push_back(next_dex_file.release());
315       }
316 
317       i++;
318     }
319 
320     return true;
321   }
322 }
323 
324 
OpenMemory(const byte * base,size_t size,const std::string & location,uint32_t location_checksum,MemMap * mem_map,std::string * error_msg)325 const DexFile* DexFile::OpenMemory(const byte* base,
326                                    size_t size,
327                                    const std::string& location,
328                                    uint32_t location_checksum,
329                                    MemMap* mem_map, std::string* error_msg) {
330   CHECK_ALIGNED(base, 4);  // various dex file structures must be word aligned
331   std::unique_ptr<DexFile> dex_file(new DexFile(base, size, location, location_checksum, mem_map));
332   if (!dex_file->Init(error_msg)) {
333     return nullptr;
334   } else {
335     return dex_file.release();
336   }
337 }
338 
DexFile(const byte * base,size_t size,const std::string & location,uint32_t location_checksum,MemMap * mem_map)339 DexFile::DexFile(const byte* base, size_t size,
340                  const std::string& location,
341                  uint32_t location_checksum,
342                  MemMap* mem_map)
343     : begin_(base),
344       size_(size),
345       location_(location),
346       location_checksum_(location_checksum),
347       mem_map_(mem_map),
348       header_(reinterpret_cast<const Header*>(base)),
349       string_ids_(reinterpret_cast<const StringId*>(base + header_->string_ids_off_)),
350       type_ids_(reinterpret_cast<const TypeId*>(base + header_->type_ids_off_)),
351       field_ids_(reinterpret_cast<const FieldId*>(base + header_->field_ids_off_)),
352       method_ids_(reinterpret_cast<const MethodId*>(base + header_->method_ids_off_)),
353       proto_ids_(reinterpret_cast<const ProtoId*>(base + header_->proto_ids_off_)),
354       class_defs_(reinterpret_cast<const ClassDef*>(base + header_->class_defs_off_)),
355       find_class_def_misses_(0),
356       class_def_index_(nullptr),
357       build_class_def_index_mutex_("DexFile index creation mutex") {
358   CHECK(begin_ != NULL) << GetLocation();
359   CHECK_GT(size_, 0U) << GetLocation();
360 }
361 
~DexFile()362 DexFile::~DexFile() {
363   // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and
364   // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could
365   // re-attach, but cleaning up these global references is not obviously useful. It's not as if
366   // the global reference table is otherwise empty!
367   // Remove the index if one were created.
368   delete class_def_index_.LoadRelaxed();
369 }
370 
Init(std::string * error_msg)371 bool DexFile::Init(std::string* error_msg) {
372   if (!CheckMagicAndVersion(error_msg)) {
373     return false;
374   }
375   return true;
376 }
377 
CheckMagicAndVersion(std::string * error_msg) const378 bool DexFile::CheckMagicAndVersion(std::string* error_msg) const {
379   if (!IsMagicValid(header_->magic_)) {
380     std::ostringstream oss;
381     oss << "Unrecognized magic number in "  << GetLocation() << ":"
382             << " " << header_->magic_[0]
383             << " " << header_->magic_[1]
384             << " " << header_->magic_[2]
385             << " " << header_->magic_[3];
386     *error_msg = oss.str();
387     return false;
388   }
389   if (!IsVersionValid(header_->magic_)) {
390     std::ostringstream oss;
391     oss << "Unrecognized version number in "  << GetLocation() << ":"
392             << " " << header_->magic_[4]
393             << " " << header_->magic_[5]
394             << " " << header_->magic_[6]
395             << " " << header_->magic_[7];
396     *error_msg = oss.str();
397     return false;
398   }
399   return true;
400 }
401 
IsMagicValid(const byte * magic)402 bool DexFile::IsMagicValid(const byte* magic) {
403   return (memcmp(magic, kDexMagic, sizeof(kDexMagic)) == 0);
404 }
405 
IsVersionValid(const byte * magic)406 bool DexFile::IsVersionValid(const byte* magic) {
407   const byte* version = &magic[sizeof(kDexMagic)];
408   return (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) == 0);
409 }
410 
GetVersion() const411 uint32_t DexFile::GetVersion() const {
412   const char* version = reinterpret_cast<const char*>(&GetHeader().magic_[sizeof(kDexMagic)]);
413   return atoi(version);
414 }
415 
FindClassDef(const char * descriptor) const416 const DexFile::ClassDef* DexFile::FindClassDef(const char* descriptor) const {
417   // If we have an index lookup the descriptor via that as its constant time to search.
418   Index* index = class_def_index_.LoadSequentiallyConsistent();
419   if (index != nullptr) {
420     auto it = index->find(descriptor);
421     return (it == index->end()) ? nullptr : it->second;
422   }
423   // Fast path for rate no class defs case.
424   uint32_t num_class_defs = NumClassDefs();
425   if (num_class_defs == 0) {
426     return nullptr;
427   }
428   // Search for class def with 2 binary searches and then a linear search.
429   const StringId* string_id = FindStringId(descriptor);
430   if (string_id != nullptr) {
431     const TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id));
432     if (type_id != nullptr) {
433       uint16_t type_idx = GetIndexForTypeId(*type_id);
434       for (size_t i = 0; i < num_class_defs; ++i) {
435         const ClassDef& class_def = GetClassDef(i);
436         if (class_def.class_idx_ == type_idx) {
437           return &class_def;
438         }
439       }
440     }
441   }
442   // A miss. If we've had kMaxFailedDexClassDefLookups misses then build an index to speed things
443   // up. This isn't done eagerly at construction as construction is not performed in multi-threaded
444   // sections of tools like dex2oat. If we're lazy we hopefully increase the chance of balancing
445   // out which thread builds the index.
446   find_class_def_misses_++;
447   const uint32_t kMaxFailedDexClassDefLookups = 100;
448   if (find_class_def_misses_ > kMaxFailedDexClassDefLookups) {
449     MutexLock mu(Thread::Current(), build_class_def_index_mutex_);
450     // Are we the first ones building the index?
451     if (class_def_index_.LoadSequentiallyConsistent() == nullptr) {
452       index = new Index(num_class_defs);
453       for (uint32_t i = 0; i < num_class_defs;  ++i) {
454         const ClassDef& class_def = GetClassDef(i);
455         const char* descriptor = GetClassDescriptor(class_def);
456         index->insert(std::make_pair(descriptor, &class_def));
457       }
458       class_def_index_.StoreSequentiallyConsistent(index);
459     }
460   }
461   return nullptr;
462 }
463 
FindClassDef(uint16_t type_idx) const464 const DexFile::ClassDef* DexFile::FindClassDef(uint16_t type_idx) const {
465   size_t num_class_defs = NumClassDefs();
466   for (size_t i = 0; i < num_class_defs; ++i) {
467     const ClassDef& class_def = GetClassDef(i);
468     if (class_def.class_idx_ == type_idx) {
469       return &class_def;
470     }
471   }
472   return NULL;
473 }
474 
FindFieldId(const DexFile::TypeId & declaring_klass,const DexFile::StringId & name,const DexFile::TypeId & type) const475 const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass,
476                                               const DexFile::StringId& name,
477                                               const DexFile::TypeId& type) const {
478   // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
479   const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
480   const uint32_t name_idx = GetIndexForStringId(name);
481   const uint16_t type_idx = GetIndexForTypeId(type);
482   int32_t lo = 0;
483   int32_t hi = NumFieldIds() - 1;
484   while (hi >= lo) {
485     int32_t mid = (hi + lo) / 2;
486     const DexFile::FieldId& field = GetFieldId(mid);
487     if (class_idx > field.class_idx_) {
488       lo = mid + 1;
489     } else if (class_idx < field.class_idx_) {
490       hi = mid - 1;
491     } else {
492       if (name_idx > field.name_idx_) {
493         lo = mid + 1;
494       } else if (name_idx < field.name_idx_) {
495         hi = mid - 1;
496       } else {
497         if (type_idx > field.type_idx_) {
498           lo = mid + 1;
499         } else if (type_idx < field.type_idx_) {
500           hi = mid - 1;
501         } else {
502           return &field;
503         }
504       }
505     }
506   }
507   return NULL;
508 }
509 
FindMethodId(const DexFile::TypeId & declaring_klass,const DexFile::StringId & name,const DexFile::ProtoId & signature) const510 const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass,
511                                                const DexFile::StringId& name,
512                                                const DexFile::ProtoId& signature) const {
513   // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
514   const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
515   const uint32_t name_idx = GetIndexForStringId(name);
516   const uint16_t proto_idx = GetIndexForProtoId(signature);
517   int32_t lo = 0;
518   int32_t hi = NumMethodIds() - 1;
519   while (hi >= lo) {
520     int32_t mid = (hi + lo) / 2;
521     const DexFile::MethodId& method = GetMethodId(mid);
522     if (class_idx > method.class_idx_) {
523       lo = mid + 1;
524     } else if (class_idx < method.class_idx_) {
525       hi = mid - 1;
526     } else {
527       if (name_idx > method.name_idx_) {
528         lo = mid + 1;
529       } else if (name_idx < method.name_idx_) {
530         hi = mid - 1;
531       } else {
532         if (proto_idx > method.proto_idx_) {
533           lo = mid + 1;
534         } else if (proto_idx < method.proto_idx_) {
535           hi = mid - 1;
536         } else {
537           return &method;
538         }
539       }
540     }
541   }
542   return NULL;
543 }
544 
FindStringId(const char * string) const545 const DexFile::StringId* DexFile::FindStringId(const char* string) const {
546   int32_t lo = 0;
547   int32_t hi = NumStringIds() - 1;
548   while (hi >= lo) {
549     int32_t mid = (hi + lo) / 2;
550     const DexFile::StringId& str_id = GetStringId(mid);
551     const char* str = GetStringData(str_id);
552     int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string, str);
553     if (compare > 0) {
554       lo = mid + 1;
555     } else if (compare < 0) {
556       hi = mid - 1;
557     } else {
558       return &str_id;
559     }
560   }
561   return NULL;
562 }
563 
FindStringId(const uint16_t * string) const564 const DexFile::StringId* DexFile::FindStringId(const uint16_t* string) const {
565   int32_t lo = 0;
566   int32_t hi = NumStringIds() - 1;
567   while (hi >= lo) {
568     int32_t mid = (hi + lo) / 2;
569     const DexFile::StringId& str_id = GetStringId(mid);
570     const char* str = GetStringData(str_id);
571     int compare = CompareModifiedUtf8ToUtf16AsCodePointValues(str, string);
572     if (compare > 0) {
573       lo = mid + 1;
574     } else if (compare < 0) {
575       hi = mid - 1;
576     } else {
577       return &str_id;
578     }
579   }
580   return NULL;
581 }
582 
FindTypeId(uint32_t string_idx) const583 const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const {
584   int32_t lo = 0;
585   int32_t hi = NumTypeIds() - 1;
586   while (hi >= lo) {
587     int32_t mid = (hi + lo) / 2;
588     const TypeId& type_id = GetTypeId(mid);
589     if (string_idx > type_id.descriptor_idx_) {
590       lo = mid + 1;
591     } else if (string_idx < type_id.descriptor_idx_) {
592       hi = mid - 1;
593     } else {
594       return &type_id;
595     }
596   }
597   return NULL;
598 }
599 
FindProtoId(uint16_t return_type_idx,const uint16_t * signature_type_idxs,uint32_t signature_length) const600 const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx,
601                                              const uint16_t* signature_type_idxs,
602                                              uint32_t signature_length) const {
603   int32_t lo = 0;
604   int32_t hi = NumProtoIds() - 1;
605   while (hi >= lo) {
606     int32_t mid = (hi + lo) / 2;
607     const DexFile::ProtoId& proto = GetProtoId(mid);
608     int compare = return_type_idx - proto.return_type_idx_;
609     if (compare == 0) {
610       DexFileParameterIterator it(*this, proto);
611       size_t i = 0;
612       while (it.HasNext() && i < signature_length && compare == 0) {
613         compare = signature_type_idxs[i] - it.GetTypeIdx();
614         it.Next();
615         i++;
616       }
617       if (compare == 0) {
618         if (it.HasNext()) {
619           compare = -1;
620         } else if (i < signature_length) {
621           compare = 1;
622         }
623       }
624     }
625     if (compare > 0) {
626       lo = mid + 1;
627     } else if (compare < 0) {
628       hi = mid - 1;
629     } else {
630       return &proto;
631     }
632   }
633   return NULL;
634 }
635 
636 // Given a signature place the type ids into the given vector
CreateTypeList(const StringPiece & signature,uint16_t * return_type_idx,std::vector<uint16_t> * param_type_idxs) const637 bool DexFile::CreateTypeList(const StringPiece& signature, uint16_t* return_type_idx,
638                              std::vector<uint16_t>* param_type_idxs) const {
639   if (signature[0] != '(') {
640     return false;
641   }
642   size_t offset = 1;
643   size_t end = signature.size();
644   bool process_return = false;
645   while (offset < end) {
646     size_t start_offset = offset;
647     char c = signature[offset];
648     offset++;
649     if (c == ')') {
650       process_return = true;
651       continue;
652     }
653     while (c == '[') {  // process array prefix
654       if (offset >= end) {  // expect some descriptor following [
655         return false;
656       }
657       c = signature[offset];
658       offset++;
659     }
660     if (c == 'L') {  // process type descriptors
661       do {
662         if (offset >= end) {  // unexpected early termination of descriptor
663           return false;
664         }
665         c = signature[offset];
666         offset++;
667       } while (c != ';');
668     }
669     // TODO: avoid creating a std::string just to get a 0-terminated char array
670     std::string descriptor(signature.data() + start_offset, offset - start_offset);
671     const DexFile::StringId* string_id = FindStringId(descriptor.c_str());
672     if (string_id == NULL) {
673       return false;
674     }
675     const DexFile::TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id));
676     if (type_id == NULL) {
677       return false;
678     }
679     uint16_t type_idx = GetIndexForTypeId(*type_id);
680     if (!process_return) {
681       param_type_idxs->push_back(type_idx);
682     } else {
683       *return_type_idx = type_idx;
684       return offset == end;  // return true if the signature had reached a sensible end
685     }
686   }
687   return false;  // failed to correctly parse return type
688 }
689 
CreateSignature(const StringPiece & signature) const690 const Signature DexFile::CreateSignature(const StringPiece& signature) const {
691   uint16_t return_type_idx;
692   std::vector<uint16_t> param_type_indices;
693   bool success = CreateTypeList(signature, &return_type_idx, &param_type_indices);
694   if (!success) {
695     return Signature::NoSignature();
696   }
697   const ProtoId* proto_id = FindProtoId(return_type_idx, param_type_indices);
698   if (proto_id == NULL) {
699     return Signature::NoSignature();
700   }
701   return Signature(this, *proto_id);
702 }
703 
GetLineNumFromPC(mirror::ArtMethod * method,uint32_t rel_pc) const704 int32_t DexFile::GetLineNumFromPC(mirror::ArtMethod* method, uint32_t rel_pc) const {
705   // For native method, lineno should be -2 to indicate it is native. Note that
706   // "line number == -2" is how libcore tells from StackTraceElement.
707   if (method->GetCodeItemOffset() == 0) {
708     return -2;
709   }
710 
711   const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
712   DCHECK(code_item != NULL) << PrettyMethod(method) << " " << GetLocation();
713 
714   // A method with no line number info should return -1
715   LineNumFromPcContext context(rel_pc, -1);
716   DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb,
717                   NULL, &context);
718   return context.line_num_;
719 }
720 
FindTryItem(const CodeItem & code_item,uint32_t address)721 int32_t DexFile::FindTryItem(const CodeItem &code_item, uint32_t address) {
722   // Note: Signed type is important for max and min.
723   int32_t min = 0;
724   int32_t max = code_item.tries_size_ - 1;
725 
726   while (min <= max) {
727     int32_t mid = min + ((max - min) / 2);
728 
729     const art::DexFile::TryItem* ti = GetTryItems(code_item, mid);
730     uint32_t start = ti->start_addr_;
731     uint32_t end = start + ti->insn_count_;
732 
733     if (address < start) {
734       max = mid - 1;
735     } else if (address >= end) {
736       min = mid + 1;
737     } else {  // We have a winner!
738       return mid;
739     }
740   }
741   // No match.
742   return -1;
743 }
744 
FindCatchHandlerOffset(const CodeItem & code_item,uint32_t address)745 int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, uint32_t address) {
746   int32_t try_item = FindTryItem(code_item, address);
747   if (try_item == -1) {
748     return -1;
749   } else {
750     return DexFile::GetTryItems(code_item, try_item)->handler_off_;
751   }
752 }
753 
DecodeDebugInfo0(const CodeItem * code_item,bool is_static,uint32_t method_idx,DexDebugNewPositionCb position_cb,DexDebugNewLocalCb local_cb,void * context,const byte * stream,LocalInfo * local_in_reg) const754 void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
755                                DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
756                                void* context, const byte* stream, LocalInfo* local_in_reg) const {
757   uint32_t line = DecodeUnsignedLeb128(&stream);
758   uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
759   uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
760   uint32_t address = 0;
761   bool need_locals = (local_cb != NULL);
762 
763   if (!is_static) {
764     if (need_locals) {
765       const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
766       local_in_reg[arg_reg].name_ = "this";
767       local_in_reg[arg_reg].descriptor_ = descriptor;
768       local_in_reg[arg_reg].signature_ = NULL;
769       local_in_reg[arg_reg].start_address_ = 0;
770       local_in_reg[arg_reg].is_live_ = true;
771     }
772     arg_reg++;
773   }
774 
775   DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
776   for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
777     if (arg_reg >= code_item->registers_size_) {
778       LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
779                  << " >= " << code_item->registers_size_ << ") in " << GetLocation();
780       return;
781     }
782     uint32_t id = DecodeUnsignedLeb128P1(&stream);
783     const char* descriptor = it.GetDescriptor();
784     if (need_locals && id != kDexNoIndex) {
785       const char* name = StringDataByIdx(id);
786       local_in_reg[arg_reg].name_ = name;
787       local_in_reg[arg_reg].descriptor_ = descriptor;
788       local_in_reg[arg_reg].signature_ = NULL;
789       local_in_reg[arg_reg].start_address_ = address;
790       local_in_reg[arg_reg].is_live_ = true;
791     }
792     switch (*descriptor) {
793       case 'D':
794       case 'J':
795         arg_reg += 2;
796         break;
797       default:
798         arg_reg += 1;
799         break;
800     }
801   }
802 
803   if (it.HasNext()) {
804     LOG(ERROR) << "invalid stream - problem with parameter iterator in " << GetLocation()
805                << " for method " << PrettyMethod(method_idx, *this);
806     return;
807   }
808 
809   for (;;)  {
810     uint8_t opcode = *stream++;
811     uint16_t reg;
812     uint32_t name_idx;
813     uint32_t descriptor_idx;
814     uint32_t signature_idx = 0;
815 
816     switch (opcode) {
817       case DBG_END_SEQUENCE:
818         return;
819 
820       case DBG_ADVANCE_PC:
821         address += DecodeUnsignedLeb128(&stream);
822         break;
823 
824       case DBG_ADVANCE_LINE:
825         line += DecodeSignedLeb128(&stream);
826         break;
827 
828       case DBG_START_LOCAL:
829       case DBG_START_LOCAL_EXTENDED:
830         reg = DecodeUnsignedLeb128(&stream);
831         if (reg > code_item->registers_size_) {
832           LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
833                      << code_item->registers_size_ << ") in " << GetLocation();
834           return;
835         }
836 
837         name_idx = DecodeUnsignedLeb128P1(&stream);
838         descriptor_idx = DecodeUnsignedLeb128P1(&stream);
839         if (opcode == DBG_START_LOCAL_EXTENDED) {
840           signature_idx = DecodeUnsignedLeb128P1(&stream);
841         }
842 
843         // Emit what was previously there, if anything
844         if (need_locals) {
845           InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb);
846 
847           local_in_reg[reg].name_ = StringDataByIdx(name_idx);
848           local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx);
849           if (opcode == DBG_START_LOCAL_EXTENDED) {
850             local_in_reg[reg].signature_ = StringDataByIdx(signature_idx);
851           }
852           local_in_reg[reg].start_address_ = address;
853           local_in_reg[reg].is_live_ = true;
854         }
855         break;
856 
857       case DBG_END_LOCAL:
858         reg = DecodeUnsignedLeb128(&stream);
859         if (reg > code_item->registers_size_) {
860           LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
861                      << code_item->registers_size_ << ") in " << GetLocation();
862           return;
863         }
864 
865         if (need_locals) {
866           InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb);
867           local_in_reg[reg].is_live_ = false;
868         }
869         break;
870 
871       case DBG_RESTART_LOCAL:
872         reg = DecodeUnsignedLeb128(&stream);
873         if (reg > code_item->registers_size_) {
874           LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
875                      << code_item->registers_size_ << ") in " << GetLocation();
876           return;
877         }
878 
879         if (need_locals) {
880           if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) {
881             LOG(ERROR) << "invalid stream - no name or descriptor in " << GetLocation();
882             return;
883           }
884 
885           // If the register is live, the "restart" is superfluous,
886           // and we don't want to mess with the existing start address.
887           if (!local_in_reg[reg].is_live_) {
888             local_in_reg[reg].start_address_ = address;
889             local_in_reg[reg].is_live_ = true;
890           }
891         }
892         break;
893 
894       case DBG_SET_PROLOGUE_END:
895       case DBG_SET_EPILOGUE_BEGIN:
896       case DBG_SET_FILE:
897         break;
898 
899       default: {
900         int adjopcode = opcode - DBG_FIRST_SPECIAL;
901 
902         address += adjopcode / DBG_LINE_RANGE;
903         line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
904 
905         if (position_cb != NULL) {
906           if (position_cb(context, address, line)) {
907             // early exit
908             return;
909           }
910         }
911         break;
912       }
913     }
914   }
915 }
916 
DecodeDebugInfo(const CodeItem * code_item,bool is_static,uint32_t method_idx,DexDebugNewPositionCb position_cb,DexDebugNewLocalCb local_cb,void * context) const917 void DexFile::DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
918                               DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
919                               void* context) const {
920   DCHECK(code_item != nullptr);
921   const byte* stream = GetDebugInfoStream(code_item);
922   std::unique_ptr<LocalInfo[]> local_in_reg(local_cb != NULL ?
923                                       new LocalInfo[code_item->registers_size_] :
924                                       NULL);
925   if (stream != NULL) {
926     DecodeDebugInfo0(code_item, is_static, method_idx, position_cb, local_cb, context, stream, &local_in_reg[0]);
927   }
928   for (int reg = 0; reg < code_item->registers_size_; reg++) {
929     InvokeLocalCbIfLive(context, reg, code_item->insns_size_in_code_units_, &local_in_reg[0], local_cb);
930   }
931 }
932 
LineNumForPcCb(void * raw_context,uint32_t address,uint32_t line_num)933 bool DexFile::LineNumForPcCb(void* raw_context, uint32_t address, uint32_t line_num) {
934   LineNumFromPcContext* context = reinterpret_cast<LineNumFromPcContext*>(raw_context);
935 
936   // We know that this callback will be called in
937   // ascending address order, so keep going until we find
938   // a match or we've just gone past it.
939   if (address > context->address_) {
940     // The line number from the previous positions callback
941     // wil be the final result.
942     return true;
943   } else {
944     context->line_num_ = line_num;
945     return address == context->address_;
946   }
947 }
948 
IsMultiDexLocation(const char * location)949 bool DexFile::IsMultiDexLocation(const char* location) {
950   return strrchr(location, kMultiDexSeparator) != nullptr;
951 }
952 
GetMultiDexClassesDexName(size_t number,const char * dex_location)953 std::string DexFile::GetMultiDexClassesDexName(size_t number, const char* dex_location) {
954   if (number == 0) {
955     return dex_location;
956   } else {
957     return StringPrintf("%s" kMultiDexSeparatorString "classes%zu.dex", dex_location, number + 1);
958   }
959 }
960 
GetDexCanonicalLocation(const char * dex_location)961 std::string DexFile::GetDexCanonicalLocation(const char* dex_location) {
962   CHECK_NE(dex_location, static_cast<const char*>(nullptr));
963   std::string base_location = GetBaseLocation(dex_location);
964   const char* suffix = dex_location + base_location.size();
965   DCHECK(suffix[0] == 0 || suffix[0] == kMultiDexSeparator);
966   UniqueCPtr<const char[]> path(realpath(base_location.c_str(), nullptr));
967   if (path != nullptr && path.get() != base_location) {
968     return std::string(path.get()) + suffix;
969   } else if (suffix[0] == 0) {
970     return base_location;
971   } else {
972     return dex_location;
973   }
974 }
975 
operator <<(std::ostream & os,const DexFile & dex_file)976 std::ostream& operator<<(std::ostream& os, const DexFile& dex_file) {
977   os << StringPrintf("[DexFile: %s dex-checksum=%08x location-checksum=%08x %p-%p]",
978                      dex_file.GetLocation().c_str(),
979                      dex_file.GetHeader().checksum_, dex_file.GetLocationChecksum(),
980                      dex_file.Begin(), dex_file.Begin() + dex_file.Size());
981   return os;
982 }
983 
ToString() const984 std::string Signature::ToString() const {
985   if (dex_file_ == nullptr) {
986     CHECK(proto_id_ == nullptr);
987     return "<no signature>";
988   }
989   const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_);
990   std::string result;
991   if (params == nullptr) {
992     result += "()";
993   } else {
994     result += "(";
995     for (uint32_t i = 0; i < params->Size(); ++i) {
996       result += dex_file_->StringByTypeIdx(params->GetTypeItem(i).type_idx_);
997     }
998     result += ")";
999   }
1000   result += dex_file_->StringByTypeIdx(proto_id_->return_type_idx_);
1001   return result;
1002 }
1003 
operator ==(const StringPiece & rhs) const1004 bool Signature::operator==(const StringPiece& rhs) const {
1005   if (dex_file_ == nullptr) {
1006     return false;
1007   }
1008   StringPiece tail(rhs);
1009   if (!tail.starts_with("(")) {
1010     return false;  // Invalid signature
1011   }
1012   tail.remove_prefix(1);  // "(";
1013   const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_);
1014   if (params != nullptr) {
1015     for (uint32_t i = 0; i < params->Size(); ++i) {
1016       StringPiece param(dex_file_->StringByTypeIdx(params->GetTypeItem(i).type_idx_));
1017       if (!tail.starts_with(param)) {
1018         return false;
1019       }
1020       tail.remove_prefix(param.length());
1021     }
1022   }
1023   if (!tail.starts_with(")")) {
1024     return false;
1025   }
1026   tail.remove_prefix(1);  // ")";
1027   return tail == dex_file_->StringByTypeIdx(proto_id_->return_type_idx_);
1028 }
1029 
operator <<(std::ostream & os,const Signature & sig)1030 std::ostream& operator<<(std::ostream& os, const Signature& sig) {
1031   return os << sig.ToString();
1032 }
1033 
1034 // Decodes the header section from the class data bytes.
ReadClassDataHeader()1035 void ClassDataItemIterator::ReadClassDataHeader() {
1036   CHECK(ptr_pos_ != NULL);
1037   header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
1038   header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_);
1039   header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
1040   header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_);
1041 }
1042 
ReadClassDataField()1043 void ClassDataItemIterator::ReadClassDataField() {
1044   field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
1045   field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
1046   if (last_idx_ != 0 && field_.field_idx_delta_ == 0) {
1047     LOG(WARNING) << "Duplicate field in " << dex_file_.GetLocation();
1048   }
1049 }
1050 
ReadClassDataMethod()1051 void ClassDataItemIterator::ReadClassDataMethod() {
1052   method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_);
1053   method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
1054   method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
1055   if (last_idx_ != 0 && method_.method_idx_delta_ == 0) {
1056     LOG(WARNING) << "Duplicate method in " << dex_file_.GetLocation();
1057   }
1058 }
1059 
1060 // Read a signed integer.  "zwidth" is the zero-based byte count.
ReadSignedInt(const byte * ptr,int zwidth)1061 static int32_t ReadSignedInt(const byte* ptr, int zwidth) {
1062   int32_t val = 0;
1063   for (int i = zwidth; i >= 0; --i) {
1064     val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
1065   }
1066   val >>= (3 - zwidth) * 8;
1067   return val;
1068 }
1069 
1070 // Read an unsigned integer.  "zwidth" is the zero-based byte count,
1071 // "fill_on_right" indicates which side we want to zero-fill from.
ReadUnsignedInt(const byte * ptr,int zwidth,bool fill_on_right)1072 static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth, bool fill_on_right) {
1073   uint32_t val = 0;
1074   if (!fill_on_right) {
1075     for (int i = zwidth; i >= 0; --i) {
1076       val = (val >> 8) | (((uint32_t)*ptr++) << 24);
1077     }
1078     val >>= (3 - zwidth) * 8;
1079   } else {
1080     for (int i = zwidth; i >= 0; --i) {
1081       val = (val >> 8) | (((uint32_t)*ptr++) << 24);
1082     }
1083   }
1084   return val;
1085 }
1086 
1087 // Read a signed long.  "zwidth" is the zero-based byte count.
ReadSignedLong(const byte * ptr,int zwidth)1088 static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
1089   int64_t val = 0;
1090   for (int i = zwidth; i >= 0; --i) {
1091     val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
1092   }
1093   val >>= (7 - zwidth) * 8;
1094   return val;
1095 }
1096 
1097 // Read an unsigned long.  "zwidth" is the zero-based byte count,
1098 // "fill_on_right" indicates which side we want to zero-fill from.
ReadUnsignedLong(const byte * ptr,int zwidth,bool fill_on_right)1099 static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right) {
1100   uint64_t val = 0;
1101   if (!fill_on_right) {
1102     for (int i = zwidth; i >= 0; --i) {
1103       val = (val >> 8) | (((uint64_t)*ptr++) << 56);
1104     }
1105     val >>= (7 - zwidth) * 8;
1106   } else {
1107     for (int i = zwidth; i >= 0; --i) {
1108       val = (val >> 8) | (((uint64_t)*ptr++) << 56);
1109     }
1110   }
1111   return val;
1112 }
1113 
EncodedStaticFieldValueIterator(const DexFile & dex_file,Handle<mirror::DexCache> * dex_cache,Handle<mirror::ClassLoader> * class_loader,ClassLinker * linker,const DexFile::ClassDef & class_def)1114 EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
1115                                                                  Handle<mirror::DexCache>* dex_cache,
1116                                                                  Handle<mirror::ClassLoader>* class_loader,
1117                                                                  ClassLinker* linker,
1118                                                                  const DexFile::ClassDef& class_def)
1119     : dex_file_(dex_file), dex_cache_(dex_cache), class_loader_(class_loader), linker_(linker),
1120       array_size_(), pos_(-1), type_(kByte) {
1121   DCHECK(dex_cache != nullptr);
1122   DCHECK(class_loader != nullptr);
1123   ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def);
1124   if (ptr_ == NULL) {
1125     array_size_ = 0;
1126   } else {
1127     array_size_ = DecodeUnsignedLeb128(&ptr_);
1128   }
1129   if (array_size_ > 0) {
1130     Next();
1131   }
1132 }
1133 
Next()1134 void EncodedStaticFieldValueIterator::Next() {
1135   pos_++;
1136   if (pos_ >= array_size_) {
1137     return;
1138   }
1139   byte value_type = *ptr_++;
1140   byte value_arg = value_type >> kEncodedValueArgShift;
1141   size_t width = value_arg + 1;  // assume and correct later
1142   type_ = static_cast<ValueType>(value_type & kEncodedValueTypeMask);
1143   switch (type_) {
1144   case kBoolean:
1145     jval_.i = (value_arg != 0) ? 1 : 0;
1146     width = 0;
1147     break;
1148   case kByte:
1149     jval_.i = ReadSignedInt(ptr_, value_arg);
1150     CHECK(IsInt(8, jval_.i));
1151     break;
1152   case kShort:
1153     jval_.i = ReadSignedInt(ptr_, value_arg);
1154     CHECK(IsInt(16, jval_.i));
1155     break;
1156   case kChar:
1157     jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
1158     CHECK(IsUint(16, jval_.i));
1159     break;
1160   case kInt:
1161     jval_.i = ReadSignedInt(ptr_, value_arg);
1162     break;
1163   case kLong:
1164     jval_.j = ReadSignedLong(ptr_, value_arg);
1165     break;
1166   case kFloat:
1167     jval_.i = ReadUnsignedInt(ptr_, value_arg, true);
1168     break;
1169   case kDouble:
1170     jval_.j = ReadUnsignedLong(ptr_, value_arg, true);
1171     break;
1172   case kString:
1173   case kType:
1174     jval_.i = ReadUnsignedInt(ptr_, value_arg, false);
1175     break;
1176   case kField:
1177   case kMethod:
1178   case kEnum:
1179   case kArray:
1180   case kAnnotation:
1181     UNIMPLEMENTED(FATAL) << ": type " << type_;
1182     break;
1183   case kNull:
1184     jval_.l = NULL;
1185     width = 0;
1186     break;
1187   default:
1188     LOG(FATAL) << "Unreached";
1189   }
1190   ptr_ += width;
1191 }
1192 
1193 template<bool kTransactionActive>
ReadValueToField(mirror::ArtField * field) const1194 void EncodedStaticFieldValueIterator::ReadValueToField(mirror::ArtField* field) const {
1195   switch (type_) {
1196     case kBoolean: field->SetBoolean<kTransactionActive>(field->GetDeclaringClass(), jval_.z); break;
1197     case kByte:    field->SetByte<kTransactionActive>(field->GetDeclaringClass(), jval_.b); break;
1198     case kShort:   field->SetShort<kTransactionActive>(field->GetDeclaringClass(), jval_.s); break;
1199     case kChar:    field->SetChar<kTransactionActive>(field->GetDeclaringClass(), jval_.c); break;
1200     case kInt:     field->SetInt<kTransactionActive>(field->GetDeclaringClass(), jval_.i); break;
1201     case kLong:    field->SetLong<kTransactionActive>(field->GetDeclaringClass(), jval_.j); break;
1202     case kFloat:   field->SetFloat<kTransactionActive>(field->GetDeclaringClass(), jval_.f); break;
1203     case kDouble:  field->SetDouble<kTransactionActive>(field->GetDeclaringClass(), jval_.d); break;
1204     case kNull:    field->SetObject<kTransactionActive>(field->GetDeclaringClass(), NULL); break;
1205     case kString: {
1206       CHECK(!kMovingFields);
1207       mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, *dex_cache_);
1208       field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
1209       break;
1210     }
1211     case kType: {
1212       CHECK(!kMovingFields);
1213       mirror::Class* resolved = linker_->ResolveType(dex_file_, jval_.i, *dex_cache_,
1214                                                      *class_loader_);
1215       field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
1216       break;
1217     }
1218     default: UNIMPLEMENTED(FATAL) << ": type " << type_;
1219   }
1220 }
1221 template void EncodedStaticFieldValueIterator::ReadValueToField<true>(mirror::ArtField* field) const;
1222 template void EncodedStaticFieldValueIterator::ReadValueToField<false>(mirror::ArtField* field) const;
1223 
CatchHandlerIterator(const DexFile::CodeItem & code_item,uint32_t address)1224 CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
1225   handler_.address_ = -1;
1226   int32_t offset = -1;
1227 
1228   // Short-circuit the overwhelmingly common cases.
1229   switch (code_item.tries_size_) {
1230     case 0:
1231       break;
1232     case 1: {
1233       const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
1234       uint32_t start = tries->start_addr_;
1235       if (address >= start) {
1236         uint32_t end = start + tries->insn_count_;
1237         if (address < end) {
1238           offset = tries->handler_off_;
1239         }
1240       }
1241       break;
1242     }
1243     default:
1244       offset = DexFile::FindCatchHandlerOffset(code_item, address);
1245   }
1246   Init(code_item, offset);
1247 }
1248 
CatchHandlerIterator(const DexFile::CodeItem & code_item,const DexFile::TryItem & try_item)1249 CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item,
1250                                            const DexFile::TryItem& try_item) {
1251   handler_.address_ = -1;
1252   Init(code_item, try_item.handler_off_);
1253 }
1254 
Init(const DexFile::CodeItem & code_item,int32_t offset)1255 void CatchHandlerIterator::Init(const DexFile::CodeItem& code_item,
1256                                 int32_t offset) {
1257   if (offset >= 0) {
1258     Init(DexFile::GetCatchHandlerData(code_item, offset));
1259   } else {
1260     // Not found, initialize as empty
1261     current_data_ = NULL;
1262     remaining_count_ = -1;
1263     catch_all_ = false;
1264     DCHECK(!HasNext());
1265   }
1266 }
1267 
Init(const byte * handler_data)1268 void CatchHandlerIterator::Init(const byte* handler_data) {
1269   current_data_ = handler_data;
1270   remaining_count_ = DecodeSignedLeb128(&current_data_);
1271 
1272   // If remaining_count_ is non-positive, then it is the negative of
1273   // the number of catch types, and the catches are followed by a
1274   // catch-all handler.
1275   if (remaining_count_ <= 0) {
1276     catch_all_ = true;
1277     remaining_count_ = -remaining_count_;
1278   } else {
1279     catch_all_ = false;
1280   }
1281   Next();
1282 }
1283 
Next()1284 void CatchHandlerIterator::Next() {
1285   if (remaining_count_ > 0) {
1286     handler_.type_idx_ = DecodeUnsignedLeb128(&current_data_);
1287     handler_.address_  = DecodeUnsignedLeb128(&current_data_);
1288     remaining_count_--;
1289     return;
1290   }
1291 
1292   if (catch_all_) {
1293     handler_.type_idx_ = DexFile::kDexNoIndex16;
1294     handler_.address_  = DecodeUnsignedLeb128(&current_data_);
1295     catch_all_ = false;
1296     return;
1297   }
1298 
1299   // no more handler
1300   remaining_count_ = -1;
1301 }
1302 
1303 }  // namespace art
1304