| 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> | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 29 | #include <type_traits> | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 30 |  | 
| Andreas Gampe | 46ee31b | 2016-12-14 10:11:49 -0800 | [diff] [blame] | 31 | #include "android-base/stringprintf.h" | 
 | 32 |  | 
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 33 | #include "base/enums.h" | 
| Vladimir Marko | 5096e66 | 2015-12-08 19:25:49 +0000 | [diff] [blame] | 34 | #include "base/file_magic.h" | 
| Elliott Hughes | 07ed66b | 2012-12-12 18:34:25 -0800 | [diff] [blame] | 35 | #include "base/logging.h" | 
| Mathieu Chartier | 32ce2ad | 2016-03-04 14:58:03 -0800 | [diff] [blame] | 36 | #include "base/systrace.h" | 
| Andreas Gampe | 43e10b0 | 2016-07-15 17:17:34 -0700 | [diff] [blame] | 37 | #include "base/unix_file/fd_file.h" | 
| Ian Rogers | 4f6ad8a | 2013-03-18 15:27:28 -0700 | [diff] [blame] | 38 | #include "dex_file-inl.h" | 
| jeffhao | 10037c8 | 2012-01-23 15:06:23 -0800 | [diff] [blame] | 39 | #include "dex_file_verifier.h" | 
| Vladimir Marko | 3a21e38 | 2016-09-02 12:38:38 +0100 | [diff] [blame] | 40 | #include "jvalue.h" | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 41 | #include "leb128.h" | 
| Brian Carlstrom | db4d540 | 2011-08-09 12:18:28 -0700 | [diff] [blame] | 42 | #include "os.h" | 
| Ian Rogers | a672490 | 2013-09-23 09:23:37 -0700 | [diff] [blame] | 43 | #include "utf-inl.h" | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 44 | #include "utils.h" | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 45 | #include "zip_archive.h" | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 46 |  | 
 | 47 | namespace art { | 
 | 48 |  | 
| Andreas Gampe | 46ee31b | 2016-12-14 10:11:49 -0800 | [diff] [blame] | 49 | using android::base::StringPrintf; | 
 | 50 |  | 
| Andreas Gampe | 8a0128a | 2016-11-28 07:38:35 -0800 | [diff] [blame] | 51 | static_assert(sizeof(dex::StringIndex) == sizeof(uint32_t), "StringIndex size is wrong"); | 
 | 52 | static_assert(std::is_trivially_copyable<dex::StringIndex>::value, "StringIndex not trivial"); | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 53 | static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong"); | 
 | 54 | static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial"); | 
 | 55 |  | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 56 | static constexpr OatDexFile* kNoOatDexFile = nullptr; | 
 | 57 |  | 
 | 58 | const char* DexFile::kClassesDex = "classes.dex"; | 
 | 59 |  | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 60 | const uint8_t DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' }; | 
| Alex Light | c496181 | 2016-03-23 10:20:41 -0700 | [diff] [blame] | 61 | const uint8_t DexFile::kDexMagicVersions[DexFile::kNumDexVersions][DexFile::kDexVersionLen] = { | 
 | 62 |   {'0', '3', '5', '\0'}, | 
 | 63 |   // Dex version 036 skipped because of an old dalvik bug on some versions of android where dex | 
 | 64 |   // files with that version number would erroneously be accepted and run. | 
| Narayan Kamath | 52e6650 | 2016-08-01 14:20:31 +0100 | [diff] [blame] | 65 |   {'0', '3', '7', '\0'}, | 
 | 66 |   // Dex version 038: Android "O" and beyond. | 
 | 67 |   {'0', '3', '8', '\0'} | 
| Alex Light | c496181 | 2016-03-23 10:20:41 -0700 | [diff] [blame] | 68 | }; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 69 |  | 
| Vladimir Marko | 3a21e38 | 2016-09-02 12:38:38 +0100 | [diff] [blame] | 70 | struct DexFile::AnnotationValue { | 
 | 71 |   JValue value_; | 
 | 72 |   uint8_t type_; | 
 | 73 | }; | 
 | 74 |  | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 75 | bool DexFile::GetChecksum(const char* filename, uint32_t* checksum, std::string* error_msg) { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 76 |   CHECK(checksum != nullptr); | 
| Brian Carlstrom | 7c3d13a | 2013-09-04 17:15:11 -0700 | [diff] [blame] | 77 |   uint32_t magic; | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 78 |  | 
 | 79 |   // Strip ":...", which is the location | 
 | 80 |   const char* zip_entry_name = kClassesDex; | 
 | 81 |   const char* file_part = filename; | 
| Vladimir Marko | aa4497d | 2014-09-05 14:01:17 +0100 | [diff] [blame] | 82 |   std::string file_part_storage; | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 83 |  | 
| Vladimir Marko | aa4497d | 2014-09-05 14:01:17 +0100 | [diff] [blame] | 84 |   if (DexFile::IsMultiDexLocation(filename)) { | 
 | 85 |     file_part_storage = GetBaseLocation(filename); | 
 | 86 |     file_part = file_part_storage.c_str(); | 
 | 87 |     zip_entry_name = filename + file_part_storage.size() + 1; | 
 | 88 |     DCHECK_EQ(zip_entry_name[-1], kMultiDexSeparator); | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 89 |   } | 
 | 90 |  | 
| Andreas Gampe | 43e10b0 | 2016-07-15 17:17:34 -0700 | [diff] [blame] | 91 |   File fd = OpenAndReadMagic(file_part, &magic, error_msg); | 
 | 92 |   if (fd.Fd() == -1) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 93 |     DCHECK(!error_msg->empty()); | 
| Brian Carlstrom | 7c3d13a | 2013-09-04 17:15:11 -0700 | [diff] [blame] | 94 |     return false; | 
 | 95 |   } | 
 | 96 |   if (IsZipMagic(magic)) { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 97 |     std::unique_ptr<ZipArchive> zip_archive( | 
| Andreas Gampe | 43e10b0 | 2016-07-15 17:17:34 -0700 | [diff] [blame] | 98 |         ZipArchive::OpenFromFd(fd.Release(), filename, error_msg)); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 99 |     if (zip_archive.get() == nullptr) { | 
| Andreas Gampe | 0b3ed3d | 2015-03-04 15:38:51 -0800 | [diff] [blame] | 100 |       *error_msg = StringPrintf("Failed to open zip archive '%s' (error msg: %s)", file_part, | 
 | 101 |                                 error_msg->c_str()); | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 102 |       return false; | 
| Brian Carlstrom | 78128a6 | 2011-09-15 17:21:19 -0700 | [diff] [blame] | 103 |     } | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 104 |     std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(zip_entry_name, error_msg)); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 105 |     if (zip_entry.get() == nullptr) { | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 106 |       *error_msg = StringPrintf("Zip archive '%s' doesn't contain %s (error msg: %s)", file_part, | 
 | 107 |                                 zip_entry_name, error_msg->c_str()); | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 108 |       return false; | 
 | 109 |     } | 
| Brian Carlstrom | 7c3d13a | 2013-09-04 17:15:11 -0700 | [diff] [blame] | 110 |     *checksum = zip_entry->GetCrc32(); | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 111 |     return true; | 
| Brian Carlstrom | 78128a6 | 2011-09-15 17:21:19 -0700 | [diff] [blame] | 112 |   } | 
| Brian Carlstrom | 7c3d13a | 2013-09-04 17:15:11 -0700 | [diff] [blame] | 113 |   if (IsDexMagic(magic)) { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 114 |     std::unique_ptr<const DexFile> dex_file( | 
| Andreas Gampe | 43e10b0 | 2016-07-15 17:17:34 -0700 | [diff] [blame] | 115 |         DexFile::OpenFile(fd.Release(), filename, false, false, error_msg)); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 116 |     if (dex_file.get() == nullptr) { | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 117 |       return false; | 
 | 118 |     } | 
| Brian Carlstrom | 7c3d13a | 2013-09-04 17:15:11 -0700 | [diff] [blame] | 119 |     *checksum = dex_file->GetHeader().checksum_; | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 120 |     return true; | 
 | 121 |   } | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 122 |   *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename); | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 123 |   return false; | 
| Brian Carlstrom | 78128a6 | 2011-09-15 17:21:19 -0700 | [diff] [blame] | 124 | } | 
 | 125 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 126 | int DexFile::GetPermissions() const { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 127 |   if (mem_map_.get() == nullptr) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 128 |     return 0; | 
 | 129 |   } else { | 
 | 130 |     return mem_map_->GetProtect(); | 
 | 131 |   } | 
 | 132 | } | 
 | 133 |  | 
| Sebastien Hertz | 2d6ba51 | 2013-05-17 11:31:37 +0200 | [diff] [blame] | 134 | bool DexFile::IsReadOnly() const { | 
 | 135 |   return GetPermissions() == PROT_READ; | 
 | 136 | } | 
 | 137 |  | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 138 | bool DexFile::EnableWrite() const { | 
| Sebastien Hertz | 2d6ba51 | 2013-05-17 11:31:37 +0200 | [diff] [blame] | 139 |   CHECK(IsReadOnly()); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 140 |   if (mem_map_.get() == nullptr) { | 
| Sebastien Hertz | 2d6ba51 | 2013-05-17 11:31:37 +0200 | [diff] [blame] | 141 |     return false; | 
 | 142 |   } else { | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 143 |     return mem_map_->Protect(PROT_READ | PROT_WRITE); | 
| Sebastien Hertz | 2d6ba51 | 2013-05-17 11:31:37 +0200 | [diff] [blame] | 144 |   } | 
 | 145 | } | 
 | 146 |  | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 147 | bool DexFile::DisableWrite() const { | 
| Sebastien Hertz | 2d6ba51 | 2013-05-17 11:31:37 +0200 | [diff] [blame] | 148 |   CHECK(!IsReadOnly()); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 149 |   if (mem_map_.get() == nullptr) { | 
| Sebastien Hertz | 2d6ba51 | 2013-05-17 11:31:37 +0200 | [diff] [blame] | 150 |     return false; | 
 | 151 |   } else { | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 152 |     return mem_map_->Protect(PROT_READ); | 
| Sebastien Hertz | 2d6ba51 | 2013-05-17 11:31:37 +0200 | [diff] [blame] | 153 |   } | 
 | 154 | } | 
 | 155 |  | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 156 |  | 
 | 157 | std::unique_ptr<const DexFile> DexFile::Open(const uint8_t* base, | 
 | 158 |                                              size_t size, | 
| Andreas Gampe | 3a2bd29 | 2016-01-26 17:23:47 -0800 | [diff] [blame] | 159 |                                              const std::string& location, | 
 | 160 |                                              uint32_t location_checksum, | 
 | 161 |                                              const OatDexFile* oat_dex_file, | 
 | 162 |                                              bool verify, | 
| Aart Bik | 37d6a3b | 2016-06-21 18:30:10 -0700 | [diff] [blame] | 163 |                                              bool verify_checksum, | 
| Andreas Gampe | 3a2bd29 | 2016-01-26 17:23:47 -0800 | [diff] [blame] | 164 |                                              std::string* error_msg) { | 
| Mathieu Chartier | 32ce2ad | 2016-03-04 14:58:03 -0800 | [diff] [blame] | 165 |   ScopedTrace trace(std::string("Open dex file from RAM ") + location); | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 166 |   return OpenCommon(base, | 
 | 167 |                     size, | 
 | 168 |                     location, | 
 | 169 |                     location_checksum, | 
 | 170 |                     oat_dex_file, | 
 | 171 |                     verify, | 
 | 172 |                     verify_checksum, | 
 | 173 |                     error_msg); | 
| Orion Hodson | a4c2a05 | 2016-08-17 10:51:42 +0100 | [diff] [blame] | 174 | } | 
| Andreas Gampe | 3a2bd29 | 2016-01-26 17:23:47 -0800 | [diff] [blame] | 175 |  | 
| Orion Hodson | a4c2a05 | 2016-08-17 10:51:42 +0100 | [diff] [blame] | 176 | std::unique_ptr<const DexFile> DexFile::Open(const std::string& location, | 
 | 177 |                                              uint32_t location_checksum, | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 178 |                                              std::unique_ptr<MemMap> map, | 
| Orion Hodson | a4c2a05 | 2016-08-17 10:51:42 +0100 | [diff] [blame] | 179 |                                              bool verify, | 
 | 180 |                                              bool verify_checksum, | 
 | 181 |                                              std::string* error_msg) { | 
 | 182 |   ScopedTrace trace(std::string("Open dex file from mapped-memory ") + location); | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 183 |   CHECK(map.get() != nullptr); | 
 | 184 |   std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(), | 
 | 185 |                                                  map->Size(), | 
 | 186 |                                                  location, | 
 | 187 |                                                  location_checksum, | 
 | 188 |                                                  kNoOatDexFile, | 
 | 189 |                                                  verify, | 
 | 190 |                                                  verify_checksum, | 
 | 191 |                                                  error_msg); | 
 | 192 |   if (dex_file != nullptr) { | 
 | 193 |     dex_file->mem_map_.reset(map.release()); | 
| Orion Hodson | a4c2a05 | 2016-08-17 10:51:42 +0100 | [diff] [blame] | 194 |   } | 
| Andreas Gampe | 3a2bd29 | 2016-01-26 17:23:47 -0800 | [diff] [blame] | 195 |   return dex_file; | 
 | 196 | } | 
 | 197 |  | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 198 | bool DexFile::Open(const char* filename, | 
 | 199 |                    const std::string& location, | 
 | 200 |                    bool verify_checksum, | 
 | 201 |                    std::string* error_msg, | 
 | 202 |                    std::vector<std::unique_ptr<const DexFile>>* dex_files) { | 
 | 203 |   ScopedTrace trace(std::string("Open dex file ") + std::string(location)); | 
 | 204 |   DCHECK(dex_files != nullptr) << "DexFile::Open: out-param is nullptr"; | 
 | 205 |   uint32_t magic; | 
 | 206 |   File fd = OpenAndReadMagic(filename, &magic, error_msg); | 
 | 207 |   if (fd.Fd() == -1) { | 
 | 208 |     DCHECK(!error_msg->empty()); | 
 | 209 |     return false; | 
 | 210 |   } | 
 | 211 |   if (IsZipMagic(magic)) { | 
 | 212 |     return DexFile::OpenZip(fd.Release(), location, verify_checksum, error_msg, dex_files); | 
 | 213 |   } | 
 | 214 |   if (IsDexMagic(magic)) { | 
 | 215 |     std::unique_ptr<const DexFile> dex_file(DexFile::OpenFile(fd.Release(), | 
 | 216 |                                                               location, | 
 | 217 |                                                               /* verify */ true, | 
 | 218 |                                                               verify_checksum, | 
 | 219 |                                                               error_msg)); | 
 | 220 |     if (dex_file.get() != nullptr) { | 
 | 221 |       dex_files->push_back(std::move(dex_file)); | 
 | 222 |       return true; | 
 | 223 |     } else { | 
 | 224 |       return false; | 
| Vladimir Marko | fd99576 | 2013-11-06 16:36:36 +0000 | [diff] [blame] | 225 |     } | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 226 |   } | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 227 |   *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename); | 
 | 228 |   return false; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 229 | } | 
 | 230 |  | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 231 | std::unique_ptr<const DexFile> DexFile::OpenDex(int fd, | 
 | 232 |                                                 const std::string& location, | 
 | 233 |                                                 bool verify_checksum, | 
 | 234 |                                                 std::string* error_msg) { | 
 | 235 |   ScopedTrace trace("Open dex file " + std::string(location)); | 
 | 236 |   return OpenFile(fd, location, true /* verify */, verify_checksum, error_msg); | 
 | 237 | } | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 238 |  | 
| Aart Bik | 37d6a3b | 2016-06-21 18:30:10 -0700 | [diff] [blame] | 239 | bool DexFile::OpenZip(int fd, | 
 | 240 |                       const std::string& location, | 
 | 241 |                       bool verify_checksum, | 
 | 242 |                       std::string* error_msg, | 
| Richard Uhler | fbef44d | 2014-12-23 09:48:51 -0800 | [diff] [blame] | 243 |                       std::vector<std::unique_ptr<const DexFile>>* dex_files) { | 
| Mathieu Chartier | 32ce2ad | 2016-03-04 14:58:03 -0800 | [diff] [blame] | 244 |   ScopedTrace trace("Dex file open Zip " + std::string(location)); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 245 |   DCHECK(dex_files != nullptr) << "DexFile::OpenZip: out-param is nullptr"; | 
| Ian Rogers | 700a402 | 2014-05-19 16:49:03 -0700 | [diff] [blame] | 246 |   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] | 247 |   if (zip_archive.get() == nullptr) { | 
 | 248 |     DCHECK(!error_msg->empty()); | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 249 |     return false; | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 250 |   } | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 251 |   return DexFile::OpenAllDexFilesFromZip(*zip_archive, | 
 | 252 |                                          location, | 
 | 253 |                                          verify_checksum, | 
 | 254 |                                          error_msg, | 
 | 255 |                                          dex_files); | 
| Brian Carlstrom | a6cc893 | 2012-01-04 14:44:07 -0800 | [diff] [blame] | 256 | } | 
 | 257 |  | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 258 | std::unique_ptr<const DexFile> DexFile::OpenFile(int fd, | 
 | 259 |                                                  const std::string& location, | 
 | 260 |                                                  bool verify, | 
 | 261 |                                                  bool verify_checksum, | 
 | 262 |                                                  std::string* error_msg) { | 
 | 263 |   ScopedTrace trace(std::string("Open dex file ") + std::string(location)); | 
 | 264 |   CHECK(!location.empty()); | 
 | 265 |   std::unique_ptr<MemMap> map; | 
 | 266 |   { | 
 | 267 |     File delayed_close(fd, /* check_usage */ false); | 
 | 268 |     struct stat sbuf; | 
 | 269 |     memset(&sbuf, 0, sizeof(sbuf)); | 
 | 270 |     if (fstat(fd, &sbuf) == -1) { | 
 | 271 |       *error_msg = StringPrintf("DexFile: fstat '%s' failed: %s", location.c_str(), | 
 | 272 |                                 strerror(errno)); | 
 | 273 |       return nullptr; | 
 | 274 |     } | 
 | 275 |     if (S_ISDIR(sbuf.st_mode)) { | 
 | 276 |       *error_msg = StringPrintf("Attempt to mmap directory '%s'", location.c_str()); | 
 | 277 |       return nullptr; | 
 | 278 |     } | 
 | 279 |     size_t length = sbuf.st_size; | 
 | 280 |     map.reset(MemMap::MapFile(length, | 
 | 281 |                               PROT_READ, | 
 | 282 |                               MAP_PRIVATE, | 
 | 283 |                               fd, | 
 | 284 |                               0, | 
 | 285 |                               /*low_4gb*/false, | 
 | 286 |                               location.c_str(), | 
 | 287 |                               error_msg)); | 
 | 288 |     if (map == nullptr) { | 
 | 289 |       DCHECK(!error_msg->empty()); | 
 | 290 |       return nullptr; | 
 | 291 |     } | 
 | 292 |   } | 
 | 293 |  | 
 | 294 |   if (map->Size() < sizeof(DexFile::Header)) { | 
 | 295 |     *error_msg = StringPrintf( | 
 | 296 |         "DexFile: failed to open dex file '%s' that is too short to have a header", | 
 | 297 |         location.c_str()); | 
 | 298 |     return nullptr; | 
 | 299 |   } | 
 | 300 |  | 
 | 301 |   const Header* dex_header = reinterpret_cast<const Header*>(map->Begin()); | 
 | 302 |  | 
 | 303 |   std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(), | 
 | 304 |                                                  map->Size(), | 
 | 305 |                                                  location, | 
 | 306 |                                                  dex_header->checksum_, | 
 | 307 |                                                  kNoOatDexFile, | 
 | 308 |                                                  verify, | 
 | 309 |                                                  verify_checksum, | 
 | 310 |                                                  error_msg); | 
 | 311 |   if (dex_file != nullptr) { | 
 | 312 |     dex_file->mem_map_.reset(map.release()); | 
 | 313 |   } | 
 | 314 |  | 
 | 315 |   return dex_file; | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 316 | } | 
 | 317 |  | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 318 | std::unique_ptr<const DexFile> DexFile::OpenOneDexFileFromZip(const ZipArchive& zip_archive, | 
 | 319 |                                                               const char* entry_name, | 
 | 320 |                                                               const std::string& location, | 
 | 321 |                                                               bool verify_checksum, | 
 | 322 |                                                               std::string* error_msg, | 
 | 323 |                                                               ZipOpenErrorCode* error_code) { | 
| Mathieu Chartier | 32ce2ad | 2016-03-04 14:58:03 -0800 | [diff] [blame] | 324 |   ScopedTrace trace("Dex file open from Zip Archive " + std::string(location)); | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 325 |   CHECK(!location.empty()); | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 326 |   std::unique_ptr<ZipEntry> zip_entry(zip_archive.Find(entry_name, error_msg)); | 
| David Sehr | 9fddd36 | 2016-09-22 14:05:37 -0700 | [diff] [blame] | 327 |   if (zip_entry == nullptr) { | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 328 |     *error_code = ZipOpenErrorCode::kEntryNotFound; | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 329 |     return nullptr; | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 330 |   } | 
| ganxiaolin | cd16d0a | 2016-07-18 11:21:44 +0800 | [diff] [blame] | 331 |   if (zip_entry->GetUncompressedLength() == 0) { | 
 | 332 |     *error_msg = StringPrintf("Dex file '%s' has zero length", location.c_str()); | 
 | 333 |     *error_code = ZipOpenErrorCode::kDexFileError; | 
 | 334 |     return nullptr; | 
 | 335 |   } | 
| Nicolas Geoffray | 960b2af | 2017-02-12 15:48:07 +0000 | [diff] [blame] | 336 |   std::unique_ptr<MemMap> map(zip_entry->ExtractToMemMap(location.c_str(), entry_name, error_msg)); | 
| David Sehr | 9fddd36 | 2016-09-22 14:05:37 -0700 | [diff] [blame] | 337 |   if (map == nullptr) { | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 338 |     *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] | 339 |                               error_msg->c_str()); | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 340 |     *error_code = ZipOpenErrorCode::kExtractToMemoryError; | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 341 |     return nullptr; | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 342 |   } | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 343 |   VerifyResult verify_result; | 
 | 344 |   std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(), | 
 | 345 |                                                  map->Size(), | 
 | 346 |                                                  location, | 
 | 347 |                                                  zip_entry->GetCrc32(), | 
 | 348 |                                                  kNoOatDexFile, | 
 | 349 |                                                  /* verify */ true, | 
 | 350 |                                                  verify_checksum, | 
 | 351 |                                                  error_msg, | 
 | 352 |                                                  &verify_result); | 
| David Sehr | 9fddd36 | 2016-09-22 14:05:37 -0700 | [diff] [blame] | 353 |   if (dex_file == nullptr) { | 
 | 354 |     if (verify_result == VerifyResult::kVerifyNotAttempted) { | 
 | 355 |       *error_code = ZipOpenErrorCode::kDexFileError; | 
 | 356 |     } else { | 
 | 357 |       *error_code = ZipOpenErrorCode::kVerifyError; | 
 | 358 |     } | 
 | 359 |     return nullptr; | 
| jeffhao | f6174e8 | 2012-01-31 16:14:17 -0800 | [diff] [blame] | 360 |   } | 
| David Sehr | 9fddd36 | 2016-09-22 14:05:37 -0700 | [diff] [blame] | 361 |   dex_file->mem_map_.reset(map.release()); | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 362 |   if (!dex_file->DisableWrite()) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 363 |     *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] | 364 |     *error_code = ZipOpenErrorCode::kMakeReadOnlyError; | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 365 |     return nullptr; | 
| Brian Carlstrom | e0948e1 | 2013-08-29 09:36:15 -0700 | [diff] [blame] | 366 |   } | 
 | 367 |   CHECK(dex_file->IsReadOnly()) << location; | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 368 |   if (verify_result != VerifyResult::kVerifySucceeded) { | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 369 |     *error_code = ZipOpenErrorCode::kVerifyError; | 
| Brian Carlstrom | d6cec90 | 2014-05-25 16:08:51 -0700 | [diff] [blame] | 370 |     return nullptr; | 
 | 371 |   } | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 372 |   *error_code = ZipOpenErrorCode::kNoError; | 
| Richard Uhler | fbef44d | 2014-12-23 09:48:51 -0800 | [diff] [blame] | 373 |   return dex_file; | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 374 | } | 
 | 375 |  | 
| Andreas Gampe | 90e3404 | 2015-04-27 20:01:52 -0700 | [diff] [blame] | 376 | // Technically we do not have a limitation with respect to the number of dex files that can be in a | 
 | 377 | // multidex APK. However, it's bad practice, as each dex file requires its own tables for symbols | 
 | 378 | // (types, classes, methods, ...) and dex caches. So warn the user that we open a zip with what | 
 | 379 | // seems an excessive number. | 
 | 380 | static constexpr size_t kWarnOnManyDexFilesThreshold = 100; | 
 | 381 |  | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 382 | bool DexFile::OpenAllDexFilesFromZip(const ZipArchive& zip_archive, | 
 | 383 |                                      const std::string& location, | 
 | 384 |                                      bool verify_checksum, | 
 | 385 |                                      std::string* error_msg, | 
 | 386 |                                      std::vector<std::unique_ptr<const DexFile>>* dex_files) { | 
| Mathieu Chartier | 32ce2ad | 2016-03-04 14:58:03 -0800 | [diff] [blame] | 387 |   ScopedTrace trace("Dex file open from Zip " + std::string(location)); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 388 |   DCHECK(dex_files != nullptr) << "DexFile::OpenFromZip: out-param is nullptr"; | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 389 |   ZipOpenErrorCode error_code; | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 390 |   std::unique_ptr<const DexFile> dex_file(OpenOneDexFileFromZip(zip_archive, | 
 | 391 |                                                                 kClassesDex, | 
 | 392 |                                                                 location, | 
 | 393 |                                                                 verify_checksum, | 
 | 394 |                                                                 error_msg, | 
 | 395 |                                                                 &error_code)); | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 396 |   if (dex_file.get() == nullptr) { | 
 | 397 |     return false; | 
 | 398 |   } else { | 
 | 399 |     // Had at least classes.dex. | 
| Richard Uhler | fbef44d | 2014-12-23 09:48:51 -0800 | [diff] [blame] | 400 |     dex_files->push_back(std::move(dex_file)); | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 401 |  | 
 | 402 |     // Now try some more. | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 403 |  | 
 | 404 |     // We could try to avoid std::string allocations by working on a char array directly. As we | 
 | 405 |     // do not expect a lot of iterations, this seems too involved and brittle. | 
 | 406 |  | 
| Andreas Gampe | 90e3404 | 2015-04-27 20:01:52 -0700 | [diff] [blame] | 407 |     for (size_t i = 1; ; ++i) { | 
 | 408 |       std::string name = GetMultiDexClassesDexName(i); | 
 | 409 |       std::string fake_location = GetMultiDexLocation(i, location.c_str()); | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 410 |       std::unique_ptr<const DexFile> next_dex_file(OpenOneDexFileFromZip(zip_archive, | 
 | 411 |                                                                          name.c_str(), | 
 | 412 |                                                                          fake_location, | 
 | 413 |                                                                          verify_checksum, | 
 | 414 |                                                                          error_msg, | 
 | 415 |                                                                          &error_code)); | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 416 |       if (next_dex_file.get() == nullptr) { | 
 | 417 |         if (error_code != ZipOpenErrorCode::kEntryNotFound) { | 
 | 418 |           LOG(WARNING) << error_msg; | 
 | 419 |         } | 
 | 420 |         break; | 
 | 421 |       } else { | 
| Richard Uhler | fbef44d | 2014-12-23 09:48:51 -0800 | [diff] [blame] | 422 |         dex_files->push_back(std::move(next_dex_file)); | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 423 |       } | 
 | 424 |  | 
| Andreas Gampe | 90e3404 | 2015-04-27 20:01:52 -0700 | [diff] [blame] | 425 |       if (i == kWarnOnManyDexFilesThreshold) { | 
 | 426 |         LOG(WARNING) << location << " has in excess of " << kWarnOnManyDexFilesThreshold | 
 | 427 |                      << " dex files. Please consider coalescing and shrinking the number to " | 
 | 428 |                         " avoid runtime overhead."; | 
 | 429 |       } | 
 | 430 |  | 
 | 431 |       if (i == std::numeric_limits<size_t>::max()) { | 
 | 432 |         LOG(ERROR) << "Overflow in number of dex files!"; | 
 | 433 |         break; | 
 | 434 |       } | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 435 |     } | 
 | 436 |  | 
 | 437 |     return true; | 
 | 438 |   } | 
 | 439 | } | 
 | 440 |  | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 441 | std::unique_ptr<DexFile> DexFile::OpenCommon(const uint8_t* base, | 
 | 442 |                                              size_t size, | 
 | 443 |                                              const std::string& location, | 
 | 444 |                                              uint32_t location_checksum, | 
 | 445 |                                              const OatDexFile* oat_dex_file, | 
 | 446 |                                              bool verify, | 
 | 447 |                                              bool verify_checksum, | 
 | 448 |                                              std::string* error_msg, | 
 | 449 |                                              VerifyResult* verify_result) { | 
| David Sehr | 9fddd36 | 2016-09-22 14:05:37 -0700 | [diff] [blame] | 450 |   if (verify_result != nullptr) { | 
 | 451 |     *verify_result = VerifyResult::kVerifyNotAttempted; | 
 | 452 |   } | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 453 |   std::unique_ptr<DexFile> dex_file(new DexFile(base, | 
 | 454 |                                                 size, | 
 | 455 |                                                 location, | 
 | 456 |                                                 location_checksum, | 
 | 457 |                                                 oat_dex_file)); | 
 | 458 |   if (dex_file == nullptr) { | 
 | 459 |     *error_msg = StringPrintf("Failed to open dex file '%s' from memory: %s", location.c_str(), | 
 | 460 |                               error_msg->c_str()); | 
 | 461 |     return nullptr; | 
 | 462 |   } | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 463 |   if (!dex_file->Init(error_msg)) { | 
| Richard Uhler | fbef44d | 2014-12-23 09:48:51 -0800 | [diff] [blame] | 464 |     dex_file.reset(); | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 465 |     return nullptr; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 466 |   } | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 467 |   if (verify && !DexFileVerifier::Verify(dex_file.get(), | 
 | 468 |                                          dex_file->Begin(), | 
 | 469 |                                          dex_file->Size(), | 
 | 470 |                                          location.c_str(), | 
 | 471 |                                          verify_checksum, | 
 | 472 |                                          error_msg)) { | 
 | 473 |     if (verify_result != nullptr) { | 
 | 474 |       *verify_result = VerifyResult::kVerifyFailed; | 
 | 475 |     } | 
 | 476 |     return nullptr; | 
 | 477 |   } | 
 | 478 |   if (verify_result != nullptr) { | 
 | 479 |     *verify_result = VerifyResult::kVerifySucceeded; | 
 | 480 |   } | 
 | 481 |   return dex_file; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 482 | } | 
 | 483 |  | 
| David Sehr | 733ddb2 | 2016-09-19 15:02:18 -0700 | [diff] [blame] | 484 | DexFile::DexFile(const uint8_t* base, | 
 | 485 |                  size_t size, | 
| Brian Carlstrom | 0d6adac | 2014-02-05 17:39:16 -0800 | [diff] [blame] | 486 |                  const std::string& location, | 
 | 487 |                  uint32_t location_checksum, | 
| Richard Uhler | 07b3c23 | 2015-03-31 15:57:54 -0700 | [diff] [blame] | 488 |                  const OatDexFile* oat_dex_file) | 
| Brian Carlstrom | 0d6adac | 2014-02-05 17:39:16 -0800 | [diff] [blame] | 489 |     : begin_(base), | 
 | 490 |       size_(size), | 
 | 491 |       location_(location), | 
 | 492 |       location_checksum_(location_checksum), | 
| Brian Carlstrom | 0d6adac | 2014-02-05 17:39:16 -0800 | [diff] [blame] | 493 |       header_(reinterpret_cast<const Header*>(base)), | 
 | 494 |       string_ids_(reinterpret_cast<const StringId*>(base + header_->string_ids_off_)), | 
 | 495 |       type_ids_(reinterpret_cast<const TypeId*>(base + header_->type_ids_off_)), | 
 | 496 |       field_ids_(reinterpret_cast<const FieldId*>(base + header_->field_ids_off_)), | 
 | 497 |       method_ids_(reinterpret_cast<const MethodId*>(base + header_->method_ids_off_)), | 
 | 498 |       proto_ids_(reinterpret_cast<const ProtoId*>(base + header_->proto_ids_off_)), | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 499 |       class_defs_(reinterpret_cast<const ClassDef*>(base + header_->class_defs_off_)), | 
| Orion Hodson | 12f4ff4 | 2017-01-13 16:43:12 +0000 | [diff] [blame^] | 500 |       method_handles_(nullptr), | 
 | 501 |       num_method_handles_(0), | 
 | 502 |       call_site_ids_(nullptr), | 
 | 503 |       num_call_site_ids_(0), | 
| Richard Uhler | 07b3c23 | 2015-03-31 15:57:54 -0700 | [diff] [blame] | 504 |       oat_dex_file_(oat_dex_file) { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 505 |   CHECK(begin_ != nullptr) << GetLocation(); | 
| Brian Carlstrom | 0d6adac | 2014-02-05 17:39:16 -0800 | [diff] [blame] | 506 |   CHECK_GT(size_, 0U) << GetLocation(); | 
| Orion Hodson | 12f4ff4 | 2017-01-13 16:43:12 +0000 | [diff] [blame^] | 507 |   InitializeSectionsFromMapList(); | 
| Brian Carlstrom | 0d6adac | 2014-02-05 17:39:16 -0800 | [diff] [blame] | 508 | } | 
 | 509 |  | 
| Jesse Wilson | 6bf1915 | 2011-09-29 13:12:33 -0400 | [diff] [blame] | 510 | DexFile::~DexFile() { | 
| Elliott Hughes | 8cef0b8 | 2011-10-11 19:24:00 -0700 | [diff] [blame] | 511 |   // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and | 
 | 512 |   // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could | 
 | 513 |   // re-attach, but cleaning up these global references is not obviously useful. It's not as if | 
 | 514 |   // the global reference table is otherwise empty! | 
| Jesse Wilson | 6bf1915 | 2011-09-29 13:12:33 -0400 | [diff] [blame] | 515 | } | 
 | 516 |  | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 517 | bool DexFile::Init(std::string* error_msg) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 518 |   if (!CheckMagicAndVersion(error_msg)) { | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 519 |     return false; | 
 | 520 |   } | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 521 |   return true; | 
 | 522 | } | 
 | 523 |  | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 524 | bool DexFile::CheckMagicAndVersion(std::string* error_msg) const { | 
| Brian Carlstrom | 6e3b1d9 | 2012-01-11 01:36:32 -0800 | [diff] [blame] | 525 |   if (!IsMagicValid(header_->magic_)) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 526 |     std::ostringstream oss; | 
 | 527 |     oss << "Unrecognized magic number in "  << GetLocation() << ":" | 
| Brian Carlstrom | 6e3b1d9 | 2012-01-11 01:36:32 -0800 | [diff] [blame] | 528 |             << " " << header_->magic_[0] | 
 | 529 |             << " " << header_->magic_[1] | 
 | 530 |             << " " << header_->magic_[2] | 
 | 531 |             << " " << header_->magic_[3]; | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 532 |     *error_msg = oss.str(); | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 533 |     return false; | 
 | 534 |   } | 
| Brian Carlstrom | 6e3b1d9 | 2012-01-11 01:36:32 -0800 | [diff] [blame] | 535 |   if (!IsVersionValid(header_->magic_)) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 536 |     std::ostringstream oss; | 
 | 537 |     oss << "Unrecognized version number in "  << GetLocation() << ":" | 
| Brian Carlstrom | 6e3b1d9 | 2012-01-11 01:36:32 -0800 | [diff] [blame] | 538 |             << " " << header_->magic_[4] | 
 | 539 |             << " " << header_->magic_[5] | 
 | 540 |             << " " << header_->magic_[6] | 
 | 541 |             << " " << header_->magic_[7]; | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 542 |     *error_msg = oss.str(); | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 543 |     return false; | 
 | 544 |   } | 
 | 545 |   return true; | 
 | 546 | } | 
 | 547 |  | 
| Orion Hodson | 12f4ff4 | 2017-01-13 16:43:12 +0000 | [diff] [blame^] | 548 | void DexFile::InitializeSectionsFromMapList() { | 
 | 549 |   const MapList* map_list = reinterpret_cast<const MapList*>(begin_ + header_->map_off_); | 
 | 550 |   const size_t count = map_list->size_; | 
 | 551 |  | 
 | 552 |   size_t map_limit = header_->map_off_ + count * sizeof(MapItem); | 
 | 553 |   if (header_->map_off_ >= map_limit || map_limit > size_) { | 
 | 554 |     // Overflow or out out of bounds. The dex file verifier runs after | 
 | 555 |     // this method and will reject the file as it is malformed. | 
 | 556 |     return; | 
 | 557 |   } | 
 | 558 |  | 
 | 559 |   for (size_t i = 0; i < count; ++i) { | 
 | 560 |     const MapItem& map_item = map_list->list_[i]; | 
 | 561 |     if (map_item.type_ == kDexTypeMethodHandleItem) { | 
 | 562 |       method_handles_ = reinterpret_cast<const MethodHandleItem*>(begin_ + map_item.offset_); | 
 | 563 |       num_method_handles_ = map_item.size_; | 
 | 564 |     } else if (map_item.type_ == kDexTypeCallSiteIdItem) { | 
 | 565 |       call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(begin_ + map_item.offset_); | 
 | 566 |       num_call_site_ids_ = map_item.size_; | 
 | 567 |     } | 
 | 568 |   } | 
 | 569 | } | 
 | 570 |  | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 571 | bool DexFile::IsMagicValid(const uint8_t* magic) { | 
| Brian Carlstrom | 6e3b1d9 | 2012-01-11 01:36:32 -0800 | [diff] [blame] | 572 |   return (memcmp(magic, kDexMagic, sizeof(kDexMagic)) == 0); | 
 | 573 | } | 
 | 574 |  | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 575 | bool DexFile::IsVersionValid(const uint8_t* magic) { | 
 | 576 |   const uint8_t* version = &magic[sizeof(kDexMagic)]; | 
| Alex Light | c496181 | 2016-03-23 10:20:41 -0700 | [diff] [blame] | 577 |   for (uint32_t i = 0; i < kNumDexVersions; i++) { | 
 | 578 |     if (memcmp(version, kDexMagicVersions[i], kDexVersionLen) == 0) { | 
 | 579 |       return true; | 
 | 580 |     } | 
 | 581 |   } | 
 | 582 |   return false; | 
| Brian Carlstrom | 6e3b1d9 | 2012-01-11 01:36:32 -0800 | [diff] [blame] | 583 | } | 
 | 584 |  | 
| Andreas Gampe | 76ed99d | 2016-03-28 18:31:29 -0700 | [diff] [blame] | 585 | uint32_t DexFile::Header::GetVersion() const { | 
 | 586 |   const char* version = reinterpret_cast<const char*>(&magic_[sizeof(kDexMagic)]); | 
| Ian Rogers | d81871c | 2011-10-03 13:57:23 -0700 | [diff] [blame] | 587 |   return atoi(version); | 
 | 588 | } | 
 | 589 |  | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 590 | const DexFile::ClassDef* DexFile::FindClassDef(dex::TypeIndex type_idx) const { | 
| David Sehr | 9aa352e | 2016-09-15 18:13:52 -0700 | [diff] [blame] | 591 |   size_t num_class_defs = NumClassDefs(); | 
| Roland Levillain | ab880f4 | 2016-05-12 16:24:36 +0100 | [diff] [blame] | 592 |   // Fast path for rare no class defs case. | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 593 |   if (num_class_defs == 0) { | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 594 |     return nullptr; | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 595 |   } | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 596 |   for (size_t i = 0; i < num_class_defs; ++i) { | 
 | 597 |     const ClassDef& class_def = GetClassDef(i); | 
 | 598 |     if (class_def.class_idx_ == type_idx) { | 
 | 599 |       return &class_def; | 
 | 600 |     } | 
| Brian Carlstrom | e24fa61 | 2011-09-29 00:53:55 -0700 | [diff] [blame] | 601 |   } | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 602 |   return nullptr; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 603 | } | 
 | 604 |  | 
| Alex Light | 9c20a14 | 2016-08-23 15:05:12 -0700 | [diff] [blame] | 605 | uint32_t DexFile::FindCodeItemOffset(const DexFile::ClassDef& class_def, | 
 | 606 |                                      uint32_t method_idx) const { | 
 | 607 |   const uint8_t* class_data = GetClassData(class_def); | 
 | 608 |   CHECK(class_data != nullptr); | 
 | 609 |   ClassDataItemIterator it(*this, class_data); | 
 | 610 |   // Skip fields | 
 | 611 |   while (it.HasNextStaticField()) { | 
 | 612 |     it.Next(); | 
 | 613 |   } | 
 | 614 |   while (it.HasNextInstanceField()) { | 
 | 615 |     it.Next(); | 
 | 616 |   } | 
 | 617 |   while (it.HasNextDirectMethod()) { | 
 | 618 |     if (it.GetMemberIndex() == method_idx) { | 
 | 619 |       return it.GetMethodCodeItemOffset(); | 
 | 620 |     } | 
 | 621 |     it.Next(); | 
 | 622 |   } | 
 | 623 |   while (it.HasNextVirtualMethod()) { | 
 | 624 |     if (it.GetMemberIndex() == method_idx) { | 
 | 625 |       return it.GetMethodCodeItemOffset(); | 
 | 626 |     } | 
 | 627 |     it.Next(); | 
 | 628 |   } | 
 | 629 |   LOG(FATAL) << "Unable to find method " << method_idx; | 
 | 630 |   UNREACHABLE(); | 
 | 631 | } | 
 | 632 |  | 
| Ian Rogers | 9b1a4f4 | 2011-11-14 18:35:10 -0800 | [diff] [blame] | 633 | const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass, | 
| Roland Levillain | ab880f4 | 2016-05-12 16:24:36 +0100 | [diff] [blame] | 634 |                                              const DexFile::StringId& name, | 
 | 635 |                                              const DexFile::TypeId& type) const { | 
| Ian Rogers | 9b1a4f4 | 2011-11-14 18:35:10 -0800 | [diff] [blame] | 636 |   // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 637 |   const dex::TypeIndex class_idx = GetIndexForTypeId(declaring_klass); | 
| Andreas Gampe | 8a0128a | 2016-11-28 07:38:35 -0800 | [diff] [blame] | 638 |   const dex::StringIndex name_idx = GetIndexForStringId(name); | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 639 |   const dex::TypeIndex type_idx = GetIndexForTypeId(type); | 
| Ian Rogers | f8582c3 | 2013-05-29 16:33:03 -0700 | [diff] [blame] | 640 |   int32_t lo = 0; | 
 | 641 |   int32_t hi = NumFieldIds() - 1; | 
| Ian Rogers | 9b1a4f4 | 2011-11-14 18:35:10 -0800 | [diff] [blame] | 642 |   while (hi >= lo) { | 
| Ian Rogers | f8582c3 | 2013-05-29 16:33:03 -0700 | [diff] [blame] | 643 |     int32_t mid = (hi + lo) / 2; | 
| Ian Rogers | 9b1a4f4 | 2011-11-14 18:35:10 -0800 | [diff] [blame] | 644 |     const DexFile::FieldId& field = GetFieldId(mid); | 
 | 645 |     if (class_idx > field.class_idx_) { | 
 | 646 |       lo = mid + 1; | 
 | 647 |     } else if (class_idx < field.class_idx_) { | 
 | 648 |       hi = mid - 1; | 
 | 649 |     } else { | 
 | 650 |       if (name_idx > field.name_idx_) { | 
 | 651 |         lo = mid + 1; | 
 | 652 |       } else if (name_idx < field.name_idx_) { | 
 | 653 |         hi = mid - 1; | 
 | 654 |       } else { | 
 | 655 |         if (type_idx > field.type_idx_) { | 
 | 656 |           lo = mid + 1; | 
 | 657 |         } else if (type_idx < field.type_idx_) { | 
 | 658 |           hi = mid - 1; | 
 | 659 |         } else { | 
 | 660 |           return &field; | 
 | 661 |         } | 
 | 662 |       } | 
 | 663 |     } | 
 | 664 |   } | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 665 |   return nullptr; | 
| Ian Rogers | 9b1a4f4 | 2011-11-14 18:35:10 -0800 | [diff] [blame] | 666 | } | 
 | 667 |  | 
 | 668 | const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass, | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 669 |                                                const DexFile::StringId& name, | 
 | 670 |                                                const DexFile::ProtoId& signature) const { | 
 | 671 |   // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 672 |   const dex::TypeIndex class_idx = GetIndexForTypeId(declaring_klass); | 
| Andreas Gampe | 8a0128a | 2016-11-28 07:38:35 -0800 | [diff] [blame] | 673 |   const dex::StringIndex name_idx = GetIndexForStringId(name); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 674 |   const uint16_t proto_idx = GetIndexForProtoId(signature); | 
| Ian Rogers | f8582c3 | 2013-05-29 16:33:03 -0700 | [diff] [blame] | 675 |   int32_t lo = 0; | 
 | 676 |   int32_t hi = NumMethodIds() - 1; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 677 |   while (hi >= lo) { | 
| Ian Rogers | f8582c3 | 2013-05-29 16:33:03 -0700 | [diff] [blame] | 678 |     int32_t mid = (hi + lo) / 2; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 679 |     const DexFile::MethodId& method = GetMethodId(mid); | 
 | 680 |     if (class_idx > method.class_idx_) { | 
 | 681 |       lo = mid + 1; | 
 | 682 |     } else if (class_idx < method.class_idx_) { | 
 | 683 |       hi = mid - 1; | 
 | 684 |     } else { | 
 | 685 |       if (name_idx > method.name_idx_) { | 
 | 686 |         lo = mid + 1; | 
 | 687 |       } else if (name_idx < method.name_idx_) { | 
 | 688 |         hi = mid - 1; | 
 | 689 |       } else { | 
 | 690 |         if (proto_idx > method.proto_idx_) { | 
 | 691 |           lo = mid + 1; | 
 | 692 |         } else if (proto_idx < method.proto_idx_) { | 
 | 693 |           hi = mid - 1; | 
 | 694 |         } else { | 
 | 695 |           return &method; | 
 | 696 |         } | 
 | 697 |       } | 
 | 698 |     } | 
 | 699 |   } | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 700 |   return nullptr; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 701 | } | 
 | 702 |  | 
| Ian Rogers | 637c65b | 2013-05-31 11:46:00 -0700 | [diff] [blame] | 703 | const DexFile::StringId* DexFile::FindStringId(const char* string) const { | 
| Ian Rogers | f8582c3 | 2013-05-29 16:33:03 -0700 | [diff] [blame] | 704 |   int32_t lo = 0; | 
 | 705 |   int32_t hi = NumStringIds() - 1; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 706 |   while (hi >= lo) { | 
| Ian Rogers | f8582c3 | 2013-05-29 16:33:03 -0700 | [diff] [blame] | 707 |     int32_t mid = (hi + lo) / 2; | 
| Andreas Gampe | 8a0128a | 2016-11-28 07:38:35 -0800 | [diff] [blame] | 708 |     const DexFile::StringId& str_id = GetStringId(dex::StringIndex(mid)); | 
| Ian Rogers | cf5077a | 2013-10-31 12:37:54 -0700 | [diff] [blame] | 709 |     const char* str = GetStringData(str_id); | 
| Ian Rogers | 637c65b | 2013-05-31 11:46:00 -0700 | [diff] [blame] | 710 |     int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string, str); | 
 | 711 |     if (compare > 0) { | 
 | 712 |       lo = mid + 1; | 
 | 713 |     } else if (compare < 0) { | 
 | 714 |       hi = mid - 1; | 
 | 715 |     } else { | 
 | 716 |       return &str_id; | 
 | 717 |     } | 
 | 718 |   } | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 719 |   return nullptr; | 
| Ian Rogers | 637c65b | 2013-05-31 11:46:00 -0700 | [diff] [blame] | 720 | } | 
 | 721 |  | 
| Artem Udovichenko | d9786b0 | 2015-10-14 16:36:55 +0300 | [diff] [blame] | 722 | const DexFile::TypeId* DexFile::FindTypeId(const char* string) const { | 
 | 723 |   int32_t lo = 0; | 
 | 724 |   int32_t hi = NumTypeIds() - 1; | 
 | 725 |   while (hi >= lo) { | 
 | 726 |     int32_t mid = (hi + lo) / 2; | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 727 |     const TypeId& type_id = GetTypeId(dex::TypeIndex(mid)); | 
| Artem Udovichenko | d9786b0 | 2015-10-14 16:36:55 +0300 | [diff] [blame] | 728 |     const DexFile::StringId& str_id = GetStringId(type_id.descriptor_idx_); | 
 | 729 |     const char* str = GetStringData(str_id); | 
 | 730 |     int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string, str); | 
 | 731 |     if (compare > 0) { | 
 | 732 |       lo = mid + 1; | 
 | 733 |     } else if (compare < 0) { | 
 | 734 |       hi = mid - 1; | 
 | 735 |     } else { | 
 | 736 |       return &type_id; | 
 | 737 |     } | 
 | 738 |   } | 
 | 739 |   return nullptr; | 
 | 740 | } | 
 | 741 |  | 
| Vladimir Marko | a48aef4 | 2014-12-03 17:53:53 +0000 | [diff] [blame] | 742 | 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] | 743 |   int32_t lo = 0; | 
 | 744 |   int32_t hi = NumStringIds() - 1; | 
 | 745 |   while (hi >= lo) { | 
 | 746 |     int32_t mid = (hi + lo) / 2; | 
| Andreas Gampe | 8a0128a | 2016-11-28 07:38:35 -0800 | [diff] [blame] | 747 |     const DexFile::StringId& str_id = GetStringId(dex::StringIndex(mid)); | 
| Ian Rogers | cf5077a | 2013-10-31 12:37:54 -0700 | [diff] [blame] | 748 |     const char* str = GetStringData(str_id); | 
| Vladimir Marko | a48aef4 | 2014-12-03 17:53:53 +0000 | [diff] [blame] | 749 |     int compare = CompareModifiedUtf8ToUtf16AsCodePointValues(str, string, length); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 750 |     if (compare > 0) { | 
 | 751 |       lo = mid + 1; | 
 | 752 |     } else if (compare < 0) { | 
 | 753 |       hi = mid - 1; | 
 | 754 |     } else { | 
 | 755 |       return &str_id; | 
 | 756 |     } | 
 | 757 |   } | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 758 |   return nullptr; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 759 | } | 
 | 760 |  | 
| Andreas Gampe | 8a0128a | 2016-11-28 07:38:35 -0800 | [diff] [blame] | 761 | const DexFile::TypeId* DexFile::FindTypeId(dex::StringIndex string_idx) const { | 
| Ian Rogers | f8582c3 | 2013-05-29 16:33:03 -0700 | [diff] [blame] | 762 |   int32_t lo = 0; | 
 | 763 |   int32_t hi = NumTypeIds() - 1; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 764 |   while (hi >= lo) { | 
| Ian Rogers | f8582c3 | 2013-05-29 16:33:03 -0700 | [diff] [blame] | 765 |     int32_t mid = (hi + lo) / 2; | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 766 |     const TypeId& type_id = GetTypeId(dex::TypeIndex(mid)); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 767 |     if (string_idx > type_id.descriptor_idx_) { | 
 | 768 |       lo = mid + 1; | 
 | 769 |     } else if (string_idx < type_id.descriptor_idx_) { | 
 | 770 |       hi = mid - 1; | 
 | 771 |     } else { | 
 | 772 |       return &type_id; | 
 | 773 |     } | 
 | 774 |   } | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 775 |   return nullptr; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 776 | } | 
 | 777 |  | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 778 | const DexFile::ProtoId* DexFile::FindProtoId(dex::TypeIndex return_type_idx, | 
 | 779 |                                              const dex::TypeIndex* signature_type_idxs, | 
| Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 780 |                                              uint32_t signature_length) const { | 
| Ian Rogers | f8582c3 | 2013-05-29 16:33:03 -0700 | [diff] [blame] | 781 |   int32_t lo = 0; | 
 | 782 |   int32_t hi = NumProtoIds() - 1; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 783 |   while (hi >= lo) { | 
| Ian Rogers | f8582c3 | 2013-05-29 16:33:03 -0700 | [diff] [blame] | 784 |     int32_t mid = (hi + lo) / 2; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 785 |     const DexFile::ProtoId& proto = GetProtoId(mid); | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 786 |     int compare = return_type_idx.index_ - proto.return_type_idx_.index_; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 787 |     if (compare == 0) { | 
 | 788 |       DexFileParameterIterator it(*this, proto); | 
 | 789 |       size_t i = 0; | 
| Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 790 |       while (it.HasNext() && i < signature_length && compare == 0) { | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 791 |         compare = signature_type_idxs[i].index_ - it.GetTypeIdx().index_; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 792 |         it.Next(); | 
 | 793 |         i++; | 
 | 794 |       } | 
 | 795 |       if (compare == 0) { | 
 | 796 |         if (it.HasNext()) { | 
 | 797 |           compare = -1; | 
| Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 798 |         } else if (i < signature_length) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 799 |           compare = 1; | 
 | 800 |         } | 
 | 801 |       } | 
 | 802 |     } | 
 | 803 |     if (compare > 0) { | 
 | 804 |       lo = mid + 1; | 
 | 805 |     } else if (compare < 0) { | 
 | 806 |       hi = mid - 1; | 
 | 807 |     } else { | 
 | 808 |       return &proto; | 
 | 809 |     } | 
 | 810 |   } | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 811 |   return nullptr; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 812 | } | 
 | 813 |  | 
 | 814 | // Given a signature place the type ids into the given vector | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 815 | bool DexFile::CreateTypeList(const StringPiece& signature, | 
 | 816 |                              dex::TypeIndex* return_type_idx, | 
 | 817 |                              std::vector<dex::TypeIndex>* param_type_idxs) const { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 818 |   if (signature[0] != '(') { | 
 | 819 |     return false; | 
 | 820 |   } | 
 | 821 |   size_t offset = 1; | 
 | 822 |   size_t end = signature.size(); | 
 | 823 |   bool process_return = false; | 
 | 824 |   while (offset < end) { | 
| Vladimir Marko | e9c36b3 | 2013-11-21 15:49:16 +0000 | [diff] [blame] | 825 |     size_t start_offset = offset; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 826 |     char c = signature[offset]; | 
 | 827 |     offset++; | 
 | 828 |     if (c == ')') { | 
 | 829 |       process_return = true; | 
 | 830 |       continue; | 
 | 831 |     } | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 832 |     while (c == '[') {  // process array prefix | 
 | 833 |       if (offset >= end) {  // expect some descriptor following [ | 
 | 834 |         return false; | 
 | 835 |       } | 
 | 836 |       c = signature[offset]; | 
 | 837 |       offset++; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 838 |     } | 
 | 839 |     if (c == 'L') {  // process type descriptors | 
 | 840 |       do { | 
 | 841 |         if (offset >= end) {  // unexpected early termination of descriptor | 
 | 842 |           return false; | 
 | 843 |         } | 
 | 844 |         c = signature[offset]; | 
 | 845 |         offset++; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 846 |       } while (c != ';'); | 
 | 847 |     } | 
| Vladimir Marko | e9c36b3 | 2013-11-21 15:49:16 +0000 | [diff] [blame] | 848 |     // TODO: avoid creating a std::string just to get a 0-terminated char array | 
 | 849 |     std::string descriptor(signature.data() + start_offset, offset - start_offset); | 
| Mathieu Chartier | 9507fa2 | 2015-10-29 15:08:57 -0700 | [diff] [blame] | 850 |     const DexFile::TypeId* type_id = FindTypeId(descriptor.c_str()); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 851 |     if (type_id == nullptr) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 852 |       return false; | 
 | 853 |     } | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 854 |     dex::TypeIndex type_idx = GetIndexForTypeId(*type_id); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 855 |     if (!process_return) { | 
 | 856 |       param_type_idxs->push_back(type_idx); | 
 | 857 |     } else { | 
 | 858 |       *return_type_idx = type_idx; | 
 | 859 |       return offset == end;  // return true if the signature had reached a sensible end | 
 | 860 |     } | 
 | 861 |   } | 
 | 862 |   return false;  // failed to correctly parse return type | 
 | 863 | } | 
 | 864 |  | 
| Ian Rogers | d91d6d6 | 2013-09-25 20:26:14 -0700 | [diff] [blame] | 865 | const Signature DexFile::CreateSignature(const StringPiece& signature) const { | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 866 |   dex::TypeIndex return_type_idx; | 
 | 867 |   std::vector<dex::TypeIndex> param_type_indices; | 
| Ian Rogers | d91d6d6 | 2013-09-25 20:26:14 -0700 | [diff] [blame] | 868 |   bool success = CreateTypeList(signature, &return_type_idx, ¶m_type_indices); | 
 | 869 |   if (!success) { | 
 | 870 |     return Signature::NoSignature(); | 
| Carl Shapiro | 419ec7b | 2011-08-03 14:48:33 -0700 | [diff] [blame] | 871 |   } | 
| Ian Rogers | d91d6d6 | 2013-09-25 20:26:14 -0700 | [diff] [blame] | 872 |   const ProtoId* proto_id = FindProtoId(return_type_idx, param_type_indices); | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 873 |   if (proto_id == nullptr) { | 
| Ian Rogers | d91d6d6 | 2013-09-25 20:26:14 -0700 | [diff] [blame] | 874 |     return Signature::NoSignature(); | 
| Brian Carlstrom | 20cfffa | 2011-08-26 02:31:27 -0700 | [diff] [blame] | 875 |   } | 
| Ian Rogers | d91d6d6 | 2013-09-25 20:26:14 -0700 | [diff] [blame] | 876 |   return Signature(this, *proto_id); | 
| Carl Shapiro | 419ec7b | 2011-08-03 14:48:33 -0700 | [diff] [blame] | 877 | } | 
 | 878 |  | 
| Ian Rogers | dbbc99d | 2013-04-18 16:51:54 -0700 | [diff] [blame] | 879 | int32_t DexFile::FindTryItem(const CodeItem &code_item, uint32_t address) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 880 |   // Note: Signed type is important for max and min. | 
 | 881 |   int32_t min = 0; | 
| Ian Rogers | dbbc99d | 2013-04-18 16:51:54 -0700 | [diff] [blame] | 882 |   int32_t max = code_item.tries_size_ - 1; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 883 |  | 
| Ian Rogers | dbbc99d | 2013-04-18 16:51:54 -0700 | [diff] [blame] | 884 |   while (min <= max) { | 
 | 885 |     int32_t mid = min + ((max - min) / 2); | 
 | 886 |  | 
 | 887 |     const art::DexFile::TryItem* ti = GetTryItems(code_item, mid); | 
 | 888 |     uint32_t start = ti->start_addr_; | 
 | 889 |     uint32_t end = start + ti->insn_count_; | 
 | 890 |  | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 891 |     if (address < start) { | 
 | 892 |       max = mid - 1; | 
| Ian Rogers | dbbc99d | 2013-04-18 16:51:54 -0700 | [diff] [blame] | 893 |     } else if (address >= end) { | 
 | 894 |       min = mid + 1; | 
 | 895 |     } else {  // We have a winner! | 
 | 896 |       return mid; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 897 |     } | 
 | 898 |   } | 
 | 899 |   // No match. | 
 | 900 |   return -1; | 
 | 901 | } | 
 | 902 |  | 
| Ian Rogers | dbbc99d | 2013-04-18 16:51:54 -0700 | [diff] [blame] | 903 | int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, uint32_t address) { | 
 | 904 |   int32_t try_item = FindTryItem(code_item, address); | 
 | 905 |   if (try_item == -1) { | 
 | 906 |     return -1; | 
 | 907 |   } else { | 
 | 908 |     return DexFile::GetTryItems(code_item, try_item)->handler_off_; | 
 | 909 |   } | 
 | 910 | } | 
 | 911 |  | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 912 | bool DexFile::DecodeDebugLocalInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx, | 
 | 913 |                                    DexDebugNewLocalCb local_cb, void* context) const { | 
 | 914 |   DCHECK(local_cb != nullptr); | 
 | 915 |   if (code_item == nullptr) { | 
 | 916 |     return false; | 
 | 917 |   } | 
 | 918 |   const uint8_t* stream = GetDebugInfoStream(code_item); | 
 | 919 |   if (stream == nullptr) { | 
 | 920 |     return false; | 
 | 921 |   } | 
 | 922 |   std::vector<LocalInfo> local_in_reg(code_item->registers_size_); | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 923 |  | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 924 |   uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_; | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 925 |   if (!is_static) { | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 926 |     const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx)); | 
 | 927 |     local_in_reg[arg_reg].name_ = "this"; | 
 | 928 |     local_in_reg[arg_reg].descriptor_ = descriptor; | 
 | 929 |     local_in_reg[arg_reg].signature_ = nullptr; | 
 | 930 |     local_in_reg[arg_reg].start_address_ = 0; | 
 | 931 |     local_in_reg[arg_reg].reg_ = arg_reg; | 
 | 932 |     local_in_reg[arg_reg].is_live_ = true; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 933 |     arg_reg++; | 
 | 934 |   } | 
 | 935 |  | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 936 |   DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx))); | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 937 |   DecodeUnsignedLeb128(&stream);  // Line. | 
 | 938 |   uint32_t parameters_size = DecodeUnsignedLeb128(&stream); | 
 | 939 |   uint32_t i; | 
 | 940 |   for (i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) { | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 941 |     if (arg_reg >= code_item->registers_size_) { | 
| jeffhao | f872887 | 2011-10-28 19:11:13 -0700 | [diff] [blame] | 942 |       LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg | 
| Brian Carlstrom | 2aab947 | 2011-12-12 15:21:43 -0800 | [diff] [blame] | 943 |                  << " >= " << code_item->registers_size_ << ") in " << GetLocation(); | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 944 |       return false; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 945 |     } | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 946 |     uint32_t name_idx = DecodeUnsignedLeb128P1(&stream); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 947 |     const char* descriptor = it.GetDescriptor(); | 
| Andreas Gampe | 8a0128a | 2016-11-28 07:38:35 -0800 | [diff] [blame] | 948 |     local_in_reg[arg_reg].name_ = StringDataByIdx(dex::StringIndex(name_idx)); | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 949 |     local_in_reg[arg_reg].descriptor_ = descriptor; | 
 | 950 |     local_in_reg[arg_reg].signature_ = nullptr; | 
 | 951 |     local_in_reg[arg_reg].start_address_ = 0; | 
 | 952 |     local_in_reg[arg_reg].reg_ = arg_reg; | 
 | 953 |     local_in_reg[arg_reg].is_live_ = true; | 
| Brian Carlstrom | 40381fb | 2011-10-19 14:13:40 -0700 | [diff] [blame] | 954 |     switch (*descriptor) { | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 955 |       case 'D': | 
 | 956 |       case 'J': | 
 | 957 |         arg_reg += 2; | 
 | 958 |         break; | 
 | 959 |       default: | 
 | 960 |         arg_reg += 1; | 
 | 961 |         break; | 
 | 962 |     } | 
 | 963 |   } | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 964 |   if (i != parameters_size || it.HasNext()) { | 
| Brian Carlstrom | f79fccb | 2014-02-20 08:55:10 -0800 | [diff] [blame] | 965 |     LOG(ERROR) << "invalid stream - problem with parameter iterator in " << GetLocation() | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 966 |                << " for method " << this->PrettyMethod(method_idx); | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 967 |     return false; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 968 |   } | 
 | 969 |  | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 970 |   uint32_t address = 0; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 971 |   for (;;)  { | 
 | 972 |     uint8_t opcode = *stream++; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 973 |     switch (opcode) { | 
 | 974 |       case DBG_END_SEQUENCE: | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 975 |         // Emit all variables which are still alive at the end of the method. | 
 | 976 |         for (uint16_t reg = 0; reg < code_item->registers_size_; reg++) { | 
 | 977 |           if (local_in_reg[reg].is_live_) { | 
 | 978 |             local_in_reg[reg].end_address_ = code_item->insns_size_in_code_units_; | 
 | 979 |             local_cb(context, local_in_reg[reg]); | 
 | 980 |           } | 
 | 981 |         } | 
 | 982 |         return true; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 983 |       case DBG_ADVANCE_PC: | 
 | 984 |         address += DecodeUnsignedLeb128(&stream); | 
 | 985 |         break; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 986 |       case DBG_ADVANCE_LINE: | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 987 |         DecodeSignedLeb128(&stream);  // Line. | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 988 |         break; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 989 |       case DBG_START_LOCAL: | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 990 |       case DBG_START_LOCAL_EXTENDED: { | 
 | 991 |         uint16_t reg = DecodeUnsignedLeb128(&stream); | 
 | 992 |         if (reg >= code_item->registers_size_) { | 
 | 993 |           LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= " | 
| Brian Carlstrom | 2aab947 | 2011-12-12 15:21:43 -0800 | [diff] [blame] | 994 |                      << code_item->registers_size_ << ") in " << GetLocation(); | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 995 |           return false; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 996 |         } | 
 | 997 |  | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 998 |         uint32_t name_idx = DecodeUnsignedLeb128P1(&stream); | 
 | 999 |         uint32_t descriptor_idx = DecodeUnsignedLeb128P1(&stream); | 
 | 1000 |         uint32_t signature_idx = kDexNoIndex; | 
| jeffhao | f872887 | 2011-10-28 19:11:13 -0700 | [diff] [blame] | 1001 |         if (opcode == DBG_START_LOCAL_EXTENDED) { | 
 | 1002 |           signature_idx = DecodeUnsignedLeb128P1(&stream); | 
 | 1003 |         } | 
 | 1004 |  | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 1005 |         // Emit what was previously there, if anything | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 1006 |         if (local_in_reg[reg].is_live_) { | 
 | 1007 |           local_in_reg[reg].end_address_ = address; | 
 | 1008 |           local_cb(context, local_in_reg[reg]); | 
 | 1009 |         } | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 1010 |  | 
| Andreas Gampe | 8a0128a | 2016-11-28 07:38:35 -0800 | [diff] [blame] | 1011 |         local_in_reg[reg].name_ = StringDataByIdx(dex::StringIndex(name_idx)); | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 1012 |         local_in_reg[reg].descriptor_ = | 
 | 1013 |             StringByTypeIdx(dex::TypeIndex(dchecked_integral_cast<uint16_t>(descriptor_idx)));; | 
| Andreas Gampe | 8a0128a | 2016-11-28 07:38:35 -0800 | [diff] [blame] | 1014 |         local_in_reg[reg].signature_ = StringDataByIdx(dex::StringIndex(signature_idx)); | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 1015 |         local_in_reg[reg].start_address_ = address; | 
 | 1016 |         local_in_reg[reg].reg_ = reg; | 
 | 1017 |         local_in_reg[reg].is_live_ = true; | 
 | 1018 |         break; | 
 | 1019 |       } | 
 | 1020 |       case DBG_END_LOCAL: { | 
 | 1021 |         uint16_t reg = DecodeUnsignedLeb128(&stream); | 
 | 1022 |         if (reg >= code_item->registers_size_) { | 
 | 1023 |           LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= " | 
 | 1024 |                      << code_item->registers_size_ << ") in " << GetLocation(); | 
 | 1025 |           return false; | 
 | 1026 |         } | 
 | 1027 |         if (!local_in_reg[reg].is_live_) { | 
 | 1028 |           LOG(ERROR) << "invalid stream - end without start in " << GetLocation(); | 
 | 1029 |           return false; | 
 | 1030 |         } | 
 | 1031 |         local_in_reg[reg].end_address_ = address; | 
 | 1032 |         local_cb(context, local_in_reg[reg]); | 
 | 1033 |         local_in_reg[reg].is_live_ = false; | 
 | 1034 |         break; | 
 | 1035 |       } | 
 | 1036 |       case DBG_RESTART_LOCAL: { | 
 | 1037 |         uint16_t reg = DecodeUnsignedLeb128(&stream); | 
 | 1038 |         if (reg >= code_item->registers_size_) { | 
 | 1039 |           LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= " | 
 | 1040 |                      << code_item->registers_size_ << ") in " << GetLocation(); | 
 | 1041 |           return false; | 
 | 1042 |         } | 
 | 1043 |         // If the register is live, the "restart" is superfluous, | 
 | 1044 |         // and we don't want to mess with the existing start address. | 
 | 1045 |         if (!local_in_reg[reg].is_live_) { | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 1046 |           local_in_reg[reg].start_address_ = address; | 
 | 1047 |           local_in_reg[reg].is_live_ = true; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 1048 |         } | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 1049 |         break; | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 1050 |       } | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 1051 |       case DBG_SET_PROLOGUE_END: | 
 | 1052 |       case DBG_SET_EPILOGUE_BEGIN: | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 1053 |         break; | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 1054 |       case DBG_SET_FILE: | 
 | 1055 |         DecodeUnsignedLeb128P1(&stream);  // name. | 
 | 1056 |         break; | 
 | 1057 |       default: | 
 | 1058 |         address += (opcode - DBG_FIRST_SPECIAL) / DBG_LINE_RANGE; | 
 | 1059 |         break; | 
 | 1060 |     } | 
 | 1061 |   } | 
 | 1062 | } | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 1063 |  | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 1064 | bool DexFile::DecodeDebugPositionInfo(const CodeItem* code_item, DexDebugNewPositionCb position_cb, | 
 | 1065 |                                       void* context) const { | 
 | 1066 |   DCHECK(position_cb != nullptr); | 
 | 1067 |   if (code_item == nullptr) { | 
 | 1068 |     return false; | 
 | 1069 |   } | 
 | 1070 |   const uint8_t* stream = GetDebugInfoStream(code_item); | 
 | 1071 |   if (stream == nullptr) { | 
 | 1072 |     return false; | 
 | 1073 |   } | 
 | 1074 |  | 
 | 1075 |   PositionInfo entry = PositionInfo(); | 
 | 1076 |   entry.line_ = DecodeUnsignedLeb128(&stream); | 
 | 1077 |   uint32_t parameters_size = DecodeUnsignedLeb128(&stream); | 
 | 1078 |   for (uint32_t i = 0; i < parameters_size; ++i) { | 
 | 1079 |     DecodeUnsignedLeb128P1(&stream);  // Parameter name. | 
 | 1080 |   } | 
 | 1081 |  | 
 | 1082 |   for (;;)  { | 
 | 1083 |     uint8_t opcode = *stream++; | 
 | 1084 |     switch (opcode) { | 
 | 1085 |       case DBG_END_SEQUENCE: | 
 | 1086 |         return true;  // end of stream. | 
 | 1087 |       case DBG_ADVANCE_PC: | 
 | 1088 |         entry.address_ += DecodeUnsignedLeb128(&stream); | 
 | 1089 |         break; | 
 | 1090 |       case DBG_ADVANCE_LINE: | 
 | 1091 |         entry.line_ += DecodeSignedLeb128(&stream); | 
 | 1092 |         break; | 
 | 1093 |       case DBG_START_LOCAL: | 
 | 1094 |         DecodeUnsignedLeb128(&stream);  // reg. | 
 | 1095 |         DecodeUnsignedLeb128P1(&stream);  // name. | 
 | 1096 |         DecodeUnsignedLeb128P1(&stream);  // descriptor. | 
 | 1097 |         break; | 
 | 1098 |       case DBG_START_LOCAL_EXTENDED: | 
 | 1099 |         DecodeUnsignedLeb128(&stream);  // reg. | 
 | 1100 |         DecodeUnsignedLeb128P1(&stream);  // name. | 
 | 1101 |         DecodeUnsignedLeb128P1(&stream);  // descriptor. | 
 | 1102 |         DecodeUnsignedLeb128P1(&stream);  // signature. | 
 | 1103 |         break; | 
 | 1104 |       case DBG_END_LOCAL: | 
 | 1105 |       case DBG_RESTART_LOCAL: | 
 | 1106 |         DecodeUnsignedLeb128(&stream);  // reg. | 
 | 1107 |         break; | 
 | 1108 |       case DBG_SET_PROLOGUE_END: | 
 | 1109 |         entry.prologue_end_ = true; | 
 | 1110 |         break; | 
 | 1111 |       case DBG_SET_EPILOGUE_BEGIN: | 
 | 1112 |         entry.epilogue_begin_ = true; | 
 | 1113 |         break; | 
 | 1114 |       case DBG_SET_FILE: { | 
 | 1115 |         uint32_t name_idx = DecodeUnsignedLeb128P1(&stream); | 
| Andreas Gampe | 8a0128a | 2016-11-28 07:38:35 -0800 | [diff] [blame] | 1116 |         entry.source_file_ = StringDataByIdx(dex::StringIndex(name_idx)); | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 1117 |         break; | 
 | 1118 |       } | 
| Shih-wei Liao | 8e1b4ff | 2011-10-15 15:43:51 -0700 | [diff] [blame] | 1119 |       default: { | 
 | 1120 |         int adjopcode = opcode - DBG_FIRST_SPECIAL; | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 1121 |         entry.address_ += adjopcode / DBG_LINE_RANGE; | 
 | 1122 |         entry.line_ += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE); | 
 | 1123 |         if (position_cb(context, entry)) { | 
 | 1124 |           return true;  // early exit. | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 1125 |         } | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 1126 |         entry.prologue_end_ = false; | 
 | 1127 |         entry.epilogue_begin_ = false; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 1128 |         break; | 
| Shih-wei Liao | 8e1b4ff | 2011-10-15 15:43:51 -0700 | [diff] [blame] | 1129 |       } | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 1130 |     } | 
 | 1131 |   } | 
 | 1132 | } | 
 | 1133 |  | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 1134 | bool DexFile::LineNumForPcCb(void* raw_context, const PositionInfo& entry) { | 
| Elliott Hughes | 2435a57 | 2012-02-17 16:07:41 -0800 | [diff] [blame] | 1135 |   LineNumFromPcContext* context = reinterpret_cast<LineNumFromPcContext*>(raw_context); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1136 |  | 
 | 1137 |   // We know that this callback will be called in | 
 | 1138 |   // ascending address order, so keep going until we find | 
 | 1139 |   // a match or we've just gone past it. | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 1140 |   if (entry.address_ > context->address_) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1141 |     // The line number from the previous positions callback | 
 | 1142 |     // wil be the final result. | 
 | 1143 |     return true; | 
 | 1144 |   } else { | 
| David Srbecky | b06e28e | 2015-12-10 13:15:00 +0000 | [diff] [blame] | 1145 |     context->line_num_ = entry.line_; | 
 | 1146 |     return entry.address_ == context->address_; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1147 |   } | 
 | 1148 | } | 
 | 1149 |  | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 1150 | bool DexFile::IsMultiDexLocation(const char* location) { | 
 | 1151 |   return strrchr(location, kMultiDexSeparator) != nullptr; | 
 | 1152 | } | 
 | 1153 |  | 
| Andreas Gampe | 90e3404 | 2015-04-27 20:01:52 -0700 | [diff] [blame] | 1154 | std::string DexFile::GetMultiDexClassesDexName(size_t index) { | 
 | 1155 |   if (index == 0) { | 
 | 1156 |     return "classes.dex"; | 
 | 1157 |   } else { | 
 | 1158 |     return StringPrintf("classes%zu.dex", index + 1); | 
 | 1159 |   } | 
 | 1160 | } | 
 | 1161 |  | 
 | 1162 | std::string DexFile::GetMultiDexLocation(size_t index, const char* dex_location) { | 
 | 1163 |   if (index == 0) { | 
| Calin Juravle | 4e1d579 | 2014-07-15 23:56:47 +0100 | [diff] [blame] | 1164 |     return dex_location; | 
 | 1165 |   } else { | 
| Andreas Gampe | 90e3404 | 2015-04-27 20:01:52 -0700 | [diff] [blame] | 1166 |     return StringPrintf("%s" kMultiDexSeparatorString "classes%zu.dex", dex_location, index + 1); | 
| Calin Juravle | 4e1d579 | 2014-07-15 23:56:47 +0100 | [diff] [blame] | 1167 |   } | 
 | 1168 | } | 
 | 1169 |  | 
 | 1170 | std::string DexFile::GetDexCanonicalLocation(const char* dex_location) { | 
 | 1171 |   CHECK_NE(dex_location, static_cast<const char*>(nullptr)); | 
| Vladimir Marko | aa4497d | 2014-09-05 14:01:17 +0100 | [diff] [blame] | 1172 |   std::string base_location = GetBaseLocation(dex_location); | 
 | 1173 |   const char* suffix = dex_location + base_location.size(); | 
 | 1174 |   DCHECK(suffix[0] == 0 || suffix[0] == kMultiDexSeparator); | 
 | 1175 |   UniqueCPtr<const char[]> path(realpath(base_location.c_str(), nullptr)); | 
 | 1176 |   if (path != nullptr && path.get() != base_location) { | 
 | 1177 |     return std::string(path.get()) + suffix; | 
 | 1178 |   } else if (suffix[0] == 0) { | 
 | 1179 |     return base_location; | 
| Calin Juravle | 4e1d579 | 2014-07-15 23:56:47 +0100 | [diff] [blame] | 1180 |   } else { | 
| Vladimir Marko | aa4497d | 2014-09-05 14:01:17 +0100 | [diff] [blame] | 1181 |     return dex_location; | 
| Calin Juravle | 4e1d579 | 2014-07-15 23:56:47 +0100 | [diff] [blame] | 1182 |   } | 
| Calin Juravle | 4e1d579 | 2014-07-15 23:56:47 +0100 | [diff] [blame] | 1183 | } | 
 | 1184 |  | 
| Jeff Hao | 13e748b | 2015-08-25 20:44:19 +0000 | [diff] [blame] | 1185 | // Read a signed integer.  "zwidth" is the zero-based byte count. | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1186 | int32_t DexFile::ReadSignedInt(const uint8_t* ptr, int zwidth) { | 
| Jeff Hao | 13e748b | 2015-08-25 20:44:19 +0000 | [diff] [blame] | 1187 |   int32_t val = 0; | 
 | 1188 |   for (int i = zwidth; i >= 0; --i) { | 
 | 1189 |     val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24); | 
 | 1190 |   } | 
 | 1191 |   val >>= (3 - zwidth) * 8; | 
 | 1192 |   return val; | 
 | 1193 | } | 
 | 1194 |  | 
 | 1195 | // Read an unsigned integer.  "zwidth" is the zero-based byte count, | 
 | 1196 | // "fill_on_right" indicates which side we want to zero-fill from. | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1197 | uint32_t DexFile::ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right) { | 
| Jeff Hao | 13e748b | 2015-08-25 20:44:19 +0000 | [diff] [blame] | 1198 |   uint32_t val = 0; | 
 | 1199 |   for (int i = zwidth; i >= 0; --i) { | 
 | 1200 |     val = (val >> 8) | (((uint32_t)*ptr++) << 24); | 
 | 1201 |   } | 
 | 1202 |   if (!fill_on_right) { | 
 | 1203 |     val >>= (3 - zwidth) * 8; | 
 | 1204 |   } | 
 | 1205 |   return val; | 
 | 1206 | } | 
 | 1207 |  | 
 | 1208 | // Read a signed long.  "zwidth" is the zero-based byte count. | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1209 | int64_t DexFile::ReadSignedLong(const uint8_t* ptr, int zwidth) { | 
| Jeff Hao | 13e748b | 2015-08-25 20:44:19 +0000 | [diff] [blame] | 1210 |   int64_t val = 0; | 
 | 1211 |   for (int i = zwidth; i >= 0; --i) { | 
 | 1212 |     val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56); | 
 | 1213 |   } | 
 | 1214 |   val >>= (7 - zwidth) * 8; | 
 | 1215 |   return val; | 
 | 1216 | } | 
 | 1217 |  | 
 | 1218 | // Read an unsigned long.  "zwidth" is the zero-based byte count, | 
 | 1219 | // "fill_on_right" indicates which side we want to zero-fill from. | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1220 | uint64_t DexFile::ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right) { | 
| Jeff Hao | 13e748b | 2015-08-25 20:44:19 +0000 | [diff] [blame] | 1221 |   uint64_t val = 0; | 
 | 1222 |   for (int i = zwidth; i >= 0; --i) { | 
 | 1223 |     val = (val >> 8) | (((uint64_t)*ptr++) << 56); | 
 | 1224 |   } | 
 | 1225 |   if (!fill_on_right) { | 
 | 1226 |     val >>= (7 - zwidth) * 8; | 
 | 1227 |   } | 
 | 1228 |   return val; | 
 | 1229 | } | 
 | 1230 |  | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 1231 | std::string DexFile::PrettyMethod(uint32_t method_idx, bool with_signature) const { | 
 | 1232 |   if (method_idx >= NumMethodIds()) { | 
 | 1233 |     return StringPrintf("<<invalid-method-idx-%d>>", method_idx); | 
 | 1234 |   } | 
 | 1235 |   const DexFile::MethodId& method_id = GetMethodId(method_idx); | 
 | 1236 |   std::string result(PrettyDescriptor(GetMethodDeclaringClassDescriptor(method_id))); | 
 | 1237 |   result += '.'; | 
 | 1238 |   result += GetMethodName(method_id); | 
 | 1239 |   if (with_signature) { | 
 | 1240 |     const Signature signature = GetMethodSignature(method_id); | 
 | 1241 |     std::string sig_as_string(signature.ToString()); | 
 | 1242 |     if (signature == Signature::NoSignature()) { | 
 | 1243 |       return result + sig_as_string; | 
 | 1244 |     } | 
 | 1245 |     result = PrettyReturnType(sig_as_string.c_str()) + " " + result + | 
 | 1246 |         PrettyArguments(sig_as_string.c_str()); | 
 | 1247 |   } | 
 | 1248 |   return result; | 
 | 1249 | } | 
 | 1250 |  | 
 | 1251 | std::string DexFile::PrettyField(uint32_t field_idx, bool with_type) const { | 
 | 1252 |   if (field_idx >= NumFieldIds()) { | 
 | 1253 |     return StringPrintf("<<invalid-field-idx-%d>>", field_idx); | 
 | 1254 |   } | 
 | 1255 |   const DexFile::FieldId& field_id = GetFieldId(field_idx); | 
 | 1256 |   std::string result; | 
 | 1257 |   if (with_type) { | 
 | 1258 |     result += GetFieldTypeDescriptor(field_id); | 
 | 1259 |     result += ' '; | 
 | 1260 |   } | 
 | 1261 |   result += PrettyDescriptor(GetFieldDeclaringClassDescriptor(field_id)); | 
 | 1262 |   result += '.'; | 
 | 1263 |   result += GetFieldName(field_id); | 
 | 1264 |   return result; | 
 | 1265 | } | 
 | 1266 |  | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 1267 | std::string DexFile::PrettyType(dex::TypeIndex type_idx) const { | 
 | 1268 |   if (type_idx.index_ >= NumTypeIds()) { | 
 | 1269 |     return StringPrintf("<<invalid-type-idx-%d>>", type_idx.index_); | 
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 1270 |   } | 
 | 1271 |   const DexFile::TypeId& type_id = GetTypeId(type_idx); | 
 | 1272 |   return PrettyDescriptor(GetTypeDescriptor(type_id)); | 
 | 1273 | } | 
 | 1274 |  | 
| Jeff Hao | 3d08086 | 2016-05-26 18:39:17 -0700 | [diff] [blame] | 1275 | // Checks that visibility is as expected. Includes special behavior for M and | 
 | 1276 | // before to allow runtime and build visibility when expecting runtime. | 
| Brian Carlstrom | 0d6adac | 2014-02-05 17:39:16 -0800 | [diff] [blame] | 1277 | std::ostream& operator<<(std::ostream& os, const DexFile& dex_file) { | 
 | 1278 |   os << StringPrintf("[DexFile: %s dex-checksum=%08x location-checksum=%08x %p-%p]", | 
 | 1279 |                      dex_file.GetLocation().c_str(), | 
 | 1280 |                      dex_file.GetHeader().checksum_, dex_file.GetLocationChecksum(), | 
 | 1281 |                      dex_file.Begin(), dex_file.Begin() + dex_file.Size()); | 
 | 1282 |   return os; | 
 | 1283 | } | 
| Calin Juravle | 4e1d579 | 2014-07-15 23:56:47 +0100 | [diff] [blame] | 1284 |  | 
| Ian Rogers | d91d6d6 | 2013-09-25 20:26:14 -0700 | [diff] [blame] | 1285 | std::string Signature::ToString() const { | 
 | 1286 |   if (dex_file_ == nullptr) { | 
 | 1287 |     CHECK(proto_id_ == nullptr); | 
 | 1288 |     return "<no signature>"; | 
 | 1289 |   } | 
 | 1290 |   const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_); | 
 | 1291 |   std::string result; | 
 | 1292 |   if (params == nullptr) { | 
 | 1293 |     result += "()"; | 
 | 1294 |   } else { | 
 | 1295 |     result += "("; | 
 | 1296 |     for (uint32_t i = 0; i < params->Size(); ++i) { | 
 | 1297 |       result += dex_file_->StringByTypeIdx(params->GetTypeItem(i).type_idx_); | 
 | 1298 |     } | 
 | 1299 |     result += ")"; | 
 | 1300 |   } | 
 | 1301 |   result += dex_file_->StringByTypeIdx(proto_id_->return_type_idx_); | 
 | 1302 |   return result; | 
 | 1303 | } | 
 | 1304 |  | 
| Orion Hodson | 6c4921b | 2016-09-21 15:41:06 +0100 | [diff] [blame] | 1305 | uint32_t Signature::GetNumberOfParameters() const { | 
 | 1306 |   const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_); | 
 | 1307 |   return (params != nullptr) ? params->Size() : 0; | 
 | 1308 | } | 
 | 1309 |  | 
 | 1310 | bool Signature::IsVoid() const { | 
 | 1311 |   const char* return_type = dex_file_->GetReturnTypeDescriptor(*proto_id_); | 
 | 1312 |   return strcmp(return_type, "V") == 0; | 
 | 1313 | } | 
 | 1314 |  | 
| Vladimir Marko | d9cffea | 2013-11-25 15:08:02 +0000 | [diff] [blame] | 1315 | bool Signature::operator==(const StringPiece& rhs) const { | 
 | 1316 |   if (dex_file_ == nullptr) { | 
 | 1317 |     return false; | 
 | 1318 |   } | 
 | 1319 |   StringPiece tail(rhs); | 
 | 1320 |   if (!tail.starts_with("(")) { | 
 | 1321 |     return false;  // Invalid signature | 
 | 1322 |   } | 
 | 1323 |   tail.remove_prefix(1);  // "("; | 
 | 1324 |   const DexFile::TypeList* params = dex_file_->GetProtoParameters(*proto_id_); | 
 | 1325 |   if (params != nullptr) { | 
 | 1326 |     for (uint32_t i = 0; i < params->Size(); ++i) { | 
 | 1327 |       StringPiece param(dex_file_->StringByTypeIdx(params->GetTypeItem(i).type_idx_)); | 
 | 1328 |       if (!tail.starts_with(param)) { | 
 | 1329 |         return false; | 
 | 1330 |       } | 
 | 1331 |       tail.remove_prefix(param.length()); | 
 | 1332 |     } | 
 | 1333 |   } | 
 | 1334 |   if (!tail.starts_with(")")) { | 
 | 1335 |     return false; | 
 | 1336 |   } | 
 | 1337 |   tail.remove_prefix(1);  // ")"; | 
 | 1338 |   return tail == dex_file_->StringByTypeIdx(proto_id_->return_type_idx_); | 
 | 1339 | } | 
 | 1340 |  | 
| Ian Rogers | d91d6d6 | 2013-09-25 20:26:14 -0700 | [diff] [blame] | 1341 | std::ostream& operator<<(std::ostream& os, const Signature& sig) { | 
 | 1342 |   return os << sig.ToString(); | 
 | 1343 | } | 
 | 1344 |  | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1345 | // Decodes the header section from the class data bytes. | 
 | 1346 | void ClassDataItemIterator::ReadClassDataHeader() { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 1347 |   CHECK(ptr_pos_ != nullptr); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1348 |   header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_); | 
 | 1349 |   header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_); | 
 | 1350 |   header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_); | 
 | 1351 |   header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_); | 
 | 1352 | } | 
 | 1353 |  | 
 | 1354 | void ClassDataItemIterator::ReadClassDataField() { | 
 | 1355 |   field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_); | 
 | 1356 |   field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_); | 
| Vladimir Marko | 23682bf | 2015-06-24 14:28:03 +0100 | [diff] [blame] | 1357 |   // The user of the iterator is responsible for checking if there | 
 | 1358 |   // are unordered or duplicate indexes. | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1359 | } | 
 | 1360 |  | 
 | 1361 | void ClassDataItemIterator::ReadClassDataMethod() { | 
 | 1362 |   method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_); | 
 | 1363 |   method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_); | 
 | 1364 |   method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_); | 
| Brian Carlstrom | 68adbe4 | 2012-05-11 17:18:08 -0700 | [diff] [blame] | 1365 |   if (last_idx_ != 0 && method_.method_idx_delta_ == 0) { | 
| Andreas Gampe | 4fdbba0 | 2014-06-19 20:24:22 -0700 | [diff] [blame] | 1366 |     LOG(WARNING) << "Duplicate method in " << dex_file_.GetLocation(); | 
| Brian Carlstrom | 6f29d0e | 2012-05-11 15:50:29 -0700 | [diff] [blame] | 1367 |   } | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1368 | } | 
 | 1369 |  | 
| Orion Hodson | 12f4ff4 | 2017-01-13 16:43:12 +0000 | [diff] [blame^] | 1370 | EncodedArrayValueIterator::EncodedArrayValueIterator(const DexFile& dex_file, | 
 | 1371 |                                                      const uint8_t* array_data) | 
| Shinichiro Hamaji | 82863f0 | 2015-11-05 16:51:33 +0900 | [diff] [blame] | 1372 |     : dex_file_(dex_file), | 
| Shinichiro Hamaji | 82863f0 | 2015-11-05 16:51:33 +0900 | [diff] [blame] | 1373 |       array_size_(), | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1374 |       pos_(-1), | 
| Orion Hodson | 12f4ff4 | 2017-01-13 16:43:12 +0000 | [diff] [blame^] | 1375 |       ptr_(array_data), | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1376 |       type_(kByte) { | 
| Orion Hodson | 12f4ff4 | 2017-01-13 16:43:12 +0000 | [diff] [blame^] | 1377 |   array_size_ = (ptr_ != nullptr) ? DecodeUnsignedLeb128(&ptr_) : 0; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1378 |   if (array_size_ > 0) { | 
 | 1379 |     Next(); | 
 | 1380 |   } | 
 | 1381 | } | 
 | 1382 |  | 
| Orion Hodson | 12f4ff4 | 2017-01-13 16:43:12 +0000 | [diff] [blame^] | 1383 | void EncodedArrayValueIterator::Next() { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1384 |   pos_++; | 
 | 1385 |   if (pos_ >= array_size_) { | 
 | 1386 |     return; | 
 | 1387 |   } | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 1388 |   uint8_t value_type = *ptr_++; | 
 | 1389 |   uint8_t value_arg = value_type >> kEncodedValueArgShift; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1390 |   size_t width = value_arg + 1;  // assume and correct later | 
| Brian Carlstrom | 88f3654 | 2012-10-16 23:24:21 -0700 | [diff] [blame] | 1391 |   type_ = static_cast<ValueType>(value_type & kEncodedValueTypeMask); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1392 |   switch (type_) { | 
 | 1393 |   case kBoolean: | 
 | 1394 |     jval_.i = (value_arg != 0) ? 1 : 0; | 
 | 1395 |     width = 0; | 
 | 1396 |     break; | 
 | 1397 |   case kByte: | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1398 |     jval_.i = DexFile::ReadSignedInt(ptr_, value_arg); | 
| Andreas Gampe | ab1eb0d | 2015-02-13 19:23:55 -0800 | [diff] [blame] | 1399 |     CHECK(IsInt<8>(jval_.i)); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1400 |     break; | 
 | 1401 |   case kShort: | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1402 |     jval_.i = DexFile::ReadSignedInt(ptr_, value_arg); | 
| Andreas Gampe | ab1eb0d | 2015-02-13 19:23:55 -0800 | [diff] [blame] | 1403 |     CHECK(IsInt<16>(jval_.i)); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1404 |     break; | 
 | 1405 |   case kChar: | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1406 |     jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false); | 
| Andreas Gampe | ab1eb0d | 2015-02-13 19:23:55 -0800 | [diff] [blame] | 1407 |     CHECK(IsUint<16>(jval_.i)); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1408 |     break; | 
 | 1409 |   case kInt: | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1410 |     jval_.i = DexFile::ReadSignedInt(ptr_, value_arg); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1411 |     break; | 
 | 1412 |   case kLong: | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1413 |     jval_.j = DexFile::ReadSignedLong(ptr_, value_arg); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1414 |     break; | 
 | 1415 |   case kFloat: | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1416 |     jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, true); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1417 |     break; | 
 | 1418 |   case kDouble: | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1419 |     jval_.j = DexFile::ReadUnsignedLong(ptr_, value_arg, true); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1420 |     break; | 
 | 1421 |   case kString: | 
 | 1422 |   case kType: | 
| Orion Hodson | 12f4ff4 | 2017-01-13 16:43:12 +0000 | [diff] [blame^] | 1423 |   case kMethodType: | 
 | 1424 |   case kMethodHandle: | 
| David Sehr | 9323e6e | 2016-09-13 08:58:35 -0700 | [diff] [blame] | 1425 |     jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1426 |     break; | 
 | 1427 |   case kField: | 
| Brian Carlstrom | 88f3654 | 2012-10-16 23:24:21 -0700 | [diff] [blame] | 1428 |   case kMethod: | 
 | 1429 |   case kEnum: | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1430 |   case kArray: | 
 | 1431 |   case kAnnotation: | 
 | 1432 |     UNIMPLEMENTED(FATAL) << ": type " << type_; | 
| Ian Rogers | 2c4257b | 2014-10-24 14:20:06 -0700 | [diff] [blame] | 1433 |     UNREACHABLE(); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1434 |   case kNull: | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 1435 |     jval_.l = nullptr; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1436 |     width = 0; | 
 | 1437 |     break; | 
 | 1438 |   default: | 
 | 1439 |     LOG(FATAL) << "Unreached"; | 
| Ian Rogers | 2c4257b | 2014-10-24 14:20:06 -0700 | [diff] [blame] | 1440 |     UNREACHABLE(); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1441 |   } | 
 | 1442 |   ptr_ += width; | 
 | 1443 | } | 
 | 1444 |  | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1445 | CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) { | 
 | 1446 |   handler_.address_ = -1; | 
 | 1447 |   int32_t offset = -1; | 
 | 1448 |  | 
 | 1449 |   // Short-circuit the overwhelmingly common cases. | 
 | 1450 |   switch (code_item.tries_size_) { | 
 | 1451 |     case 0: | 
 | 1452 |       break; | 
 | 1453 |     case 1: { | 
 | 1454 |       const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0); | 
 | 1455 |       uint32_t start = tries->start_addr_; | 
 | 1456 |       if (address >= start) { | 
 | 1457 |         uint32_t end = start + tries->insn_count_; | 
 | 1458 |         if (address < end) { | 
 | 1459 |           offset = tries->handler_off_; | 
 | 1460 |         } | 
 | 1461 |       } | 
 | 1462 |       break; | 
 | 1463 |     } | 
 | 1464 |     default: | 
| Ian Rogers | dbbc99d | 2013-04-18 16:51:54 -0700 | [diff] [blame] | 1465 |       offset = DexFile::FindCatchHandlerOffset(code_item, address); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1466 |   } | 
| Logan Chien | 736df02 | 2012-04-27 16:25:57 +0800 | [diff] [blame] | 1467 |   Init(code_item, offset); | 
 | 1468 | } | 
 | 1469 |  | 
 | 1470 | CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, | 
 | 1471 |                                            const DexFile::TryItem& try_item) { | 
 | 1472 |   handler_.address_ = -1; | 
 | 1473 |   Init(code_item, try_item.handler_off_); | 
 | 1474 | } | 
 | 1475 |  | 
 | 1476 | void CatchHandlerIterator::Init(const DexFile::CodeItem& code_item, | 
 | 1477 |                                 int32_t offset) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1478 |   if (offset >= 0) { | 
| Logan Chien | 736df02 | 2012-04-27 16:25:57 +0800 | [diff] [blame] | 1479 |     Init(DexFile::GetCatchHandlerData(code_item, offset)); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1480 |   } else { | 
 | 1481 |     // Not found, initialize as empty | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 1482 |     current_data_ = nullptr; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1483 |     remaining_count_ = -1; | 
 | 1484 |     catch_all_ = false; | 
 | 1485 |     DCHECK(!HasNext()); | 
 | 1486 |   } | 
 | 1487 | } | 
 | 1488 |  | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 1489 | void CatchHandlerIterator::Init(const uint8_t* handler_data) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1490 |   current_data_ = handler_data; | 
 | 1491 |   remaining_count_ = DecodeSignedLeb128(¤t_data_); | 
 | 1492 |  | 
 | 1493 |   // If remaining_count_ is non-positive, then it is the negative of | 
 | 1494 |   // the number of catch types, and the catches are followed by a | 
 | 1495 |   // catch-all handler. | 
 | 1496 |   if (remaining_count_ <= 0) { | 
 | 1497 |     catch_all_ = true; | 
 | 1498 |     remaining_count_ = -remaining_count_; | 
 | 1499 |   } else { | 
 | 1500 |     catch_all_ = false; | 
 | 1501 |   } | 
 | 1502 |   Next(); | 
 | 1503 | } | 
 | 1504 |  | 
 | 1505 | void CatchHandlerIterator::Next() { | 
 | 1506 |   if (remaining_count_ > 0) { | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 1507 |     handler_.type_idx_ = dex::TypeIndex(DecodeUnsignedLeb128(¤t_data_)); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1508 |     handler_.address_  = DecodeUnsignedLeb128(¤t_data_); | 
 | 1509 |     remaining_count_--; | 
 | 1510 |     return; | 
 | 1511 |   } | 
 | 1512 |  | 
 | 1513 |   if (catch_all_) { | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 1514 |     handler_.type_idx_ = dex::TypeIndex(DexFile::kDexNoIndex16); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1515 |     handler_.address_  = DecodeUnsignedLeb128(¤t_data_); | 
 | 1516 |     catch_all_ = false; | 
 | 1517 |     return; | 
 | 1518 |   } | 
 | 1519 |  | 
 | 1520 |   // no more handler | 
 | 1521 |   remaining_count_ = -1; | 
 | 1522 | } | 
 | 1523 |  | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 1524 | namespace dex { | 
 | 1525 |  | 
| Andreas Gampe | 8a0128a | 2016-11-28 07:38:35 -0800 | [diff] [blame] | 1526 | std::ostream& operator<<(std::ostream& os, const StringIndex& index) { | 
 | 1527 |   os << "StringIndex[" << index.index_ << "]"; | 
 | 1528 |   return os; | 
 | 1529 | } | 
 | 1530 |  | 
| Andreas Gampe | a5b09a6 | 2016-11-17 15:21:22 -0800 | [diff] [blame] | 1531 | std::ostream& operator<<(std::ostream& os, const TypeIndex& index) { | 
 | 1532 |   os << "TypeIndex[" << index.index_ << "]"; | 
 | 1533 |   return os; | 
 | 1534 | } | 
 | 1535 |  | 
 | 1536 | }  // namespace dex | 
 | 1537 |  | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 1538 | }  // namespace art |