| 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> | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 26 |  | 
| Elliott Hughes | 07ed66b | 2012-12-12 18:34:25 -0800 | [diff] [blame] | 27 | #include "base/logging.h" | 
| Elliott Hughes | e222ee0 | 2012-12-13 14:41:43 -0800 | [diff] [blame] | 28 | #include "base/stringprintf.h" | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 29 | #include "class_linker.h" | 
| jeffhao | 10037c8 | 2012-01-23 15:06:23 -0800 | [diff] [blame] | 30 | #include "dex_file_verifier.h" | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 31 | #include "globals.h" | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 32 | #include "leb128.h" | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame^] | 33 | #include "mirror/abstract_method-inl.h" | 
|  | 34 | #include "mirror/field.h" | 
|  | 35 | #include "mirror/field-inl.h" | 
|  | 36 | #include "mirror/string.h" | 
| Brian Carlstrom | db4d540 | 2011-08-09 12:18:28 -0700 | [diff] [blame] | 37 | #include "os.h" | 
| Elliott Hughes | a0e1806 | 2012-04-13 15:59:59 -0700 | [diff] [blame] | 38 | #include "safe_map.h" | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 39 | #include "thread.h" | 
| Elliott Hughes | a0e1806 | 2012-04-13 15:59:59 -0700 | [diff] [blame] | 40 | #include "UniquePtr.h" | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 41 | #include "utf.h" | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 42 | #include "utils.h" | 
| Elliott Hughes | eac7667 | 2012-05-24 21:56:51 -0700 | [diff] [blame] | 43 | #include "well_known_classes.h" | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 44 | #include "zip_archive.h" | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 45 |  | 
|  | 46 | namespace art { | 
|  | 47 |  | 
| Brian Carlstrom | f615a61 | 2011-07-23 12:50:34 -0700 | [diff] [blame] | 48 | const byte DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' }; | 
|  | 49 | const byte DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' }; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 50 |  | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 51 | DexFile::ClassPathEntry DexFile::FindInClassPath(const StringPiece& descriptor, | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 52 | const ClassPath& class_path) { | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 53 | for (size_t i = 0; i != class_path.size(); ++i) { | 
|  | 54 | const DexFile* dex_file = class_path[i]; | 
|  | 55 | const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor); | 
|  | 56 | if (dex_class_def != NULL) { | 
|  | 57 | return ClassPathEntry(dex_file, dex_class_def); | 
|  | 58 | } | 
|  | 59 | } | 
| Brian Carlstrom | 4a289ed | 2011-08-16 17:17:49 -0700 | [diff] [blame] | 60 | // TODO: remove reinterpret_cast when issue with -std=gnu++0x host issue resolved | 
| Brian Carlstrom | 7e93b50 | 2011-08-04 14:16:22 -0700 | [diff] [blame] | 61 | return ClassPathEntry(reinterpret_cast<const DexFile*>(NULL), | 
|  | 62 | reinterpret_cast<const DexFile::ClassDef*>(NULL)); | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 63 | } | 
|  | 64 |  | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 65 | bool DexFile::GetChecksum(const std::string& filename, uint32_t& checksum) { | 
|  | 66 | if (IsValidZipFilename(filename)) { | 
|  | 67 | UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename)); | 
|  | 68 | if (zip_archive.get() == NULL) { | 
|  | 69 | return false; | 
| Brian Carlstrom | 78128a6 | 2011-09-15 17:21:19 -0700 | [diff] [blame] | 70 | } | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 71 | UniquePtr<ZipEntry> zip_entry(zip_archive->Find(kClassesDex)); | 
|  | 72 | if (zip_entry.get() == NULL) { | 
|  | 73 | return false; | 
|  | 74 | } | 
|  | 75 | checksum = zip_entry->GetCrc32(); | 
|  | 76 | return true; | 
| Brian Carlstrom | 78128a6 | 2011-09-15 17:21:19 -0700 | [diff] [blame] | 77 | } | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 78 | if (IsValidDexFilename(filename)) { | 
| Brian Carlstrom | 1db858a | 2012-03-11 22:44:45 -0700 | [diff] [blame] | 79 | UniquePtr<const DexFile> dex_file(DexFile::OpenFile(filename, filename, false)); | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 80 | if (dex_file.get() == NULL) { | 
|  | 81 | return false; | 
|  | 82 | } | 
|  | 83 | checksum = dex_file->GetHeader().checksum_; | 
|  | 84 | return true; | 
|  | 85 | } | 
|  | 86 | return false; | 
| Brian Carlstrom | 78128a6 | 2011-09-15 17:21:19 -0700 | [diff] [blame] | 87 | } | 
|  | 88 |  | 
| Brian Carlstrom | 1619286 | 2011-09-12 17:50:06 -0700 | [diff] [blame] | 89 | const DexFile* DexFile::Open(const std::string& filename, | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 90 | const std::string& location) { | 
| jeffhao | 262bf46 | 2011-10-20 18:36:32 -0700 | [diff] [blame] | 91 | if (IsValidZipFilename(filename)) { | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 92 | return DexFile::OpenZip(filename, location); | 
| Brian Carlstrom | 69b15fb | 2011-09-03 12:25:21 -0700 | [diff] [blame] | 93 | } | 
| Brian Carlstrom | 0dd7dda | 2011-10-25 15:47:53 -0700 | [diff] [blame] | 94 | if (!IsValidDexFilename(filename)) { | 
|  | 95 | LOG(WARNING) << "Attempting to open dex file with unknown extension '" << filename << "'"; | 
|  | 96 | } | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 97 | return DexFile::OpenFile(filename, location, true); | 
| Brian Carlstrom | 69b15fb | 2011-09-03 12:25:21 -0700 | [diff] [blame] | 98 | } | 
|  | 99 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame^] | 100 | int DexFile::GetPermissions() const { | 
|  | 101 | if (mem_map_.get() == NULL) { | 
|  | 102 | return 0; | 
|  | 103 | } else { | 
|  | 104 | return mem_map_->GetProtect(); | 
|  | 105 | } | 
|  | 106 | } | 
|  | 107 |  | 
| Brian Carlstrom | 1619286 | 2011-09-12 17:50:06 -0700 | [diff] [blame] | 108 | const DexFile* DexFile::OpenFile(const std::string& filename, | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 109 | const std::string& location, | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 110 | bool verify) { | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 111 | CHECK(!location.empty()) << filename; | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 112 | int fd = open(filename.c_str(), O_RDONLY);  // TODO: scoped_fd | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 113 | if (fd == -1) { | 
|  | 114 | PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed"; | 
|  | 115 | return NULL; | 
|  | 116 | } | 
|  | 117 | struct stat sbuf; | 
|  | 118 | memset(&sbuf, 0, sizeof(sbuf)); | 
|  | 119 | if (fstat(fd, &sbuf) == -1) { | 
|  | 120 | PLOG(ERROR) << "fstat \"" << filename << "\" failed"; | 
|  | 121 | close(fd); | 
|  | 122 | return NULL; | 
|  | 123 | } | 
| Ian Rogers | 7cfb93e | 2012-01-17 19:46:36 -0800 | [diff] [blame] | 124 | if (S_ISDIR(sbuf.st_mode)) { | 
|  | 125 | LOG(ERROR) << "attempt to mmap directory \"" << filename << "\""; | 
|  | 126 | return NULL; | 
|  | 127 | } | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 128 | size_t length = sbuf.st_size; | 
| Brian Carlstrom | 8952189 | 2011-12-07 22:05:07 -0800 | [diff] [blame] | 129 | UniquePtr<MemMap> map(MemMap::MapFile(length, PROT_READ, MAP_PRIVATE, fd, 0)); | 
| Brian Carlstrom | 33f741e | 2011-10-03 11:24:05 -0700 | [diff] [blame] | 130 | if (map.get() == NULL) { | 
|  | 131 | LOG(ERROR) << "mmap \"" << filename << "\" failed"; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 132 | close(fd); | 
|  | 133 | return NULL; | 
|  | 134 | } | 
|  | 135 | close(fd); | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 136 |  | 
|  | 137 | if (map->Size() < sizeof(DexFile::Header)) { | 
|  | 138 | LOG(ERROR) << "Failed to open dex file '" << filename << "' that is too short to have a header"; | 
|  | 139 | return NULL; | 
|  | 140 | } | 
|  | 141 |  | 
|  | 142 | const Header* dex_header = reinterpret_cast<const Header*>(map->Begin()); | 
|  | 143 |  | 
|  | 144 | const DexFile* dex_file = OpenMemory(location, dex_header->checksum_, map.release()); | 
| jeffhao | 54c1ceb | 2012-02-01 11:45:32 -0800 | [diff] [blame] | 145 | if (dex_file == NULL) { | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 146 | LOG(ERROR) << "Failed to open dex file '" << filename << "' from memory"; | 
| jeffhao | 54c1ceb | 2012-02-01 11:45:32 -0800 | [diff] [blame] | 147 | return NULL; | 
| jeffhao | f6174e8 | 2012-01-31 16:14:17 -0800 | [diff] [blame] | 148 | } | 
| jeffhao | 54c1ceb | 2012-02-01 11:45:32 -0800 | [diff] [blame] | 149 |  | 
| Elliott Hughes | 1bac54f | 2012-03-16 12:48:31 -0700 | [diff] [blame] | 150 | if (verify && !DexFileVerifier::Verify(dex_file, dex_file->Begin(), dex_file->Size())) { | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 151 | LOG(ERROR) << "Failed to verify dex file '" << filename << "'"; | 
| jeffhao | 54c1ceb | 2012-02-01 11:45:32 -0800 | [diff] [blame] | 152 | return NULL; | 
|  | 153 | } | 
|  | 154 |  | 
| jeffhao | f6174e8 | 2012-01-31 16:14:17 -0800 | [diff] [blame] | 155 | return dex_file; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 156 | } | 
|  | 157 |  | 
| Brian Carlstrom | b7bbba4 | 2011-10-13 14:58:47 -0700 | [diff] [blame] | 158 | const char* DexFile::kClassesDex = "classes.dex"; | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 159 |  | 
| Brian Carlstrom | 1619286 | 2011-09-12 17:50:06 -0700 | [diff] [blame] | 160 | const DexFile* DexFile::OpenZip(const std::string& filename, | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 161 | const std::string& location) { | 
| Elliott Hughes | 90a3369 | 2011-08-30 13:27:07 -0700 | [diff] [blame] | 162 | UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(filename)); | 
|  | 163 | if (zip_archive.get() == NULL) { | 
| Brian Carlstrom | 1619286 | 2011-09-12 17:50:06 -0700 | [diff] [blame] | 164 | LOG(ERROR) << "Failed to open " << filename << " when looking for classes.dex"; | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 165 | return NULL; | 
|  | 166 | } | 
| Brian Carlstrom | a6cc893 | 2012-01-04 14:44:07 -0800 | [diff] [blame] | 167 | return DexFile::Open(*zip_archive.get(), location); | 
|  | 168 | } | 
|  | 169 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame^] | 170 | const DexFile* DexFile::OpenMemory(const std::string& location, | 
|  | 171 | uint32_t location_checksum, | 
|  | 172 | MemMap* mem_map) { | 
|  | 173 | return OpenMemory(mem_map->Begin(), | 
|  | 174 | mem_map->Size(), | 
|  | 175 | location, | 
|  | 176 | location_checksum, | 
|  | 177 | mem_map); | 
|  | 178 | } | 
|  | 179 |  | 
| Brian Carlstrom | a6cc893 | 2012-01-04 14:44:07 -0800 | [diff] [blame] | 180 | const DexFile* DexFile::Open(const ZipArchive& zip_archive, const std::string& location) { | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 181 | CHECK(!location.empty()); | 
| Brian Carlstrom | a6cc893 | 2012-01-04 14:44:07 -0800 | [diff] [blame] | 182 | UniquePtr<ZipEntry> zip_entry(zip_archive.Find(kClassesDex)); | 
| Elliott Hughes | 90a3369 | 2011-08-30 13:27:07 -0700 | [diff] [blame] | 183 | if (zip_entry.get() == NULL) { | 
| Brian Carlstrom | a6cc893 | 2012-01-04 14:44:07 -0800 | [diff] [blame] | 184 | LOG(ERROR) << "Failed to find classes.dex within " << location; | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 185 | return NULL; | 
|  | 186 | } | 
|  | 187 |  | 
| Brian Carlstrom | 8952189 | 2011-12-07 22:05:07 -0800 | [diff] [blame] | 188 | uint32_t length = zip_entry->GetUncompressedLength(); | 
| Elliott Hughes | 850162c | 2012-01-12 18:46:43 -0800 | [diff] [blame] | 189 | std::string name("classes.dex extracted in memory from "); | 
|  | 190 | name += location; | 
|  | 191 | UniquePtr<MemMap> map(MemMap::MapAnonymous(name.c_str(), NULL, length, PROT_READ | PROT_WRITE)); | 
| Brian Carlstrom | 8952189 | 2011-12-07 22:05:07 -0800 | [diff] [blame] | 192 | if (map.get() == NULL) { | 
| Brian Carlstrom | a6cc893 | 2012-01-04 14:44:07 -0800 | [diff] [blame] | 193 | LOG(ERROR) << "mmap classes.dex for \"" << location << "\" failed"; | 
| Brian Carlstrom | 8952189 | 2011-12-07 22:05:07 -0800 | [diff] [blame] | 194 | return NULL; | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 195 | } | 
| Brian Carlstrom | 8952189 | 2011-12-07 22:05:07 -0800 | [diff] [blame] | 196 |  | 
|  | 197 | // Extract classes.dex | 
|  | 198 | bool success = zip_entry->ExtractToMemory(*map.get()); | 
|  | 199 | if (!success) { | 
| Brian Carlstrom | a6cc893 | 2012-01-04 14:44:07 -0800 | [diff] [blame] | 200 | LOG(ERROR) << "Failed to extract classes.dex from '" << location << "' to memory"; | 
| Brian Carlstrom | 8952189 | 2011-12-07 22:05:07 -0800 | [diff] [blame] | 201 | return NULL; | 
|  | 202 | } | 
|  | 203 |  | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 204 | const DexFile* dex_file = OpenMemory(location, zip_entry->GetCrc32(), map.release()); | 
| jeffhao | 54c1ceb | 2012-02-01 11:45:32 -0800 | [diff] [blame] | 205 | if (dex_file == NULL) { | 
|  | 206 | LOG(ERROR) << "Failed to open dex file '" << location << "' from memory"; | 
|  | 207 | return NULL; | 
| jeffhao | f6174e8 | 2012-01-31 16:14:17 -0800 | [diff] [blame] | 208 | } | 
| jeffhao | 54c1ceb | 2012-02-01 11:45:32 -0800 | [diff] [blame] | 209 |  | 
|  | 210 | if (!DexFileVerifier::Verify(dex_file, dex_file->Begin(), dex_file->Size())) { | 
|  | 211 | LOG(ERROR) << "Failed to verify dex file '" << location << "'"; | 
|  | 212 | return NULL; | 
|  | 213 | } | 
|  | 214 |  | 
| jeffhao | f6174e8 | 2012-01-31 16:14:17 -0800 | [diff] [blame] | 215 | return dex_file; | 
| Brian Carlstrom | b0460ea | 2011-07-29 10:08:05 -0700 | [diff] [blame] | 216 | } | 
|  | 217 |  | 
| Brian Carlstrom | 8952189 | 2011-12-07 22:05:07 -0800 | [diff] [blame] | 218 | const DexFile* DexFile::OpenMemory(const byte* base, | 
| jeffhao | f6174e8 | 2012-01-31 16:14:17 -0800 | [diff] [blame] | 219 | size_t size, | 
| Brian Carlstrom | 8952189 | 2011-12-07 22:05:07 -0800 | [diff] [blame] | 220 | const std::string& location, | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 221 | uint32_t location_checksum, | 
| Brian Carlstrom | 8952189 | 2011-12-07 22:05:07 -0800 | [diff] [blame] | 222 | MemMap* mem_map) { | 
|  | 223 | CHECK_ALIGNED(base, 4); // various dex file structures must be word aligned | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 224 | UniquePtr<DexFile> dex_file(new DexFile(base, size, location, location_checksum, mem_map)); | 
| Brian Carlstrom | f615a61 | 2011-07-23 12:50:34 -0700 | [diff] [blame] | 225 | if (!dex_file->Init()) { | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 226 | return NULL; | 
|  | 227 | } else { | 
| Brian Carlstrom | f615a61 | 2011-07-23 12:50:34 -0700 | [diff] [blame] | 228 | return dex_file.release(); | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 229 | } | 
|  | 230 | } | 
|  | 231 |  | 
| Jesse Wilson | 6bf1915 | 2011-09-29 13:12:33 -0400 | [diff] [blame] | 232 | DexFile::~DexFile() { | 
| Elliott Hughes | 8cef0b8 | 2011-10-11 19:24:00 -0700 | [diff] [blame] | 233 | // We don't call DeleteGlobalRef on dex_object_ because we're only called by DestroyJavaVM, and | 
|  | 234 | // that's only called after DetachCurrentThread, which means there's no JNIEnv. We could | 
|  | 235 | // re-attach, but cleaning up these global references is not obviously useful. It's not as if | 
|  | 236 | // the global reference table is otherwise empty! | 
| Jesse Wilson | 6bf1915 | 2011-09-29 13:12:33 -0400 | [diff] [blame] | 237 | } | 
|  | 238 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 239 | class ScopedJniMonitorLock { | 
|  | 240 | public: | 
|  | 241 | ScopedJniMonitorLock(JNIEnv* env, jobject locked) : env_(env), locked_(locked){ | 
|  | 242 | env->MonitorEnter(locked_); | 
| Jesse Wilson | 6bf1915 | 2011-09-29 13:12:33 -0400 | [diff] [blame] | 243 | } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 244 | ~ScopedJniMonitorLock() { | 
|  | 245 | env_->MonitorExit(locked_); | 
|  | 246 | } | 
|  | 247 | private: | 
|  | 248 | JNIEnv* const env_; | 
|  | 249 | const jobject locked_; | 
|  | 250 | }; | 
| Jesse Wilson | 6bf1915 | 2011-09-29 13:12:33 -0400 | [diff] [blame] | 251 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 252 | jobject DexFile::GetDexObject(JNIEnv* env) const { | 
|  | 253 | { | 
|  | 254 | ScopedJniMonitorLock lock(env, WellKnownClasses::com_android_dex_Dex); | 
|  | 255 | if (dex_object_ != NULL) { | 
|  | 256 | return dex_object_; | 
|  | 257 | } | 
|  | 258 | } | 
| Ian Rogers | 30fab40 | 2012-01-23 15:43:46 -0800 | [diff] [blame] | 259 | void* address = const_cast<void*>(reinterpret_cast<const void*>(begin_)); | 
| jeffhao | f6174e8 | 2012-01-31 16:14:17 -0800 | [diff] [blame] | 260 | jobject byte_buffer = env->NewDirectByteBuffer(address, size_); | 
| Jesse Wilson | 6bf1915 | 2011-09-29 13:12:33 -0400 | [diff] [blame] | 261 | if (byte_buffer == NULL) { | 
|  | 262 | return NULL; | 
|  | 263 | } | 
|  | 264 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 265 | ScopedJniMonitorLock lock(env, WellKnownClasses::com_android_dex_Dex); | 
|  | 266 | // Re-test to see if someone beat us to the creation when we had the lock released. | 
|  | 267 | if (dex_object_ != NULL) { | 
|  | 268 | return dex_object_; | 
|  | 269 | } | 
| Jesse Wilson | 6bf1915 | 2011-09-29 13:12:33 -0400 | [diff] [blame] | 270 | jvalue args[1]; | 
|  | 271 | args[0].l = byte_buffer; | 
| Elliott Hughes | eac7667 | 2012-05-24 21:56:51 -0700 | [diff] [blame] | 272 | jobject local = env->CallStaticObjectMethodA(WellKnownClasses::com_android_dex_Dex, | 
|  | 273 | WellKnownClasses::com_android_dex_Dex_create, | 
|  | 274 | args); | 
| Jesse Wilson | 6bf1915 | 2011-09-29 13:12:33 -0400 | [diff] [blame] | 275 | if (local == NULL) { | 
|  | 276 | return NULL; | 
|  | 277 | } | 
|  | 278 |  | 
|  | 279 | dex_object_ = env->NewGlobalRef(local); | 
|  | 280 | return dex_object_; | 
|  | 281 | } | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 282 |  | 
| Brian Carlstrom | f615a61 | 2011-07-23 12:50:34 -0700 | [diff] [blame] | 283 | bool DexFile::Init() { | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 284 | InitMembers(); | 
| Brian Carlstrom | 6e3b1d9 | 2012-01-11 01:36:32 -0800 | [diff] [blame] | 285 | if (!CheckMagicAndVersion()) { | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 286 | return false; | 
|  | 287 | } | 
|  | 288 | InitIndex(); | 
|  | 289 | return true; | 
|  | 290 | } | 
|  | 291 |  | 
| Brian Carlstrom | f615a61 | 2011-07-23 12:50:34 -0700 | [diff] [blame] | 292 | void DexFile::InitMembers() { | 
| Ian Rogers | 30fab40 | 2012-01-23 15:43:46 -0800 | [diff] [blame] | 293 | const byte* b = begin_; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 294 | header_ = reinterpret_cast<const Header*>(b); | 
|  | 295 | const Header* h = header_; | 
|  | 296 | string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_); | 
|  | 297 | type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_); | 
|  | 298 | field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_); | 
|  | 299 | method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_); | 
|  | 300 | proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_); | 
|  | 301 | class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_); | 
| jeffhao | f6174e8 | 2012-01-31 16:14:17 -0800 | [diff] [blame] | 302 | DCHECK_EQ(size_, header_->file_size_); | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 303 | } | 
|  | 304 |  | 
| jeffhao | 10037c8 | 2012-01-23 15:06:23 -0800 | [diff] [blame] | 305 | bool DexFile::CheckMagicAndVersion() const { | 
| Brian Carlstrom | 6e3b1d9 | 2012-01-11 01:36:32 -0800 | [diff] [blame] | 306 | CHECK(header_->magic_ != NULL) << GetLocation(); | 
|  | 307 | if (!IsMagicValid(header_->magic_)) { | 
| Brian Carlstrom | 2aab947 | 2011-12-12 15:21:43 -0800 | [diff] [blame] | 308 | LOG(ERROR) << "Unrecognized magic number in "  << GetLocation() << ":" | 
| Brian Carlstrom | 6e3b1d9 | 2012-01-11 01:36:32 -0800 | [diff] [blame] | 309 | << " " << header_->magic_[0] | 
|  | 310 | << " " << header_->magic_[1] | 
|  | 311 | << " " << header_->magic_[2] | 
|  | 312 | << " " << header_->magic_[3]; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 313 | return false; | 
|  | 314 | } | 
| Brian Carlstrom | 6e3b1d9 | 2012-01-11 01:36:32 -0800 | [diff] [blame] | 315 | if (!IsVersionValid(header_->magic_)) { | 
| Brian Carlstrom | 2aab947 | 2011-12-12 15:21:43 -0800 | [diff] [blame] | 316 | LOG(ERROR) << "Unrecognized version number in "  << GetLocation() << ":" | 
| Brian Carlstrom | 6e3b1d9 | 2012-01-11 01:36:32 -0800 | [diff] [blame] | 317 | << " " << header_->magic_[4] | 
|  | 318 | << " " << header_->magic_[5] | 
|  | 319 | << " " << header_->magic_[6] | 
|  | 320 | << " " << header_->magic_[7]; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 321 | return false; | 
|  | 322 | } | 
|  | 323 | return true; | 
|  | 324 | } | 
|  | 325 |  | 
| Brian Carlstrom | 6e3b1d9 | 2012-01-11 01:36:32 -0800 | [diff] [blame] | 326 | bool DexFile::IsMagicValid(const byte* magic) { | 
|  | 327 | return (memcmp(magic, kDexMagic, sizeof(kDexMagic)) == 0); | 
|  | 328 | } | 
|  | 329 |  | 
|  | 330 | bool DexFile::IsVersionValid(const byte* magic) { | 
|  | 331 | const byte* version = &magic[sizeof(kDexMagic)]; | 
|  | 332 | return (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) == 0); | 
|  | 333 | } | 
|  | 334 |  | 
| Ian Rogers | d81871c | 2011-10-03 13:57:23 -0700 | [diff] [blame] | 335 | uint32_t DexFile::GetVersion() const { | 
|  | 336 | const char* version = reinterpret_cast<const char*>(&GetHeader().magic_[sizeof(kDexMagic)]); | 
|  | 337 | return atoi(version); | 
|  | 338 | } | 
|  | 339 |  | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 340 | int32_t DexFile::GetStringLength(const StringId& string_id) const { | 
| Ian Rogers | 30fab40 | 2012-01-23 15:43:46 -0800 | [diff] [blame] | 341 | const byte* ptr = begin_ + string_id.string_data_off_; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 342 | return DecodeUnsignedLeb128(&ptr); | 
|  | 343 | } | 
|  | 344 |  | 
|  | 345 | // Returns a pointer to the UTF-8 string data referred to by the given string_id. | 
| Elliott Hughes | 45651fd | 2012-02-21 15:48:20 -0800 | [diff] [blame] | 346 | const char* DexFile::GetStringDataAndLength(const StringId& string_id, uint32_t* length) const { | 
| Ian Rogers | 7b0c5b4 | 2012-02-16 15:29:07 -0800 | [diff] [blame] | 347 | DCHECK(length != NULL) << GetLocation(); | 
| Ian Rogers | 30fab40 | 2012-01-23 15:43:46 -0800 | [diff] [blame] | 348 | const byte* ptr = begin_ + string_id.string_data_off_; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 349 | *length = DecodeUnsignedLeb128(&ptr); | 
|  | 350 | return reinterpret_cast<const char*>(ptr); | 
|  | 351 | } | 
|  | 352 |  | 
| Brian Carlstrom | f615a61 | 2011-07-23 12:50:34 -0700 | [diff] [blame] | 353 | void DexFile::InitIndex() { | 
| Brian Carlstrom | 61e513c | 2011-12-09 15:30:06 -0800 | [diff] [blame] | 354 | CHECK_EQ(index_.size(), 0U) << GetLocation(); | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 355 | for (size_t i = 0; i < NumClassDefs(); ++i) { | 
|  | 356 | const ClassDef& class_def = GetClassDef(i); | 
|  | 357 | const char* descriptor = GetClassDescriptor(class_def); | 
| Elliott Hughes | a0e1806 | 2012-04-13 15:59:59 -0700 | [diff] [blame] | 358 | index_.Put(descriptor, i); | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 359 | } | 
|  | 360 | } | 
|  | 361 |  | 
| Brian Carlstrom | e24fa61 | 2011-09-29 00:53:55 -0700 | [diff] [blame] | 362 | bool DexFile::FindClassDefIndex(const StringPiece& descriptor, uint32_t& idx) const { | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 363 | Index::const_iterator it = index_.find(descriptor); | 
|  | 364 | if (it == index_.end()) { | 
| Brian Carlstrom | e24fa61 | 2011-09-29 00:53:55 -0700 | [diff] [blame] | 365 | return false; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 366 | } | 
| Brian Carlstrom | e24fa61 | 2011-09-29 00:53:55 -0700 | [diff] [blame] | 367 | idx = it->second; | 
|  | 368 | return true; | 
|  | 369 | } | 
|  | 370 |  | 
|  | 371 | const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const { | 
|  | 372 | uint32_t idx; | 
|  | 373 | if (FindClassDefIndex(descriptor, idx)) { | 
|  | 374 | return &GetClassDef(idx); | 
|  | 375 | } | 
|  | 376 | return NULL; | 
| Brian Carlstrom | 7e49dca | 2011-07-22 18:07:34 -0700 | [diff] [blame] | 377 | } | 
|  | 378 |  | 
| Ian Rogers | 9b1a4f4 | 2011-11-14 18:35:10 -0800 | [diff] [blame] | 379 | const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass, | 
|  | 380 | const DexFile::StringId& name, | 
|  | 381 | const DexFile::TypeId& type) const { | 
|  | 382 | // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx | 
|  | 383 | const uint16_t class_idx = GetIndexForTypeId(declaring_klass); | 
|  | 384 | const uint32_t name_idx = GetIndexForStringId(name); | 
|  | 385 | const uint16_t type_idx = GetIndexForTypeId(type); | 
|  | 386 | uint32_t lo = 0; | 
|  | 387 | uint32_t hi = NumFieldIds() - 1; | 
|  | 388 | while (hi >= lo) { | 
|  | 389 | uint32_t mid = (hi + lo) / 2; | 
|  | 390 | const DexFile::FieldId& field = GetFieldId(mid); | 
|  | 391 | if (class_idx > field.class_idx_) { | 
|  | 392 | lo = mid + 1; | 
|  | 393 | } else if (class_idx < field.class_idx_) { | 
|  | 394 | hi = mid - 1; | 
|  | 395 | } else { | 
|  | 396 | if (name_idx > field.name_idx_) { | 
|  | 397 | lo = mid + 1; | 
|  | 398 | } else if (name_idx < field.name_idx_) { | 
|  | 399 | hi = mid - 1; | 
|  | 400 | } else { | 
|  | 401 | if (type_idx > field.type_idx_) { | 
|  | 402 | lo = mid + 1; | 
|  | 403 | } else if (type_idx < field.type_idx_) { | 
|  | 404 | hi = mid - 1; | 
|  | 405 | } else { | 
|  | 406 | return &field; | 
|  | 407 | } | 
|  | 408 | } | 
|  | 409 | } | 
|  | 410 | } | 
|  | 411 | return NULL; | 
|  | 412 | } | 
|  | 413 |  | 
|  | 414 | const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass, | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 415 | const DexFile::StringId& name, | 
|  | 416 | const DexFile::ProtoId& signature) const { | 
|  | 417 | // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx | 
| Ian Rogers | 9b1a4f4 | 2011-11-14 18:35:10 -0800 | [diff] [blame] | 418 | const uint16_t class_idx = GetIndexForTypeId(declaring_klass); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 419 | const uint32_t name_idx = GetIndexForStringId(name); | 
|  | 420 | const uint16_t proto_idx = GetIndexForProtoId(signature); | 
|  | 421 | uint32_t lo = 0; | 
|  | 422 | uint32_t hi = NumMethodIds() - 1; | 
|  | 423 | while (hi >= lo) { | 
|  | 424 | uint32_t mid = (hi + lo) / 2; | 
|  | 425 | const DexFile::MethodId& method = GetMethodId(mid); | 
|  | 426 | if (class_idx > method.class_idx_) { | 
|  | 427 | lo = mid + 1; | 
|  | 428 | } else if (class_idx < method.class_idx_) { | 
|  | 429 | hi = mid - 1; | 
|  | 430 | } else { | 
|  | 431 | if (name_idx > method.name_idx_) { | 
|  | 432 | lo = mid + 1; | 
|  | 433 | } else if (name_idx < method.name_idx_) { | 
|  | 434 | hi = mid - 1; | 
|  | 435 | } else { | 
|  | 436 | if (proto_idx > method.proto_idx_) { | 
|  | 437 | lo = mid + 1; | 
|  | 438 | } else if (proto_idx < method.proto_idx_) { | 
|  | 439 | hi = mid - 1; | 
|  | 440 | } else { | 
|  | 441 | return &method; | 
|  | 442 | } | 
|  | 443 | } | 
|  | 444 | } | 
|  | 445 | } | 
|  | 446 | return NULL; | 
|  | 447 | } | 
|  | 448 |  | 
|  | 449 | const DexFile::StringId* DexFile::FindStringId(const std::string& string) const { | 
|  | 450 | uint32_t lo = 0; | 
|  | 451 | uint32_t hi = NumStringIds() - 1; | 
|  | 452 | while (hi >= lo) { | 
|  | 453 | uint32_t mid = (hi + lo) / 2; | 
| Elliott Hughes | 45651fd | 2012-02-21 15:48:20 -0800 | [diff] [blame] | 454 | uint32_t length; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 455 | const DexFile::StringId& str_id = GetStringId(mid); | 
|  | 456 | const char* str = GetStringDataAndLength(str_id, &length); | 
|  | 457 | int compare = CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(string.c_str(), str); | 
|  | 458 | if (compare > 0) { | 
|  | 459 | lo = mid + 1; | 
|  | 460 | } else if (compare < 0) { | 
|  | 461 | hi = mid - 1; | 
|  | 462 | } else { | 
|  | 463 | return &str_id; | 
|  | 464 | } | 
|  | 465 | } | 
|  | 466 | return NULL; | 
|  | 467 | } | 
|  | 468 |  | 
|  | 469 | const DexFile::TypeId* DexFile::FindTypeId(uint32_t string_idx) const { | 
|  | 470 | uint32_t lo = 0; | 
|  | 471 | uint32_t hi = NumTypeIds() - 1; | 
|  | 472 | while (hi >= lo) { | 
|  | 473 | uint32_t mid = (hi + lo) / 2; | 
|  | 474 | const TypeId& type_id = GetTypeId(mid); | 
|  | 475 | if (string_idx > type_id.descriptor_idx_) { | 
|  | 476 | lo = mid + 1; | 
|  | 477 | } else if (string_idx < type_id.descriptor_idx_) { | 
|  | 478 | hi = mid - 1; | 
|  | 479 | } else { | 
|  | 480 | return &type_id; | 
|  | 481 | } | 
|  | 482 | } | 
|  | 483 | return NULL; | 
|  | 484 | } | 
|  | 485 |  | 
|  | 486 | const DexFile::ProtoId* DexFile::FindProtoId(uint16_t return_type_idx, | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 487 | const std::vector<uint16_t>& signature_type_idxs) const { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 488 | uint32_t lo = 0; | 
|  | 489 | uint32_t hi = NumProtoIds() - 1; | 
|  | 490 | while (hi >= lo) { | 
|  | 491 | uint32_t mid = (hi + lo) / 2; | 
|  | 492 | const DexFile::ProtoId& proto = GetProtoId(mid); | 
|  | 493 | int compare = return_type_idx - proto.return_type_idx_; | 
|  | 494 | if (compare == 0) { | 
|  | 495 | DexFileParameterIterator it(*this, proto); | 
|  | 496 | size_t i = 0; | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 497 | while (it.HasNext() && i < signature_type_idxs.size() && compare == 0) { | 
|  | 498 | compare = signature_type_idxs[i] - it.GetTypeIdx(); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 499 | it.Next(); | 
|  | 500 | i++; | 
|  | 501 | } | 
|  | 502 | if (compare == 0) { | 
|  | 503 | if (it.HasNext()) { | 
|  | 504 | compare = -1; | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 505 | } else if (i < signature_type_idxs.size()) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 506 | compare = 1; | 
|  | 507 | } | 
|  | 508 | } | 
|  | 509 | } | 
|  | 510 | if (compare > 0) { | 
|  | 511 | lo = mid + 1; | 
|  | 512 | } else if (compare < 0) { | 
|  | 513 | hi = mid - 1; | 
|  | 514 | } else { | 
|  | 515 | return &proto; | 
|  | 516 | } | 
|  | 517 | } | 
|  | 518 | return NULL; | 
|  | 519 | } | 
|  | 520 |  | 
|  | 521 | // Given a signature place the type ids into the given vector | 
|  | 522 | bool DexFile::CreateTypeList(uint16_t* return_type_idx, std::vector<uint16_t>* param_type_idxs, | 
|  | 523 | const std::string& signature) const { | 
|  | 524 | if (signature[0] != '(') { | 
|  | 525 | return false; | 
|  | 526 | } | 
|  | 527 | size_t offset = 1; | 
|  | 528 | size_t end = signature.size(); | 
|  | 529 | bool process_return = false; | 
|  | 530 | while (offset < end) { | 
|  | 531 | char c = signature[offset]; | 
|  | 532 | offset++; | 
|  | 533 | if (c == ')') { | 
|  | 534 | process_return = true; | 
|  | 535 | continue; | 
|  | 536 | } | 
|  | 537 | std::string descriptor; | 
|  | 538 | descriptor += c; | 
|  | 539 | while (c == '[') {  // process array prefix | 
|  | 540 | if (offset >= end) {  // expect some descriptor following [ | 
|  | 541 | return false; | 
|  | 542 | } | 
|  | 543 | c = signature[offset]; | 
|  | 544 | offset++; | 
|  | 545 | descriptor += c; | 
|  | 546 | } | 
|  | 547 | if (c == 'L') {  // process type descriptors | 
|  | 548 | do { | 
|  | 549 | if (offset >= end) {  // unexpected early termination of descriptor | 
|  | 550 | return false; | 
|  | 551 | } | 
|  | 552 | c = signature[offset]; | 
|  | 553 | offset++; | 
|  | 554 | descriptor += c; | 
|  | 555 | } while (c != ';'); | 
|  | 556 | } | 
|  | 557 | const DexFile::StringId* string_id = FindStringId(descriptor); | 
|  | 558 | if (string_id == NULL) { | 
|  | 559 | return false; | 
|  | 560 | } | 
|  | 561 | const DexFile::TypeId* type_id = FindTypeId(GetIndexForStringId(*string_id)); | 
|  | 562 | if (type_id == NULL) { | 
|  | 563 | return false; | 
|  | 564 | } | 
|  | 565 | uint16_t type_idx = GetIndexForTypeId(*type_id); | 
|  | 566 | if (!process_return) { | 
|  | 567 | param_type_idxs->push_back(type_idx); | 
|  | 568 | } else { | 
|  | 569 | *return_type_idx = type_idx; | 
|  | 570 | return offset == end;  // return true if the signature had reached a sensible end | 
|  | 571 | } | 
|  | 572 | } | 
|  | 573 | return false;  // failed to correctly parse return type | 
|  | 574 | } | 
|  | 575 |  | 
| Carl Shapiro | 419ec7b | 2011-08-03 14:48:33 -0700 | [diff] [blame] | 576 | // Materializes the method descriptor for a method prototype.  Method | 
|  | 577 | // descriptors are not stored directly in the dex file.  Instead, one | 
|  | 578 | // must assemble the descriptor from references in the prototype. | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 579 | std::string DexFile::CreateMethodSignature(uint32_t proto_idx, int32_t* unicode_length) const { | 
| Carl Shapiro | 419ec7b | 2011-08-03 14:48:33 -0700 | [diff] [blame] | 580 | const ProtoId& proto_id = GetProtoId(proto_idx); | 
|  | 581 | std::string descriptor; | 
|  | 582 | descriptor.push_back('('); | 
|  | 583 | const TypeList* type_list = GetProtoParameters(proto_id); | 
|  | 584 | size_t parameter_length = 0; | 
|  | 585 | if (type_list != NULL) { | 
|  | 586 | // A non-zero number of arguments.  Append the type names. | 
|  | 587 | for (size_t i = 0; i < type_list->Size(); ++i) { | 
|  | 588 | const TypeItem& type_item = type_list->GetTypeItem(i); | 
|  | 589 | uint32_t type_idx = type_item.type_idx_; | 
| Elliott Hughes | 45651fd | 2012-02-21 15:48:20 -0800 | [diff] [blame] | 590 | uint32_t type_length; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 591 | const char* name = StringByTypeIdx(type_idx, &type_length); | 
| Carl Shapiro | 419ec7b | 2011-08-03 14:48:33 -0700 | [diff] [blame] | 592 | parameter_length += type_length; | 
|  | 593 | descriptor.append(name); | 
|  | 594 | } | 
|  | 595 | } | 
|  | 596 | descriptor.push_back(')'); | 
|  | 597 | uint32_t return_type_idx = proto_id.return_type_idx_; | 
| Elliott Hughes | 45651fd | 2012-02-21 15:48:20 -0800 | [diff] [blame] | 598 | uint32_t return_type_length; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 599 | const char* name = StringByTypeIdx(return_type_idx, &return_type_length); | 
| Carl Shapiro | 419ec7b | 2011-08-03 14:48:33 -0700 | [diff] [blame] | 600 | descriptor.append(name); | 
| Brian Carlstrom | 20cfffa | 2011-08-26 02:31:27 -0700 | [diff] [blame] | 601 | if (unicode_length != NULL) { | 
|  | 602 | *unicode_length = parameter_length + return_type_length + 2;  // 2 for ( and ) | 
|  | 603 | } | 
| Elliott Hughes | 0c424cb | 2011-08-26 10:16:25 -0700 | [diff] [blame] | 604 | return descriptor; | 
| Carl Shapiro | 419ec7b | 2011-08-03 14:48:33 -0700 | [diff] [blame] | 605 | } | 
|  | 606 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame^] | 607 | int32_t DexFile::GetLineNumFromPC(const mirror::AbstractMethod* method, uint32_t rel_pc) const { | 
| Shih-wei Liao | ff0f9be | 2011-08-29 15:43:53 -0700 | [diff] [blame] | 608 | // For native method, lineno should be -2 to indicate it is native. Note that | 
|  | 609 | // "line number == -2" is how libcore tells from StackTraceElement. | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 610 | if (method->GetCodeItemOffset() == 0) { | 
| Shih-wei Liao | ff0f9be | 2011-08-29 15:43:53 -0700 | [diff] [blame] | 611 | return -2; | 
|  | 612 | } | 
|  | 613 |  | 
| TDYa127 | c8dc101 | 2012-04-19 07:03:33 -0700 | [diff] [blame] | 614 | const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset()); | 
| Elliott Hughes | caf7654 | 2012-06-28 16:08:22 -0700 | [diff] [blame] | 615 | DCHECK(code_item != NULL) << PrettyMethod(method) << " " << GetLocation(); | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 616 |  | 
|  | 617 | // A method with no line number info should return -1 | 
|  | 618 | LineNumFromPcContext context(rel_pc, -1); | 
| TDYa127 | c8dc101 | 2012-04-19 07:03:33 -0700 | [diff] [blame] | 619 | DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb, | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 620 | NULL, &context); | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 621 | return context.line_num_; | 
|  | 622 | } | 
|  | 623 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame^] | 624 | const DexFile::TryItem* DexFile::GetTryItems(const CodeItem& code_item, uint32_t offset) { | 
|  | 625 | const uint16_t* insns_end_ = &code_item.insns_[code_item.insns_size_in_code_units_]; | 
|  | 626 | return reinterpret_cast<const TryItem*> | 
|  | 627 | (RoundUp(reinterpret_cast<uint32_t>(insns_end_), 4)) + offset; | 
|  | 628 | } | 
|  | 629 |  | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 630 | int32_t DexFile::FindCatchHandlerOffset(const CodeItem &code_item, int32_t tries_size, | 
| Elliott Hughes | ba8eee1 | 2012-01-24 20:25:24 -0800 | [diff] [blame] | 631 | uint32_t address) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 632 | // Note: Signed type is important for max and min. | 
|  | 633 | int32_t min = 0; | 
|  | 634 | int32_t max = tries_size - 1; | 
|  | 635 |  | 
|  | 636 | while (max >= min) { | 
|  | 637 | int32_t mid = (min + max) / 2; | 
| Elliott Hughes | 24edeb5 | 2012-06-18 15:29:46 -0700 | [diff] [blame] | 638 | const TryItem* try_item = DexFile::GetTryItems(code_item, mid); | 
|  | 639 | uint32_t start = try_item->start_addr_; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 640 | if (address < start) { | 
|  | 641 | max = mid - 1; | 
|  | 642 | } else { | 
| Elliott Hughes | 24edeb5 | 2012-06-18 15:29:46 -0700 | [diff] [blame] | 643 | uint32_t end = start + try_item->insn_count_; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 644 | if (address >= end) { | 
|  | 645 | min = mid + 1; | 
|  | 646 | } else {  // We have a winner! | 
| Elliott Hughes | 24edeb5 | 2012-06-18 15:29:46 -0700 | [diff] [blame] | 647 | return (int32_t) try_item->handler_off_; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 648 | } | 
|  | 649 | } | 
|  | 650 | } | 
|  | 651 | // No match. | 
|  | 652 | return -1; | 
|  | 653 | } | 
|  | 654 |  | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 655 | void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx, | 
| Elliott Hughes | 2435a57 | 2012-02-17 16:07:41 -0800 | [diff] [blame] | 656 | DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb, | 
|  | 657 | void* context, const byte* stream, LocalInfo* local_in_reg) const { | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 658 | uint32_t line = DecodeUnsignedLeb128(&stream); | 
|  | 659 | uint32_t parameters_size = DecodeUnsignedLeb128(&stream); | 
|  | 660 | uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_; | 
|  | 661 | uint32_t address = 0; | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 662 | bool need_locals = (local_cb != NULL); | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 663 |  | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 664 | if (!is_static) { | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 665 | if (need_locals) { | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 666 | const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx)); | 
| Brian Carlstrom | 40381fb | 2011-10-19 14:13:40 -0700 | [diff] [blame] | 667 | local_in_reg[arg_reg].name_ = "this"; | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 668 | local_in_reg[arg_reg].descriptor_ = descriptor; | 
| Elliott Hughes | 392b124 | 2011-11-30 13:55:50 -0800 | [diff] [blame] | 669 | local_in_reg[arg_reg].signature_ = NULL; | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 670 | local_in_reg[arg_reg].start_address_ = 0; | 
|  | 671 | local_in_reg[arg_reg].is_live_ = true; | 
|  | 672 | } | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 673 | arg_reg++; | 
|  | 674 | } | 
|  | 675 |  | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 676 | DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx))); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 677 | for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) { | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 678 | if (arg_reg >= code_item->registers_size_) { | 
| jeffhao | f872887 | 2011-10-28 19:11:13 -0700 | [diff] [blame] | 679 | LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg | 
| Brian Carlstrom | 2aab947 | 2011-12-12 15:21:43 -0800 | [diff] [blame] | 680 | << " >= " << code_item->registers_size_ << ") in " << GetLocation(); | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 681 | return; | 
|  | 682 | } | 
| Elliott Hughes | 392b124 | 2011-11-30 13:55:50 -0800 | [diff] [blame] | 683 | uint32_t id = DecodeUnsignedLeb128P1(&stream); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 684 | const char* descriptor = it.GetDescriptor(); | 
| Elliott Hughes | 392b124 | 2011-11-30 13:55:50 -0800 | [diff] [blame] | 685 | if (need_locals && id != kDexNoIndex) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 686 | const char* name = StringDataByIdx(id); | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 687 | local_in_reg[arg_reg].name_ = name; | 
|  | 688 | local_in_reg[arg_reg].descriptor_ = descriptor; | 
| Elliott Hughes | 392b124 | 2011-11-30 13:55:50 -0800 | [diff] [blame] | 689 | local_in_reg[arg_reg].signature_ = NULL; | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 690 | local_in_reg[arg_reg].start_address_ = address; | 
|  | 691 | local_in_reg[arg_reg].is_live_ = true; | 
|  | 692 | } | 
| Brian Carlstrom | 40381fb | 2011-10-19 14:13:40 -0700 | [diff] [blame] | 693 | switch (*descriptor) { | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 694 | case 'D': | 
|  | 695 | case 'J': | 
|  | 696 | arg_reg += 2; | 
|  | 697 | break; | 
|  | 698 | default: | 
|  | 699 | arg_reg += 1; | 
|  | 700 | break; | 
|  | 701 | } | 
|  | 702 | } | 
|  | 703 |  | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 704 | if (it.HasNext()) { | 
| Brian Carlstrom | 2aab947 | 2011-12-12 15:21:43 -0800 | [diff] [blame] | 705 | LOG(ERROR) << "invalid stream - problem with parameter iterator in " << GetLocation(); | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 706 | return; | 
|  | 707 | } | 
|  | 708 |  | 
|  | 709 | for (;;)  { | 
|  | 710 | uint8_t opcode = *stream++; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 711 | uint16_t reg; | 
| jeffhao | f872887 | 2011-10-28 19:11:13 -0700 | [diff] [blame] | 712 | uint16_t name_idx; | 
|  | 713 | uint16_t descriptor_idx; | 
|  | 714 | uint16_t signature_idx = 0; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 715 |  | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 716 | switch (opcode) { | 
|  | 717 | case DBG_END_SEQUENCE: | 
|  | 718 | return; | 
|  | 719 |  | 
|  | 720 | case DBG_ADVANCE_PC: | 
|  | 721 | address += DecodeUnsignedLeb128(&stream); | 
|  | 722 | break; | 
|  | 723 |  | 
|  | 724 | case DBG_ADVANCE_LINE: | 
| Shih-wei Liao | 8a05d27 | 2011-10-15 18:45:43 -0700 | [diff] [blame] | 725 | line += DecodeSignedLeb128(&stream); | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 726 | break; | 
|  | 727 |  | 
|  | 728 | case DBG_START_LOCAL: | 
|  | 729 | case DBG_START_LOCAL_EXTENDED: | 
|  | 730 | reg = DecodeUnsignedLeb128(&stream); | 
|  | 731 | if (reg > code_item->registers_size_) { | 
| jeffhao | f872887 | 2011-10-28 19:11:13 -0700 | [diff] [blame] | 732 | LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > " | 
| Brian Carlstrom | 2aab947 | 2011-12-12 15:21:43 -0800 | [diff] [blame] | 733 | << code_item->registers_size_ << ") in " << GetLocation(); | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 734 | return; | 
|  | 735 | } | 
|  | 736 |  | 
| jeffhao | f872887 | 2011-10-28 19:11:13 -0700 | [diff] [blame] | 737 | name_idx = DecodeUnsignedLeb128P1(&stream); | 
|  | 738 | descriptor_idx = DecodeUnsignedLeb128P1(&stream); | 
|  | 739 | if (opcode == DBG_START_LOCAL_EXTENDED) { | 
|  | 740 | signature_idx = DecodeUnsignedLeb128P1(&stream); | 
|  | 741 | } | 
|  | 742 |  | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 743 | // Emit what was previously there, if anything | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 744 | if (need_locals) { | 
| Elliott Hughes | 2435a57 | 2012-02-17 16:07:41 -0800 | [diff] [blame] | 745 | InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb); | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 746 |  | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 747 | local_in_reg[reg].name_ = StringDataByIdx(name_idx); | 
|  | 748 | local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx); | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 749 | if (opcode == DBG_START_LOCAL_EXTENDED) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 750 | local_in_reg[reg].signature_ = StringDataByIdx(signature_idx); | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 751 | } | 
|  | 752 | local_in_reg[reg].start_address_ = address; | 
|  | 753 | local_in_reg[reg].is_live_ = true; | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 754 | } | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 755 | break; | 
|  | 756 |  | 
|  | 757 | case DBG_END_LOCAL: | 
|  | 758 | reg = DecodeUnsignedLeb128(&stream); | 
|  | 759 | if (reg > code_item->registers_size_) { | 
| jeffhao | f872887 | 2011-10-28 19:11:13 -0700 | [diff] [blame] | 760 | LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > " | 
| Brian Carlstrom | 2aab947 | 2011-12-12 15:21:43 -0800 | [diff] [blame] | 761 | << code_item->registers_size_ << ") in " << GetLocation(); | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 762 | return; | 
|  | 763 | } | 
|  | 764 |  | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 765 | if (need_locals) { | 
| Elliott Hughes | 2435a57 | 2012-02-17 16:07:41 -0800 | [diff] [blame] | 766 | InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb); | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 767 | local_in_reg[reg].is_live_ = false; | 
|  | 768 | } | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 769 | break; | 
|  | 770 |  | 
|  | 771 | case DBG_RESTART_LOCAL: | 
|  | 772 | reg = DecodeUnsignedLeb128(&stream); | 
|  | 773 | if (reg > code_item->registers_size_) { | 
| jeffhao | f872887 | 2011-10-28 19:11:13 -0700 | [diff] [blame] | 774 | LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > " | 
| Brian Carlstrom | 2aab947 | 2011-12-12 15:21:43 -0800 | [diff] [blame] | 775 | << code_item->registers_size_ << ") in " << GetLocation(); | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 776 | return; | 
|  | 777 | } | 
|  | 778 |  | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 779 | if (need_locals) { | 
|  | 780 | if (local_in_reg[reg].name_ == NULL || local_in_reg[reg].descriptor_ == NULL) { | 
| Brian Carlstrom | 2aab947 | 2011-12-12 15:21:43 -0800 | [diff] [blame] | 781 | LOG(ERROR) << "invalid stream - no name or descriptor in " << GetLocation(); | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 782 | return; | 
|  | 783 | } | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 784 |  | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 785 | // If the register is live, the "restart" is superfluous, | 
|  | 786 | // and we don't want to mess with the existing start address. | 
|  | 787 | if (!local_in_reg[reg].is_live_) { | 
|  | 788 | local_in_reg[reg].start_address_ = address; | 
|  | 789 | local_in_reg[reg].is_live_ = true; | 
|  | 790 | } | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 791 | } | 
|  | 792 | break; | 
|  | 793 |  | 
|  | 794 | case DBG_SET_PROLOGUE_END: | 
|  | 795 | case DBG_SET_EPILOGUE_BEGIN: | 
|  | 796 | case DBG_SET_FILE: | 
|  | 797 | break; | 
|  | 798 |  | 
| Shih-wei Liao | 8e1b4ff | 2011-10-15 15:43:51 -0700 | [diff] [blame] | 799 | default: { | 
|  | 800 | int adjopcode = opcode - DBG_FIRST_SPECIAL; | 
|  | 801 |  | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 802 | address += adjopcode / DBG_LINE_RANGE; | 
|  | 803 | line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE); | 
|  | 804 |  | 
| Elliott Hughes | 2435a57 | 2012-02-17 16:07:41 -0800 | [diff] [blame] | 805 | if (position_cb != NULL) { | 
|  | 806 | if (position_cb(context, address, line)) { | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 807 | // early exit | 
|  | 808 | return; | 
|  | 809 | } | 
|  | 810 | } | 
|  | 811 | break; | 
| Shih-wei Liao | 8e1b4ff | 2011-10-15 15:43:51 -0700 | [diff] [blame] | 812 | } | 
| Shih-wei Liao | 195487c | 2011-08-20 13:29:04 -0700 | [diff] [blame] | 813 | } | 
|  | 814 | } | 
|  | 815 | } | 
|  | 816 |  | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 817 | void DexFile::DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx, | 
| Elliott Hughes | 2435a57 | 2012-02-17 16:07:41 -0800 | [diff] [blame] | 818 | DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb, | 
|  | 819 | void* context) const { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 820 | const byte* stream = GetDebugInfoStream(code_item); | 
| Elliott Hughes | ee0fa76 | 2012-03-26 17:12:41 -0700 | [diff] [blame] | 821 | UniquePtr<LocalInfo[]> local_in_reg(local_cb != NULL ? new LocalInfo[code_item->registers_size_] : NULL); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 822 | if (stream != NULL) { | 
| Elliott Hughes | ee0fa76 | 2012-03-26 17:12:41 -0700 | [diff] [blame] | 823 | DecodeDebugInfo0(code_item, is_static, method_idx, position_cb, local_cb, context, stream, &local_in_reg[0]); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 824 | } | 
|  | 825 | for (int reg = 0; reg < code_item->registers_size_; reg++) { | 
| Elliott Hughes | ee0fa76 | 2012-03-26 17:12:41 -0700 | [diff] [blame] | 826 | InvokeLocalCbIfLive(context, reg, code_item->insns_size_in_code_units_, &local_in_reg[0], local_cb); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 827 | } | 
|  | 828 | } | 
|  | 829 |  | 
| Elliott Hughes | 2435a57 | 2012-02-17 16:07:41 -0800 | [diff] [blame] | 830 | bool DexFile::LineNumForPcCb(void* raw_context, uint32_t address, uint32_t line_num) { | 
|  | 831 | LineNumFromPcContext* context = reinterpret_cast<LineNumFromPcContext*>(raw_context); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 832 |  | 
|  | 833 | // We know that this callback will be called in | 
|  | 834 | // ascending address order, so keep going until we find | 
|  | 835 | // a match or we've just gone past it. | 
|  | 836 | if (address > context->address_) { | 
|  | 837 | // The line number from the previous positions callback | 
|  | 838 | // wil be the final result. | 
|  | 839 | return true; | 
|  | 840 | } else { | 
|  | 841 | context->line_num_ = line_num; | 
|  | 842 | return address == context->address_; | 
|  | 843 | } | 
|  | 844 | } | 
|  | 845 |  | 
|  | 846 | // Decodes the header section from the class data bytes. | 
|  | 847 | void ClassDataItemIterator::ReadClassDataHeader() { | 
|  | 848 | CHECK(ptr_pos_ != NULL); | 
|  | 849 | header_.static_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_); | 
|  | 850 | header_.instance_fields_size_ = DecodeUnsignedLeb128(&ptr_pos_); | 
|  | 851 | header_.direct_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_); | 
|  | 852 | header_.virtual_methods_size_ = DecodeUnsignedLeb128(&ptr_pos_); | 
|  | 853 | } | 
|  | 854 |  | 
|  | 855 | void ClassDataItemIterator::ReadClassDataField() { | 
|  | 856 | field_.field_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_); | 
|  | 857 | field_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_); | 
| Brian Carlstrom | 68adbe4 | 2012-05-11 17:18:08 -0700 | [diff] [blame] | 858 | if (last_idx_ != 0 && field_.field_idx_delta_ == 0) { | 
| Brian Carlstrom | 6f29d0e | 2012-05-11 15:50:29 -0700 | [diff] [blame] | 859 | LOG(WARNING) << "Duplicate field " << PrettyField(GetMemberIndex(), dex_file_) | 
|  | 860 | << " in " << dex_file_.GetLocation(); | 
|  | 861 | } | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 862 | } | 
|  | 863 |  | 
|  | 864 | void ClassDataItemIterator::ReadClassDataMethod() { | 
|  | 865 | method_.method_idx_delta_ = DecodeUnsignedLeb128(&ptr_pos_); | 
|  | 866 | method_.access_flags_ = DecodeUnsignedLeb128(&ptr_pos_); | 
|  | 867 | method_.code_off_ = DecodeUnsignedLeb128(&ptr_pos_); | 
| Brian Carlstrom | 68adbe4 | 2012-05-11 17:18:08 -0700 | [diff] [blame] | 868 | if (last_idx_ != 0 && method_.method_idx_delta_ == 0) { | 
| Brian Carlstrom | 6f29d0e | 2012-05-11 15:50:29 -0700 | [diff] [blame] | 869 | LOG(WARNING) << "Duplicate method " << PrettyMethod(GetMemberIndex(), dex_file_) | 
|  | 870 | << " in " << dex_file_.GetLocation(); | 
|  | 871 | } | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 872 | } | 
|  | 873 |  | 
|  | 874 | // Read a signed integer.  "zwidth" is the zero-based byte count. | 
|  | 875 | static int32_t ReadSignedInt(const byte* ptr, int zwidth) { | 
|  | 876 | int32_t val = 0; | 
|  | 877 | for (int i = zwidth; i >= 0; --i) { | 
|  | 878 | val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24); | 
|  | 879 | } | 
|  | 880 | val >>= (3 - zwidth) * 8; | 
|  | 881 | return val; | 
|  | 882 | } | 
|  | 883 |  | 
|  | 884 | // Read an unsigned integer.  "zwidth" is the zero-based byte count, | 
|  | 885 | // "fill_on_right" indicates which side we want to zero-fill from. | 
|  | 886 | static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth, bool fill_on_right) { | 
|  | 887 | uint32_t val = 0; | 
|  | 888 | if (!fill_on_right) { | 
|  | 889 | for (int i = zwidth; i >= 0; --i) { | 
|  | 890 | val = (val >> 8) | (((uint32_t)*ptr++) << 24); | 
|  | 891 | } | 
|  | 892 | val >>= (3 - zwidth) * 8; | 
|  | 893 | } else { | 
|  | 894 | for (int i = zwidth; i >= 0; --i) { | 
|  | 895 | val = (val >> 8) | (((uint32_t)*ptr++) << 24); | 
|  | 896 | } | 
|  | 897 | } | 
|  | 898 | return val; | 
|  | 899 | } | 
|  | 900 |  | 
|  | 901 | // Read a signed long.  "zwidth" is the zero-based byte count. | 
|  | 902 | static int64_t ReadSignedLong(const byte* ptr, int zwidth) { | 
|  | 903 | int64_t val = 0; | 
|  | 904 | for (int i = zwidth; i >= 0; --i) { | 
|  | 905 | val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56); | 
|  | 906 | } | 
|  | 907 | val >>= (7 - zwidth) * 8; | 
|  | 908 | return val; | 
|  | 909 | } | 
|  | 910 |  | 
|  | 911 | // Read an unsigned long.  "zwidth" is the zero-based byte count, | 
|  | 912 | // "fill_on_right" indicates which side we want to zero-fill from. | 
|  | 913 | static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, bool fill_on_right) { | 
|  | 914 | uint64_t val = 0; | 
|  | 915 | if (!fill_on_right) { | 
|  | 916 | for (int i = zwidth; i >= 0; --i) { | 
|  | 917 | val = (val >> 8) | (((uint64_t)*ptr++) << 56); | 
|  | 918 | } | 
|  | 919 | val >>= (7 - zwidth) * 8; | 
|  | 920 | } else { | 
|  | 921 | for (int i = zwidth; i >= 0; --i) { | 
|  | 922 | val = (val >> 8) | (((uint64_t)*ptr++) << 56); | 
|  | 923 | } | 
|  | 924 | } | 
|  | 925 | return val; | 
|  | 926 | } | 
|  | 927 |  | 
|  | 928 | EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file, | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame^] | 929 | mirror::DexCache* dex_cache, | 
|  | 930 | mirror::ClassLoader* class_loader, | 
| Ian Rogers | ca19066 | 2012-06-26 15:45:57 -0700 | [diff] [blame] | 931 | ClassLinker* linker, | 
|  | 932 | const DexFile::ClassDef& class_def) | 
| Brian Carlstrom | 88f3654 | 2012-10-16 23:24:21 -0700 | [diff] [blame] | 933 | : dex_file_(dex_file), dex_cache_(dex_cache), class_loader_(class_loader), linker_(linker), | 
|  | 934 | array_size_(), pos_(-1), type_(kByte) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 935 | ptr_ = dex_file.GetEncodedStaticFieldValuesArray(class_def); | 
|  | 936 | if (ptr_ == NULL) { | 
|  | 937 | array_size_ = 0; | 
|  | 938 | } else { | 
|  | 939 | array_size_ = DecodeUnsignedLeb128(&ptr_); | 
|  | 940 | } | 
|  | 941 | if (array_size_ > 0) { | 
|  | 942 | Next(); | 
|  | 943 | } | 
|  | 944 | } | 
|  | 945 |  | 
|  | 946 | void EncodedStaticFieldValueIterator::Next() { | 
|  | 947 | pos_++; | 
|  | 948 | if (pos_ >= array_size_) { | 
|  | 949 | return; | 
|  | 950 | } | 
|  | 951 | byte value_type = *ptr_++; | 
|  | 952 | byte value_arg = value_type >> kEncodedValueArgShift; | 
|  | 953 | size_t width = value_arg + 1;  // assume and correct later | 
| Brian Carlstrom | 88f3654 | 2012-10-16 23:24:21 -0700 | [diff] [blame] | 954 | type_ = static_cast<ValueType>(value_type & kEncodedValueTypeMask); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 955 | switch (type_) { | 
|  | 956 | case kBoolean: | 
|  | 957 | jval_.i = (value_arg != 0) ? 1 : 0; | 
|  | 958 | width = 0; | 
|  | 959 | break; | 
|  | 960 | case kByte: | 
|  | 961 | jval_.i = ReadSignedInt(ptr_, value_arg); | 
|  | 962 | CHECK(IsInt(8, jval_.i)); | 
|  | 963 | break; | 
|  | 964 | case kShort: | 
|  | 965 | jval_.i = ReadSignedInt(ptr_, value_arg); | 
|  | 966 | CHECK(IsInt(16, jval_.i)); | 
|  | 967 | break; | 
|  | 968 | case kChar: | 
|  | 969 | jval_.i = ReadUnsignedInt(ptr_, value_arg, false); | 
|  | 970 | CHECK(IsUint(16, jval_.i)); | 
|  | 971 | break; | 
|  | 972 | case kInt: | 
|  | 973 | jval_.i = ReadSignedInt(ptr_, value_arg); | 
|  | 974 | break; | 
|  | 975 | case kLong: | 
|  | 976 | jval_.j = ReadSignedLong(ptr_, value_arg); | 
|  | 977 | break; | 
|  | 978 | case kFloat: | 
|  | 979 | jval_.i = ReadUnsignedInt(ptr_, value_arg, true); | 
|  | 980 | break; | 
|  | 981 | case kDouble: | 
|  | 982 | jval_.j = ReadUnsignedLong(ptr_, value_arg, true); | 
|  | 983 | break; | 
|  | 984 | case kString: | 
|  | 985 | case kType: | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 986 | jval_.i = ReadUnsignedInt(ptr_, value_arg, false); | 
|  | 987 | break; | 
|  | 988 | case kField: | 
| Brian Carlstrom | 88f3654 | 2012-10-16 23:24:21 -0700 | [diff] [blame] | 989 | case kMethod: | 
|  | 990 | case kEnum: | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 991 | case kArray: | 
|  | 992 | case kAnnotation: | 
|  | 993 | UNIMPLEMENTED(FATAL) << ": type " << type_; | 
|  | 994 | break; | 
|  | 995 | case kNull: | 
|  | 996 | jval_.l = NULL; | 
|  | 997 | width = 0; | 
|  | 998 | break; | 
|  | 999 | default: | 
|  | 1000 | LOG(FATAL) << "Unreached"; | 
|  | 1001 | } | 
|  | 1002 | ptr_ += width; | 
|  | 1003 | } | 
|  | 1004 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame^] | 1005 | void EncodedStaticFieldValueIterator::ReadValueToField(mirror::Field* field) const { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1006 | switch (type_) { | 
| Ian Rogers | 2fa6b2e | 2012-10-17 00:10:17 -0700 | [diff] [blame] | 1007 | case kBoolean: field->SetBoolean(field->GetDeclaringClass(), jval_.z); break; | 
|  | 1008 | case kByte:    field->SetByte(field->GetDeclaringClass(), jval_.b); break; | 
|  | 1009 | case kShort:   field->SetShort(field->GetDeclaringClass(), jval_.s); break; | 
|  | 1010 | case kChar:    field->SetChar(field->GetDeclaringClass(), jval_.c); break; | 
|  | 1011 | case kInt:     field->SetInt(field->GetDeclaringClass(), jval_.i); break; | 
|  | 1012 | case kLong:    field->SetLong(field->GetDeclaringClass(), jval_.j); break; | 
|  | 1013 | case kFloat:   field->SetFloat(field->GetDeclaringClass(), jval_.f); break; | 
|  | 1014 | case kDouble:  field->SetDouble(field->GetDeclaringClass(), jval_.d); break; | 
|  | 1015 | case kNull:    field->SetObject(field->GetDeclaringClass(), NULL); break; | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1016 | case kString: { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame^] | 1017 | mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, dex_cache_); | 
| Ian Rogers | 2fa6b2e | 2012-10-17 00:10:17 -0700 | [diff] [blame] | 1018 | field->SetObject(field->GetDeclaringClass(), resolved); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1019 | break; | 
|  | 1020 | } | 
| Brian Carlstrom | 88f3654 | 2012-10-16 23:24:21 -0700 | [diff] [blame] | 1021 | case kType: { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame^] | 1022 | mirror::Class* resolved = linker_->ResolveType(dex_file_, jval_.i, dex_cache_, class_loader_); | 
| mikaelpeltier | ebf6aa8 | 2012-11-07 14:02:15 +0100 | [diff] [blame] | 1023 | field->SetObject(field->GetDeclaringClass(), resolved); | 
| Brian Carlstrom | 88f3654 | 2012-10-16 23:24:21 -0700 | [diff] [blame] | 1024 | break; | 
|  | 1025 | } | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1026 | default: UNIMPLEMENTED(FATAL) << ": type " << type_; | 
|  | 1027 | } | 
|  | 1028 | } | 
|  | 1029 |  | 
|  | 1030 | CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) { | 
|  | 1031 | handler_.address_ = -1; | 
|  | 1032 | int32_t offset = -1; | 
|  | 1033 |  | 
|  | 1034 | // Short-circuit the overwhelmingly common cases. | 
|  | 1035 | switch (code_item.tries_size_) { | 
|  | 1036 | case 0: | 
|  | 1037 | break; | 
|  | 1038 | case 1: { | 
|  | 1039 | const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0); | 
|  | 1040 | uint32_t start = tries->start_addr_; | 
|  | 1041 | if (address >= start) { | 
|  | 1042 | uint32_t end = start + tries->insn_count_; | 
|  | 1043 | if (address < end) { | 
|  | 1044 | offset = tries->handler_off_; | 
|  | 1045 | } | 
|  | 1046 | } | 
|  | 1047 | break; | 
|  | 1048 | } | 
|  | 1049 | default: | 
|  | 1050 | offset = DexFile::FindCatchHandlerOffset(code_item, code_item.tries_size_, address); | 
|  | 1051 | } | 
| Logan Chien | 736df02 | 2012-04-27 16:25:57 +0800 | [diff] [blame] | 1052 | Init(code_item, offset); | 
|  | 1053 | } | 
|  | 1054 |  | 
|  | 1055 | CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, | 
|  | 1056 | const DexFile::TryItem& try_item) { | 
|  | 1057 | handler_.address_ = -1; | 
|  | 1058 | Init(code_item, try_item.handler_off_); | 
|  | 1059 | } | 
|  | 1060 |  | 
|  | 1061 | void CatchHandlerIterator::Init(const DexFile::CodeItem& code_item, | 
|  | 1062 | int32_t offset) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1063 | if (offset >= 0) { | 
| Logan Chien | 736df02 | 2012-04-27 16:25:57 +0800 | [diff] [blame] | 1064 | Init(DexFile::GetCatchHandlerData(code_item, offset)); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1065 | } else { | 
|  | 1066 | // Not found, initialize as empty | 
|  | 1067 | current_data_ = NULL; | 
|  | 1068 | remaining_count_ = -1; | 
|  | 1069 | catch_all_ = false; | 
|  | 1070 | DCHECK(!HasNext()); | 
|  | 1071 | } | 
|  | 1072 | } | 
|  | 1073 |  | 
|  | 1074 | void CatchHandlerIterator::Init(const byte* handler_data) { | 
|  | 1075 | current_data_ = handler_data; | 
|  | 1076 | remaining_count_ = DecodeSignedLeb128(¤t_data_); | 
|  | 1077 |  | 
|  | 1078 | // If remaining_count_ is non-positive, then it is the negative of | 
|  | 1079 | // the number of catch types, and the catches are followed by a | 
|  | 1080 | // catch-all handler. | 
|  | 1081 | if (remaining_count_ <= 0) { | 
|  | 1082 | catch_all_ = true; | 
|  | 1083 | remaining_count_ = -remaining_count_; | 
|  | 1084 | } else { | 
|  | 1085 | catch_all_ = false; | 
|  | 1086 | } | 
|  | 1087 | Next(); | 
|  | 1088 | } | 
|  | 1089 |  | 
|  | 1090 | void CatchHandlerIterator::Next() { | 
|  | 1091 | if (remaining_count_ > 0) { | 
|  | 1092 | handler_.type_idx_ = DecodeUnsignedLeb128(¤t_data_); | 
|  | 1093 | handler_.address_  = DecodeUnsignedLeb128(¤t_data_); | 
|  | 1094 | remaining_count_--; | 
|  | 1095 | return; | 
|  | 1096 | } | 
|  | 1097 |  | 
|  | 1098 | if (catch_all_) { | 
|  | 1099 | handler_.type_idx_ = DexFile::kDexNoIndex16; | 
|  | 1100 | handler_.address_  = DecodeUnsignedLeb128(¤t_data_); | 
|  | 1101 | catch_all_ = false; | 
|  | 1102 | return; | 
|  | 1103 | } | 
|  | 1104 |  | 
|  | 1105 | // no more handler | 
|  | 1106 | remaining_count_ = -1; | 
|  | 1107 | } | 
|  | 1108 |  | 
| Carl Shapiro | 1fb8620 | 2011-06-27 17:43:13 -0700 | [diff] [blame] | 1109 | }  // namespace art |