12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 16e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 17e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "oat_file.h" 18e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 19700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include <dlfcn.h> 204e1d579d6401fef2dd57b16f8d406e33221a69d9Calin Juravle#include <string.h> 21daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe#include <unistd.h> 22700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 237848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe#include <cstdlib> 24a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#ifndef __APPLE__ 25a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#include <link.h> // for dl_iterate_phdr. 26a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#endif 27e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler#include <sstream> 28e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler 29fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// dlopen_ext support from bionic. 30fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#ifdef HAVE_ANDROID_OS 31fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#include "android/dlext.h" 32fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#endif 33fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 343d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier#include "art_method-inl.h" 35ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom#include "base/bit_vector.h" 361aa246dec5abe212f699de1413a0c4a191ca364aElliott Hughes#include "base/stl_util.h" 37761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h" 38700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "elf_file.h" 3984d7605f93f1e6e86a16e02017e305c90e93117aAlex Light#include "elf_utils.h" 40700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "oat.h" 41a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#include "mem_map.h" 422dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h" 434f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h" 44e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "os.h" 4522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe#include "runtime.h" 462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "utils.h" 471809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers#include "vmap_table.h" 48e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 49e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art { 50e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 51fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// Whether OatFile::Open will try DlOpen() first. Fallback is our own ELF loader. 52a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbeckystatic constexpr bool kUseDlopen = true; 53fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 54fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// Whether OatFile::Open will try DlOpen() on the host. On the host we're not linking against 55fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// bionic, so cannot take advantage of the support for changed semantics (loading the same soname 56fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// multiple times). However, if/when we switch the above, we likely want to switch this, too, 57fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// to get test coverage of the code paths. 58a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbeckystatic constexpr bool kUseDlopenOnHost = true; 59fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 60fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// For debugging, Open will print DlOpen error message if set to true. 61fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampestatic constexpr bool kPrintDlOpenErrorMessage = false; 62fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 63e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhlerstd::string OatFile::ResolveRelativeEncodedDexLocation( 64e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, const std::string& rel_dex_location) { 65e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler if (abs_dex_location != nullptr && rel_dex_location[0] != '/') { 66e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler // Strip :classes<N>.dex used for secondary multidex files. 67e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler std::string base = DexFile::GetBaseLocation(rel_dex_location); 68e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler std::string multidex_suffix = DexFile::GetMultiDexSuffix(rel_dex_location); 69e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler 70e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler // Check if the base is a suffix of the provided abs_dex_location. 71e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler std::string target_suffix = "/" + base; 72e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler std::string abs_location(abs_dex_location); 73e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler if (abs_location.size() > target_suffix.size()) { 74e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler size_t pos = abs_location.size() - target_suffix.size(); 75e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler if (abs_location.compare(pos, std::string::npos, target_suffix) == 0) { 76e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler return abs_location + multidex_suffix; 77e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler } 78e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler } 79e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler } 80e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler return rel_dex_location; 81e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler} 82e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler 83700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstromvoid OatFile::CheckLocation(const std::string& location) { 84700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom CHECK(!location.empty()); 85700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom} 86700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 8784d7605f93f1e6e86a16e02017e305c90e93117aAlex LightOatFile* OatFile::OpenWithElfFile(ElfFile* elf_file, 8884d7605f93f1e6e86a16e02017e305c90e93117aAlex Light const std::string& location, 89e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 9084d7605f93f1e6e86a16e02017e305c90e93117aAlex Light std::string* error_msg) { 9184d7605f93f1e6e86a16e02017e305c90e93117aAlex Light std::unique_ptr<OatFile> oat_file(new OatFile(location, false)); 9284d7605f93f1e6e86a16e02017e305c90e93117aAlex Light oat_file->elf_file_.reset(elf_file); 9362d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen uint64_t offset, size; 9462d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size); 9562d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen CHECK(has_section); 9662d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen oat_file->begin_ = elf_file->Begin() + offset; 9762d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen oat_file->end_ = elf_file->Begin() + size + offset; 985c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko // Ignore the optional .bss section when opening non-executable. 99e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler return oat_file->Setup(abs_dex_location, error_msg) ? oat_file.release() : nullptr; 100700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom} 101700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 102e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile* OatFile::Open(const std::string& filename, 103a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom const std::string& location, 10413735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* requested_base, 10546774767fcf7780d1455e755729198648d08742eIgor Murashkin uint8_t* oat_file_begin, 1068d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers bool executable, 107e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 1088d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string* error_msg) { 1097a967b3d4468ab56bf1b75ebd4d7bf9e6798761bBrian Carlstrom CHECK(!filename.empty()) << location; 1107ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe CheckLocation(location); 11122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe std::unique_ptr<OatFile> ret; 112fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 113fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // Use dlopen only when flagged to do so, and when it's OK to load things executable. 114fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // TODO: Also try when not executable? The issue here could be re-mapping as writable (as 115fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // !executable is a sign that we may want to patch), which may not be allowed for 116fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // various reasons. 117fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (kUseDlopen && (kIsTargetBuild || kUseDlopenOnHost) && executable) { 118fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // Try to use dlopen. This may fail for various reasons, outlined below. We try dlopen, as 119fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // this will register the oat file with the linker and allows libunwind to find our info. 120fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe ret.reset(OpenDlopen(filename, location, requested_base, abs_dex_location, error_msg)); 121fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (ret.get() != nullptr) { 122fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe return ret.release(); 123fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 124fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (kPrintDlOpenErrorMessage) { 125fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe LOG(ERROR) << "Failed to dlopen: " << *error_msg; 126fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 127fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 128fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 129956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons: 130956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes // 131956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes // On target, dlopen may fail when compiling due to selinux restrictions on installd. 132956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes // 133956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes // We use our own ELF loader for Quick to deal with legacy apps that 134956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes // open a generated dex file by name, remove the file, then open 135956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes // another generated dex file with the same name. http://b/10614658 136956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes // 137956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile. 138fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // 139fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // 140fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually 141fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN. 142956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes std::unique_ptr<File> file(OS::OpenFileForReading(filename.c_str())); 143fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (file == nullptr) { 144956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno)); 145956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes return nullptr; 14622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe } 147956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes ret.reset(OpenElfFile(file.get(), location, requested_base, oat_file_begin, false, executable, 148e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler abs_dex_location, error_msg)); 149956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes 150956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes // It would be nice to unlink here. But we might have opened the file created by the 151956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes // ScopedLock, which we better not delete to avoid races. TODO: Investigate how to fix the API 152956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes // to allow removal when we know the ELF must be borked. 15369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison return ret.release(); 1545b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom} 155e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 156e5fed03772144595c0904faf3d6974cc55214c8cRichard UhlerOatFile* OatFile::OpenWritable(File* file, const std::string& location, 157e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 158e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler std::string* error_msg) { 159700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom CheckLocation(location); 160e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler return OpenElfFile(file, location, nullptr, nullptr, true, false, abs_dex_location, error_msg); 161700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom} 162700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 163e5fed03772144595c0904faf3d6974cc55214c8cRichard UhlerOatFile* OatFile::OpenReadable(File* file, const std::string& location, 164e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 165e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler std::string* error_msg) { 166a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light CheckLocation(location); 167e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler return OpenElfFile(file, location, nullptr, nullptr, false, false, abs_dex_location, error_msg); 168a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light} 169a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 170fa8429b967fe2260ece572337534c9dda6c50d8aAndreas GampeOatFile* OatFile::OpenDlopen(const std::string& elf_filename, 171fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe const std::string& location, 172fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe uint8_t* requested_base, 173fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe const char* abs_dex_location, 174fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe std::string* error_msg) { 175fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe std::unique_ptr<OatFile> oat_file(new OatFile(location, true)); 176fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe bool success = oat_file->Dlopen(elf_filename, requested_base, abs_dex_location, error_msg); 177fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (!success) { 178fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe return nullptr; 179fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 180fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe return oat_file.release(); 181fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe} 182fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 183700c8d31733534a3d978b75a03f6f7e177dc7e81Brian CarlstromOatFile* OatFile::OpenElfFile(File* file, 184700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom const std::string& location, 18513735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* requested_base, 18646774767fcf7780d1455e755729198648d08742eIgor Murashkin uint8_t* oat_file_begin, 187f1d3455064792ac1c486a4a9c24279a37b4af473Brian Carlstrom bool writable, 1888d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers bool executable, 189e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 1908d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string* error_msg) { 1919dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light std::unique_ptr<OatFile> oat_file(new OatFile(location, executable)); 19246774767fcf7780d1455e755729198648d08742eIgor Murashkin bool success = oat_file->ElfFileOpen(file, requested_base, oat_file_begin, writable, executable, 193e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler abs_dex_location, error_msg); 194e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!success) { 1958d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers CHECK(!error_msg->empty()); 1968d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers return nullptr; 197e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 198e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return oat_file.release(); 199e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 200e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 2019dcc4572949f6a8231a1b4ed859676ba6f411726Alex LightOatFile::OatFile(const std::string& location, bool is_executable) 202fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe : location_(location), begin_(nullptr), end_(nullptr), bss_begin_(nullptr), bss_end_(nullptr), 203fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe is_executable_(is_executable), dlopen_handle_(nullptr), 2043f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) { 205a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom CHECK(!location_.empty()); 206a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom} 207e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 208e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::~OatFile() { 209aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko STLDeleteElements(&oat_dex_files_storage_); 210fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (dlopen_handle_ != nullptr) { 211700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom dlclose(dlopen_handle_); 212700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom } 213e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 214e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 215fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampebool OatFile::Dlopen(const std::string& elf_filename, uint8_t* requested_base, 216fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe const char* abs_dex_location, std::string* error_msg) { 217a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#ifdef __APPLE__ 218a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // The dl_iterate_phdr syscall is missing. There is similar API on OSX, 219a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // but let's fallback to the custom loading code for the time being. 220a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky UNUSED(elf_filename); 221a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky UNUSED(requested_base); 222a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky UNUSED(abs_dex_location); 223a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky UNUSED(error_msg); 224a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky return false; 225a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#else 226fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe std::unique_ptr<char> absolute_path(realpath(elf_filename.c_str(), nullptr)); 227fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (absolute_path == nullptr) { 228fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str()); 229fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe return false; 230fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 231fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#ifdef HAVE_ANDROID_OS 232fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe android_dlextinfo extinfo; 233a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky extinfo.flags = ANDROID_DLEXT_FORCE_LOAD | ANDROID_DLEXT_FORCE_FIXED_VADDR; 234fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo); 235fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#else 236fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW); 237fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#endif 238fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (dlopen_handle_ == nullptr) { 239fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror()); 240fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe return false; 241fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 242fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe begin_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatdata")); 243fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (begin_ == nullptr) { 244fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe *error_msg = StringPrintf("Failed to find oatdata symbol in '%s': %s", elf_filename.c_str(), 245fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe dlerror()); 246fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe return false; 247fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 248fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (requested_base != nullptr && begin_ != requested_base) { 249fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 250fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: " 251fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe "oatdata=%p != expected=%p, %s. See process maps in the log.", 252fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe begin_, requested_base, elf_filename.c_str()); 253fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe return false; 254fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 255fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe end_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatlastword")); 256fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (end_ == nullptr) { 257fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s': %s", elf_filename.c_str(), 258fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe dlerror()); 259fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe return false; 260fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 261fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // Readjust to be non-inclusive upper bound. 262fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe end_ += sizeof(uint32_t); 263fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 264fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe bss_begin_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatbss")); 265fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (bss_begin_ == nullptr) { 266fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // No .bss section. Clear dlerror(). 267fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe bss_end_ = nullptr; 268fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe dlerror(); 269fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } else { 270fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe bss_end_ = reinterpret_cast<uint8_t*>(dlsym(dlopen_handle_, "oatbsslastword")); 271fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (bss_end_ == nullptr) { 272fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'", 273fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe elf_filename.c_str()); 274fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe return false; 275fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 276fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe // Readjust to be non-inclusive upper bound. 277fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe bss_end_ += sizeof(uint32_t); 278fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 279fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 280a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions. 281a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky struct dl_iterate_context { 282a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky static int callback(struct dl_phdr_info *info, size_t /* size */, void *data) { 283a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky auto* context = reinterpret_cast<dl_iterate_context*>(data); 284a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // See whether this callback corresponds to the file which we have just loaded. 285a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky bool contains_begin = false; 286a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky for (int i = 0; i < info->dlpi_phnum; i++) { 287a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky if (info->dlpi_phdr[i].p_type == PT_LOAD) { 288a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr + 289a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky info->dlpi_phdr[i].p_vaddr); 290a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky size_t memsz = info->dlpi_phdr[i].p_memsz; 291a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) { 292a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky contains_begin = true; 293a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky break; 294a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky } 295a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky } 296a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky } 297a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // Add dummy mmaps for this file. 298a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky if (contains_begin) { 299a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky for (int i = 0; i < info->dlpi_phnum; i++) { 300a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky if (info->dlpi_phdr[i].p_type == PT_LOAD) { 301a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr + 302a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky info->dlpi_phdr[i].p_vaddr); 303a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky size_t memsz = info->dlpi_phdr[i].p_memsz; 304a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky MemMap* mmap = MemMap::MapDummy(info->dlpi_name, vaddr, memsz); 305a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky context->dlopen_mmaps_->push_back(std::unique_ptr<MemMap>(mmap)); 306a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky } 307a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky } 308a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky return 1; // Stop iteration and return 1 from dl_iterate_phdr. 309a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky } 310a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished. 311a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky } 312a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky const uint8_t* const begin_; 313a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky std::vector<std::unique_ptr<MemMap>>* const dlopen_mmaps_; 314a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky } context = { begin_, &dlopen_mmaps_ }; 315a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky 316a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) { 317a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 318a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but can not find its mmaps."; 319a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky } 320a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky 321fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe return Setup(abs_dex_location, error_msg); 322a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky#endif // __APPLE__ 323fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe} 324fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 32546774767fcf7780d1455e755729198648d08742eIgor Murashkinbool OatFile::ElfFileOpen(File* file, uint8_t* requested_base, uint8_t* oat_file_begin, 32646774767fcf7780d1455e755729198648d08742eIgor Murashkin bool writable, bool executable, 327e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 3288d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string* error_msg) { 32946774767fcf7780d1455e755729198648d08742eIgor Murashkin // TODO: rename requested_base to oat_data_begin 33046774767fcf7780d1455e755729198648d08742eIgor Murashkin elf_file_.reset(ElfFile::Open(file, writable, /*program_header_only*/true, error_msg, 33146774767fcf7780d1455e755729198648d08742eIgor Murashkin oat_file_begin)); 332fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (elf_file_ == nullptr) { 3338d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers DCHECK(!error_msg->empty()); 334700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom return false; 335700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom } 3368d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers bool loaded = elf_file_->Load(executable, error_msg); 337700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom if (!loaded) { 3388d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers DCHECK(!error_msg->empty()); 339700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom return false; 340700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom } 341700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom begin_ = elf_file_->FindDynamicSymbolAddress("oatdata"); 342fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (begin_ == nullptr) { 3438d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("Failed to find oatdata symbol in '%s'", file->GetPath().c_str()); 344700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom return false; 345700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom } 346fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (requested_base != nullptr && begin_ != requested_base) { 347a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 3488d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: " 349a6dfdae1cffc78f9791348b2e1dc8f4c6c3f7128Andreas Gampe "oatdata=%p != expected=%p. See process maps in the log.", 3508d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers begin_, requested_base); 351700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom return false; 352700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom } 353700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom end_ = elf_file_->FindDynamicSymbolAddress("oatlastword"); 354fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (end_ == nullptr) { 3558d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s'", file->GetPath().c_str()); 356700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom return false; 357700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom } 358700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom // Readjust to be non-inclusive upper bound. 359700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom end_ += sizeof(uint32_t); 3605c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 3615c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko bss_begin_ = elf_file_->FindDynamicSymbolAddress("oatbss"); 3625c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko if (bss_begin_ == nullptr) { 3635c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko // No .bss section. Clear dlerror(). 3645c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko bss_end_ = nullptr; 3655c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko dlerror(); 3665c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko } else { 3675c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko bss_end_ = elf_file_->FindDynamicSymbolAddress("oatbsslastword"); 3685c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko if (bss_end_ == nullptr) { 3695c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'", 3705c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko file->GetPath().c_str()); 3715c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko return false; 3725c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko } 3735c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko // Readjust to be non-inclusive upper bound. 3745c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko bss_end_ += sizeof(uint32_t); 3755c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko } 3765c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 377e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler return Setup(abs_dex_location, error_msg); 378700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom} 3796e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom 380e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhlerbool OatFile::Setup(const char* abs_dex_location, std::string* error_msg) { 381f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom if (!GetOatHeader().IsValid()) { 3822bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe std::string cause = GetOatHeader().GetValidationErrorMessage(); 3832bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe *error_msg = StringPrintf("Invalid oat header for '%s': %s", GetLocation().c_str(), 3842bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe cause.c_str()); 385f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom return false; 386f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom } 38713735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* oat = Begin(); 388e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat += sizeof(OatHeader); 389fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom if (oat > End()) { 3908d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader", GetLocation().c_str()); 391fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 392fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 393fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom 39422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe oat += GetOatHeader().GetKeyValueStoreSize(); 395fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom if (oat > End()) { 39622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe *error_msg = StringPrintf("In oat file '%s' found truncated variable-size data: " 3978d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers "%p + %zd + %ud <= %p", GetLocation().c_str(), 39822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe Begin(), sizeof(OatHeader), GetOatHeader().GetKeyValueStoreSize(), 3998d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers End()); 400fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 401fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 40281f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom 403aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko uint32_t dex_file_count = GetOatHeader().GetDexFileCount(); 404aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko oat_dex_files_storage_.reserve(dex_file_count); 405aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko for (size_t i = 0; i < dex_file_count; i++) { 40683bef92043a5b9020e99eac076db5f327b36cb7eDmitry Petrochenko uint32_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat); 4078d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(dex_file_location_size == 0U)) { 4088d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with empty location name", 4098d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers GetLocation().c_str(), i); 410fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 411fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 412e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat += sizeof(dex_file_location_size); 4138d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(oat > End())) { 4148d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd truncated after dex file " 4158d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers "location size", GetLocation().c_str(), i); 416fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 417fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 418e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 419e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const char* dex_file_location_data = reinterpret_cast<const char*>(oat); 420e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat += dex_file_location_size; 4218d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(oat > End())) { 4228d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with truncated dex file " 4238d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers "location", GetLocation().c_str(), i); 424fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 425fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 426e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 427e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler std::string dex_file_location = ResolveRelativeEncodedDexLocation( 428e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler abs_dex_location, 429e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler std::string(dex_file_location_data, dex_file_location_size)); 430e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 431e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom uint32_t dex_file_checksum = *reinterpret_cast<const uint32_t*>(oat); 432e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat += sizeof(dex_file_checksum); 4338d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(oat > End())) { 4348d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated after " 4358d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers "dex file checksum", GetLocation().c_str(), i, 4368d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers dex_file_location.c_str()); 437fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 438fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 439e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 44089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom uint32_t dex_file_offset = *reinterpret_cast<const uint32_t*>(oat); 4418d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(dex_file_offset == 0U)) { 4428d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with zero dex " 4438d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers "file offset", GetLocation().c_str(), i, dex_file_location.c_str()); 444fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 445fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 4468d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(dex_file_offset > Size())) { 4478d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with dex file " 4488d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers "offset %ud > %zd", GetLocation().c_str(), i, 4498d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers dex_file_location.c_str(), dex_file_offset, Size()); 450fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 451fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 45289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom oat += sizeof(dex_file_offset); 4538d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(oat > End())) { 4548d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated " 45537628b7528e5611088ec046d9c2295e12c1f9b08Brian Carlstrom "after dex file offsets", GetLocation().c_str(), i, 4568d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers dex_file_location.c_str()); 457fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 458fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 45989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 460700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom const uint8_t* dex_file_pointer = Begin() + dex_file_offset; 4618d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) { 4628d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid " 46337628b7528e5611088ec046d9c2295e12c1f9b08Brian Carlstrom "dex file magic '%s'", GetLocation().c_str(), i, 4648d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers dex_file_location.c_str(), dex_file_pointer); 465fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 466fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 4678d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) { 4688d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with invalid " 46937628b7528e5611088ec046d9c2295e12c1f9b08Brian Carlstrom "dex file version '%s'", GetLocation().c_str(), i, 4708d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers dex_file_location.c_str(), dex_file_pointer); 471fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 472fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 4736e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer); 4746e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom const uint32_t* methods_offsets_pointer = reinterpret_cast<const uint32_t*>(oat); 47589521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 4766e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_); 4778d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(oat > End())) { 4788d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with truncated " 47937628b7528e5611088ec046d9c2295e12c1f9b08Brian Carlstrom "method offsets", GetLocation().c_str(), i, 4808d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers dex_file_location.c_str()); 481fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 482fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 483e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 484aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str()); 485aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko 486aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko // Create the OatDexFile and add it to the owning container. 487539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko OatDexFile* oat_dex_file = new OatDexFile(this, 488539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko dex_file_location, 489aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko canonical_location, 490539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko dex_file_checksum, 491539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko dex_file_pointer, 492539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko methods_offsets_pointer); 493aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko oat_dex_files_storage_.push_back(oat_dex_file); 494aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko 495aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko // Add the location and canonical location (if different) to the oat_dex_files_ table. 4963f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko StringPiece key(oat_dex_file->GetDexFileLocation()); 497539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko oat_dex_files_.Put(key, oat_dex_file); 498aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko if (canonical_location != dex_file_location) { 499aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko StringPiece canonical_key(oat_dex_file->GetCanonicalDexFileLocation()); 500aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko oat_dex_files_.Put(canonical_key, oat_dex_file); 501aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko } 502e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 503f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom return true; 504e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 505e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 506e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromconst OatHeader& OatFile::GetOatHeader() const { 50730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers return *reinterpret_cast<const OatHeader*>(Begin()); 508e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 509e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 51013735955f39b3b304c37d2b2840663c131262c18Ian Rogersconst uint8_t* OatFile::Begin() const { 511fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe CHECK(begin_ != nullptr); 512700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom return begin_; 513e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 514e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 51513735955f39b3b304c37d2b2840663c131262c18Ian Rogersconst uint8_t* OatFile::End() const { 516fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe CHECK(end_ != nullptr); 517700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom return end_; 518e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 519e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 5205c42c29b89286e5efa4a4613132b09051ce5945bVladimir Markoconst uint8_t* OatFile::BssBegin() const { 5215c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko return bss_begin_; 5225c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko} 5235c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 5245c42c29b89286e5efa4a4613132b09051ce5945bVladimir Markoconst uint8_t* OatFile::BssEnd() const { 5255c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko return bss_end_; 5265c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko} 5275c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 5288d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogersconst OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location, 5298d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers const uint32_t* dex_location_checksum, 5307fe2c691866ad643b9e21dd2c9d36fa79ec454c3Ian Rogers bool warn_if_not_found) const { 5313f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // NOTE: We assume here that the canonical location for a given dex_location never 5323f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // changes. If it does (i.e. some symlink used by the filename changes) we may return 5333f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // an incorrect OatDexFile. As long as we have a checksum to check, we shall return 5343f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // an identical file or fail; otherwise we may see some unpredictable failures. 5353f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko 5363f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // TODO: Additional analysis of usage patterns to see if this can be simplified 5373f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // without any performance loss, for example by not doing the first lock-free lookup. 5383f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko 5393f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko const OatFile::OatDexFile* oat_dex_file = nullptr; 5403f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko StringPiece key(dex_location); 5413f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations 5423f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // directly mentioned in the oat file and doesn't require locking. 5433f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko auto primary_it = oat_dex_files_.find(key); 5443f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko if (primary_it != oat_dex_files_.end()) { 5453f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko oat_dex_file = primary_it->second; 5463f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko DCHECK(oat_dex_file != nullptr); 5473f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko } else { 5483f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // This dex_location is not one of the dex locations directly mentioned in the 5493f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // oat file. The correct lookup is via the canonical location but first see in 5503f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // the secondary_oat_dex_files_ whether we've looked up this location before. 5513f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko MutexLock mu(Thread::Current(), secondary_lookup_lock_); 5523f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko auto secondary_lb = secondary_oat_dex_files_.lower_bound(key); 5533f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) { 5542cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier oat_dex_file = secondary_lb->second; // May be null. 5553f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko } else { 5563f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // We haven't seen this dex_location before, we must check the canonical location. 5573f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location); 558aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko if (dex_canonical_location != dex_location) { 559aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko StringPiece canonical_key(dex_canonical_location); 560aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko auto canonical_it = oat_dex_files_.find(canonical_key); 561aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko if (canonical_it != oat_dex_files_.end()) { 562aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko oat_dex_file = canonical_it->second; 5632cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier } // else keep null. 5642cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier } // else keep null. 5653f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko 5663f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // Copy the key to the string_cache_ and store the result in secondary map. 5673f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko string_cache_.emplace_back(key.data(), key.length()); 5683f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko StringPiece key_copy(string_cache_.back()); 5693f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file); 570756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom } 571756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom } 5723f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko if (oat_dex_file != nullptr && 5733f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko (dex_location_checksum == nullptr || 5743f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko oat_dex_file->GetDexFileLocationChecksum() == *dex_location_checksum)) { 5753f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko return oat_dex_file; 5763f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko } 577756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom 578756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom if (warn_if_not_found) { 5793f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location); 5800d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom std::string checksum("<unspecified>"); 581fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (dex_location_checksum != nullptr) { 5820d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom checksum = StringPrintf("0x%08x", *dex_location_checksum); 5830d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom } 584756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_location 5854e1d579d6401fef2dd57b16f8d406e33221a69d9Calin Juravle << " ( canonical path " << dex_canonical_location << ")" 5860d6adac2550113da33d42e88f0d87a57b25c5a60Brian Carlstrom << " with checksum " << checksum << " in OatFile " << GetLocation(); 587756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom if (kIsDebugBuild) { 588aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko for (const OatDexFile* odf : oat_dex_files_storage_) { 589756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom LOG(WARNING) << "OatFile " << GetLocation() 590aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko << " contains OatDexFile " << odf->GetDexFileLocation() 591aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko << " (canonical path " << odf->GetCanonicalDexFileLocation() << ")" 592aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko << " with checksum 0x" << std::hex << odf->GetDexFileLocationChecksum(); 5937571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom } 5947fe2c691866ad643b9e21dd2c9d36fa79ec454c3Ian Rogers } 595aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 5964e1d579d6401fef2dd57b16f8d406e33221a69d9Calin Juravle 597fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe return nullptr; 598aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom} 599aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 600e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::OatDexFile::OatDexFile(const OatFile* oat_file, 601aa6a588eb83288481389aa08b03105346a87e706Elliott Hughes const std::string& dex_file_location, 602aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko const std::string& canonical_dex_file_location, 6035b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom uint32_t dex_file_location_checksum, 60413735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* dex_file_pointer, 6050755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom const uint32_t* oat_class_offsets_pointer) 606e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom : oat_file_(oat_file), 607e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_location_(dex_file_location), 608aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko canonical_dex_file_location_(canonical_dex_file_location), 6095b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom dex_file_location_checksum_(dex_file_location_checksum), 61089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom dex_file_pointer_(dex_file_pointer), 6110755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom oat_class_offsets_pointer_(oat_class_offsets_pointer) {} 612e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 613e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::OatDexFile::~OatDexFile() {} 614e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 61505f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogerssize_t OatFile::OatDexFile::FileSize() const { 61605f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_; 61705f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers} 61805f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers 619fbef44de596d298dc6430f482dffc933a046dd28Richard Uhlerstd::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const { 62005f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers return DexFile::Open(dex_file_pointer_, FileSize(), dex_file_location_, 62107b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler dex_file_location_checksum_, this, error_msg); 62289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom} 62389521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 6242cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromuint32_t OatFile::OatDexFile::GetOatClassOffset(uint16_t class_def_index) const { 6252cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom return oat_class_offsets_pointer_[class_def_index]; 6262cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom} 6272cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom 628d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir MarkoOatFile::OatClass OatFile::OatDexFile::GetOatClass(uint16_t class_def_index) const { 6292cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom uint32_t oat_class_offset = GetOatClassOffset(class_def_index); 6300755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 63113735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* oat_class_pointer = oat_file_->Begin() + oat_class_offset; 6327571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation(); 6330755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 63413735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* status_pointer = oat_class_pointer; 635ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation(); 636ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom mirror::Class::Status status = 637ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom static_cast<mirror::Class::Status>(*reinterpret_cast<const int16_t*>(status_pointer)); 638ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LT(status, mirror::Class::kStatusMax); 639ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 64013735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* type_pointer = status_pointer + sizeof(uint16_t); 641ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation(); 642ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom OatClassType type = static_cast<OatClassType>(*reinterpret_cast<const uint16_t*>(type_pointer)); 643ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LT(type, kOatClassMax); 644ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 64513735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* after_type_pointer = type_pointer + sizeof(int16_t); 646cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom CHECK_LE(after_type_pointer, oat_file_->End()) << oat_file_->GetLocation(); 647cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom 648ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t bitmap_size = 0; 64913735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* bitmap_pointer = nullptr; 65013735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* methods_pointer = nullptr; 65197b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers if (type != kOatClassNoneCompiled) { 65297b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers if (type == kOatClassSomeCompiled) { 65397b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers bitmap_size = static_cast<uint32_t>(*reinterpret_cast<const uint32_t*>(after_type_pointer)); 65497b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers bitmap_pointer = after_type_pointer + sizeof(bitmap_size); 65597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers CHECK_LE(bitmap_pointer, oat_file_->End()) << oat_file_->GetLocation(); 65697b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers methods_pointer = bitmap_pointer + bitmap_size; 65797b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers } else { 65897b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers methods_pointer = after_type_pointer; 65997b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers } 66097b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation(); 661ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 6620755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 66307b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler return OatFile::OatClass(oat_file_, 66407b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler status, 66507b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler type, 66607b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler bitmap_size, 66707b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler reinterpret_cast<const uint32_t*>(bitmap_pointer), 66807b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler reinterpret_cast<const OatMethodOffsets*>(methods_pointer)); 669e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 670e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 6710755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian CarlstromOatFile::OatClass::OatClass(const OatFile* oat_file, 6722dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class::Status status, 673ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom OatClassType type, 674ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t bitmap_size, 675ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom const uint32_t* bitmap_pointer, 6760755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom const OatMethodOffsets* methods_pointer) 677ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom : oat_file_(oat_file), status_(status), type_(type), 678d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko bitmap_(bitmap_pointer), methods_pointer_(methods_pointer) { 679ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom switch (type_) { 680ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom case kOatClassAllCompiled: { 681ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(0U, bitmap_size); 682cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom CHECK(bitmap_pointer == nullptr); 68397b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers CHECK(methods_pointer != nullptr); 684ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom break; 685ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 686ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom case kOatClassSomeCompiled: { 687ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_NE(0U, bitmap_size); 688cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom CHECK(bitmap_pointer != nullptr); 68997b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers CHECK(methods_pointer != nullptr); 690ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom break; 691ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 692ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom case kOatClassNoneCompiled: { 693ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(0U, bitmap_size); 694cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom CHECK(bitmap_pointer == nullptr); 69597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers CHECK(methods_pointer_ == nullptr); 696ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom break; 697ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 698ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom case kOatClassMax: { 699ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom LOG(FATAL) << "Invalid OatClassType " << type_; 700ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom break; 701ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 702ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 703ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom} 704e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 7052cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromuint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const { 7062cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index); 7072cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom if (oat_method_offsets == nullptr) { 7082cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom return 0u; 7092cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom } 7102cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin(); 7112cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom} 7122cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom 7132cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromconst OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const { 714d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index. 7152cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom if (methods_pointer_ == nullptr) { 716ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(kOatClassNoneCompiled, type_); 7172cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom return nullptr; 718ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 719ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_t methods_pointer_index; 7202cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom if (bitmap_ == nullptr) { 721ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(kOatClassAllCompiled, type_); 722ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom methods_pointer_index = method_index; 723ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } else { 724ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(kOatClassSomeCompiled, type_); 725d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko if (!BitVector::IsBitSet(bitmap_, method_index)) { 7262cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom return nullptr; 727ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 728d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index); 729d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko methods_pointer_index = num_set_bits; 730ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 731ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index]; 7322cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom return &oat_method_offsets; 7332cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom} 7342cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom 7352cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromconst OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const { 7362cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index); 7372cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom if (oat_method_offsets == nullptr) { 738957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier return OatMethod(nullptr, 0); 7392cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom } 7402cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom if (oat_file_->IsExecutable() || 7412cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom Runtime::Current() == nullptr || // This case applies for oatdump. 742e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier Runtime::Current()->IsAotCompiler()) { 743957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_); 7449dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light } 745e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier // We aren't allowed to use the compiled code. We just force it down the interpreted / jit 746e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier // version. 747e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return OatMethod(oat_file_->Begin(), 0); 7483320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom} 7493320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 7503d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartiervoid OatFile::OatMethod::LinkMethod(ArtMethod* method) const { 751fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe CHECK(method != nullptr); 752ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers method->SetEntryPointFromQuickCompiledCode(GetQuickCode()); 753ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom} 754ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 7557ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampebool OatFile::IsPic() const { 75646774767fcf7780d1455e755729198648d08742eIgor Murashkin return GetOatHeader().IsPic(); 7577ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe // TODO: Check against oat_patches. b/18144996 7587ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe} 7597ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe 760094ff2c0c1f736521c634d5f606e274cb6c55345Sebastien Hertzbool OatFile::IsDebuggable() const { 761094ff2c0c1f736521c634d5f606e274cb6c55345Sebastien Hertz return GetOatHeader().IsDebuggable(); 762094ff2c0c1f736521c634d5f606e274cb6c55345Sebastien Hertz} 763094ff2c0c1f736521c634d5f606e274cb6c55345Sebastien Hertz 7647848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampestatic constexpr char kDexClassPathEncodingSeparator = '*'; 7657848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 7667848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampestd::string OatFile::EncodeDexFileDependencies(const std::vector<const DexFile*>& dex_files) { 7677848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe std::ostringstream out; 7687848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 7697848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe for (const DexFile* dex_file : dex_files) { 7707848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe out << dex_file->GetLocation().c_str(); 7717848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe out << kDexClassPathEncodingSeparator; 7727848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe out << dex_file->GetLocationChecksum(); 7737848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe out << kDexClassPathEncodingSeparator; 7747848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe } 7757848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 7767848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe return out.str(); 7777848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe} 7787848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 7797848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampebool OatFile::CheckStaticDexFileDependencies(const char* dex_dependencies, std::string* msg) { 7807848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe if (dex_dependencies == nullptr || dex_dependencies[0] == 0) { 7817848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // No dependencies. 7827848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe return true; 7837848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe } 7847848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 7857848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // Assumption: this is not performance-critical. So it's OK to do this with a std::string and 7867848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // Split() instead of manual parsing of the combined char*. 7877848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe std::vector<std::string> split; 7887848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe Split(dex_dependencies, kDexClassPathEncodingSeparator, &split); 7897848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe if (split.size() % 2 != 0) { 7907848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // Expected pairs of location and checksum. 7917848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe *msg = StringPrintf("Odd number of elements in dependency list %s", dex_dependencies); 7927848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe return false; 7937848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe } 7947848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 7957848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe for (auto it = split.begin(), end = split.end(); it != end; it += 2) { 7967848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe std::string& location = *it; 7977848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe std::string& checksum = *(it + 1); 7987848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe int64_t converted = strtoll(checksum.c_str(), nullptr, 10); 7997848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe if (converted == 0) { 8007848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // Conversion error. 8017848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe *msg = StringPrintf("Conversion error for %s", checksum.c_str()); 8027848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe return false; 8037848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe } 8047848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 8057848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe uint32_t dex_checksum; 8067848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe std::string error_msg; 8077848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe if (DexFile::GetChecksum(DexFile::GetDexCanonicalLocation(location.c_str()).c_str(), 8087848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe &dex_checksum, 8097848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe &error_msg)) { 8107848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe if (converted != dex_checksum) { 8117848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe *msg = StringPrintf("Checksums don't match for %s: %" PRId64 " vs %u", 8127848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe location.c_str(), converted, dex_checksum); 8137848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe return false; 8147848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe } 8157848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe } else { 8167848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // Problem retrieving checksum. 8177848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // TODO: odex files? 8187848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe *msg = StringPrintf("Could not retrieve checksum for %s: %s", location.c_str(), 8197848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe error_msg.c_str()); 8207848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe return false; 8217848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe } 8227848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe } 8237848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 8247848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe return true; 8257848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe} 8267848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 8277848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampebool OatFile::GetDexLocationsFromDependencies(const char* dex_dependencies, 8287848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe std::vector<std::string>* locations) { 8297848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe DCHECK(locations != nullptr); 8307848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe if (dex_dependencies == nullptr || dex_dependencies[0] == 0) { 8317848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe return true; 8327848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe } 8337848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 8347848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // Assumption: this is not performance-critical. So it's OK to do this with a std::string and 8357848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // Split() instead of manual parsing of the combined char*. 8367848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe std::vector<std::string> split; 8377848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe Split(dex_dependencies, kDexClassPathEncodingSeparator, &split); 8387848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe if (split.size() % 2 != 0) { 8397848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // Expected pairs of location and checksum. 8407848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe return false; 8417848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe } 8427848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 8437848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe for (auto it = split.begin(), end = split.end(); it != end; it += 2) { 8447848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe locations->push_back(*it); 8457848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe } 8467848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 8477848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe return true; 8487848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe} 8497848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 850e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} // namespace art 851