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