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> 2106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko#include <type_traits> 22daab38ca60c5b91787e29c87a161a2bb8c1b6f11Andreas Gampe#include <unistd.h> 23700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 247848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe#include <cstdlib> 251baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky#ifndef __APPLE__ 261baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky#include <link.h> // for dl_iterate_phdr. 271baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky#endif 28e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler#include <sstream> 29e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler 30fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// dlopen_ext support from bionic. 31bb661c0f0cb72d4bbfc2e251f6ded6949a713292Bilyan Borisov#ifdef ART_TARGET_ANDROID 32fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#include "android/dlext.h" 33fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe#endif 34fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 3546ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe#include "android-base/stringprintf.h" 3646ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe 37c6ea7d00ad069a2736f603daa3d8eaa9a1f8ea11Andreas Gampe#include "art_method.h" 38ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom#include "base/bit_vector.h" 39542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe#include "base/enums.h" 401aa246dec5abe212f699de1413a0c4a191ca364aElliott Hughes#include "base/stl_util.h" 4132ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier#include "base/systrace.h" 42761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h" 43a5b09a67034e57a6e10231dd4bd92f4cb50b824cAndreas Gampe#include "dex_file_types.h" 44700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "elf_file.h" 4584d7605f93f1e6e86a16e02017e305c90e93117aAlex Light#include "elf_utils.h" 46aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko#include "gc_root.h" 47700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "oat.h" 481baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky#include "mem_map.h" 492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h" 504f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h" 51c04c800e7bda94abfadc8c2d30f58c50b261b612Nicolas Geoffray#include "oat_file-inl.h" 52f9c6fc610b27887f832e453a0da1789187293408Mathieu Chartier#include "oat_file_manager.h" 53e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "os.h" 5422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe#include "runtime.h" 559bdf108885a27ba05fae8501725649574d7c491bVladimir Marko#include "type_lookup_table.h" 569aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr#include "utf-inl.h" 572dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "utils.h" 5809d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko#include "utils/dex_cache_arrays_layout-inl.h" 5997d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko#include "vdex_file.h" 60e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 61e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art { 62e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 6346ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampeusing android::base::StringPrintf; 6446ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe 65049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// Whether OatFile::Open will try dlopen. Fallback is our own ELF loader. 661baabf0726eb285284e0c908ccba9f209b399faeDavid Srbeckystatic constexpr bool kUseDlopen = true; 67fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 68049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// Whether OatFile::Open will try dlopen on the host. On the host we're not linking against 69fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// bionic, so cannot take advantage of the support for changed semantics (loading the same soname 70fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// multiple times). However, if/when we switch the above, we likely want to switch this, too, 71fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// to get test coverage of the code paths. 721baabf0726eb285284e0c908ccba9f209b399faeDavid Srbeckystatic constexpr bool kUseDlopenOnHost = true; 73fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 74fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe// For debugging, Open will print DlOpen error message if set to true. 75fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampestatic constexpr bool kPrintDlOpenErrorMessage = false; 76fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 77049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// Note for OatFileBase and descendents: 78049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 79049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// These are used in OatFile::Open to try all our loaders. 80049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 81049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// The process is simple: 82049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 83049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 1) Allocate an instance through the standard constructor (location, executable) 84049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 2) Load() to try to open the file. 85049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 3) ComputeFields() to populate the OatFile fields like begin_, using FindDynamicSymbolAddress. 86049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 4) PreSetup() for any steps that should be done before the final setup. 87049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// 5) Setup() to complete the procedure. 88049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 89049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampeclass OatFileBase : public OatFile { 90049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe public: 91049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe virtual ~OatFileBase() {} 92049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 93049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe template <typename kOatFileBaseSubType> 947b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil static OatFileBase* OpenOatFile(const std::string& vdex_filename, 957b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil const std::string& elf_filename, 9684d7605f93f1e6e86a16e02017e305c90e93117aAlex Light const std::string& location, 97049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* requested_base, 98049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, 99049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool writable, 100049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool executable, 1010b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool low_4gb, 102e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 103049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg); 104fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 105049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe protected: 106049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe OatFileBase(const std::string& filename, bool executable) : OatFile(filename, executable) {} 107fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 108049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe virtual const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name, 109049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) const = 0; 110956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes 1114075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe virtual void PreLoad() = 0; 1124075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe 1137b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil bool LoadVdex(const std::string& vdex_filename, 1147b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil bool writable, 1157b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil bool low_4gb, 1167b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil std::string* error_msg); 1177b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil 118049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe virtual bool Load(const std::string& elf_filename, 119049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, 120049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool writable, 121049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool executable, 1220b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool low_4gb, 123049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) = 0; 124e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 125049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool ComputeFields(uint8_t* requested_base, 126049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const std::string& file_path, 127049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg); 128700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 129049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe virtual void PreSetup(const std::string& elf_filename) = 0; 130a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light 131049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool Setup(const char* abs_dex_location, std::string* error_msg); 132fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 133049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // Setters exposed for ElfOatFile. 134e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 135049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe void SetBegin(const uint8_t* begin) { 136049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe begin_ = begin; 137e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier } 138e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 139049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe void SetEnd(const uint8_t* end) { 140049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe end_ = end; 141700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom } 142e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 143c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil void SetVdex(VdexFile* vdex) { 144c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil vdex_.reset(vdex); 145c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil } 146c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil 147049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe private: 148049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe DISALLOW_COPY_AND_ASSIGN(OatFileBase); 149049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}; 150049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 151049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampetemplate <typename kOatFileBaseSubType> 1527b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David BrazdilOatFileBase* OatFileBase::OpenOatFile(const std::string& vdex_filename, 1537b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil const std::string& elf_filename, 154049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const std::string& location, 155049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* requested_base, 156049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, 157049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool writable, 158049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool executable, 1590b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool low_4gb, 160049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const char* abs_dex_location, 161049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) { 162049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable)); 1634075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe 1644075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe ret->PreLoad(); 1654075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe 1667b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil if (kIsVdexEnabled && !ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) { 1677b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil return nullptr; 1687b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil } 1697b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil 170049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (!ret->Load(elf_filename, 171049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe oat_file_begin, 172049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe writable, 173049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe executable, 1740b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier low_4gb, 175049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe error_msg)) { 176049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return nullptr; 177fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 178fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 179049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (!ret->ComputeFields(requested_base, elf_filename, error_msg)) { 180049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return nullptr; 181fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe } 1824075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe 183049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe ret->PreSetup(elf_filename); 1841baabf0726eb285284e0c908ccba9f209b399faeDavid Srbecky 185049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (!ret->Setup(abs_dex_location, error_msg)) { 186049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return nullptr; 1875dedb808acf84712daf7dee3cf8137d4e34b4b78David Srbecky } 1885dedb808acf84712daf7dee3cf8137d4e34b4b78David Srbecky 189049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return ret.release(); 190fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe} 191fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 1927b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdilbool OatFileBase::LoadVdex(const std::string& vdex_filename, 1937b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil bool writable, 1947b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil bool low_4gb, 1957b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil std::string* error_msg) { 196cab655799dc0c04d42b00642a813438efe46acf5Nicolas Geoffray vdex_ = VdexFile::Open(vdex_filename, writable, low_4gb, /* unquicken*/ false, error_msg); 1977b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil if (vdex_.get() == nullptr) { 1987b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil *error_msg = StringPrintf("Failed to load vdex file '%s' %s", 1997b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil vdex_filename.c_str(), 2007b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil error_msg->c_str()); 2017b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil return false; 2027b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil } 2037b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil return true; 2047b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil} 2057b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil 206049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool OatFileBase::ComputeFields(uint8_t* requested_base, 207049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const std::string& file_path, 208049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) { 209049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string symbol_error_msg; 210049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe begin_ = FindDynamicSymbolAddress("oatdata", &symbol_error_msg); 211fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (begin_ == nullptr) { 212049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = StringPrintf("Failed to find oatdata symbol in '%s' %s", 213049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe file_path.c_str(), 214049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe symbol_error_msg.c_str()); 215700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom return false; 216700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom } 217fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (requested_base != nullptr && begin_ != requested_base) { 218f97cf2a7d8089ca74a4920a5e0c351e070cc6e60Nicolas Geoffray // Host can fail this check. Do not dump there to avoid polluting the output. 2197ec0904eac1d799d3443b4c5e83545b72eae9ad3Andreas Gampe if (kIsTargetBuild && (kIsDebugBuild || VLOG_IS_ON(oat))) { 220f97cf2a7d8089ca74a4920a5e0c351e070cc6e60Nicolas Geoffray PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 221f97cf2a7d8089ca74a4920a5e0c351e070cc6e60Nicolas Geoffray } 2228d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: " 223049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe "oatdata=%p != expected=%p. See process maps in the log.", 224049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe begin_, requested_base); 225700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom return false; 226700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom } 227049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe end_ = FindDynamicSymbolAddress("oatlastword", &symbol_error_msg); 228fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe if (end_ == nullptr) { 229049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s' %s", 230049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe file_path.c_str(), 231049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe symbol_error_msg.c_str()); 232700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom return false; 233700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom } 234700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom // Readjust to be non-inclusive upper bound. 235700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom end_ += sizeof(uint32_t); 2365c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 237049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg)); 2385c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko if (bss_begin_ == nullptr) { 239049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // No .bss section. 2405c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko bss_end_ = nullptr; 2415c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko } else { 242049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bss_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbsslastword", &symbol_error_msg)); 2435c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko if (bss_end_ == nullptr) { 244049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'", file_path.c_str()); 2455c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko return false; 2465c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko } 2475c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko // Readjust to be non-inclusive upper bound. 2485c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko bss_end_ += sizeof(uint32_t); 249aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko // Find bss roots if present. 250aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko bss_roots_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssroots", &symbol_error_msg)); 2515c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko } 2525c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 253049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return true; 254700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom} 2556e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom 25606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko// Read an unaligned entry from the OatDexFile data in OatFile and advance the read 25706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko// position by the number of bytes read, i.e. sizeof(T). 25806d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko// Return true on success, false if the read would go beyond the end of the OatFile. 25906d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Markotemplate <typename T> 260722fa98e0ed3796575930eb8e3d5fc89046f01ccVladimir Markoinline static bool ReadOatDexFileData(const OatFile& oat_file, 261722fa98e0ed3796575930eb8e3d5fc89046f01ccVladimir Marko /*inout*/const uint8_t** oat, 262722fa98e0ed3796575930eb8e3d5fc89046f01ccVladimir Marko /*out*/T* value) { 26306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko DCHECK(oat != nullptr); 26406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko DCHECK(value != nullptr); 26506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko DCHECK_LE(*oat, oat_file.End()); 26606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko if (UNLIKELY(static_cast<size_t>(oat_file.End() - *oat) < sizeof(T))) { 26706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko return false; 26806d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko } 26906d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko static_assert(std::is_trivial<T>::value, "T must be a trivial type"); 27006d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko typedef __attribute__((__aligned__(1))) T unaligned_type; 27106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *value = *reinterpret_cast<const unaligned_type*>(*oat); 27206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *oat += sizeof(T); 27306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko return true; 27406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko} 27506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko 276c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodsonstatic bool FindDexFileMapItem(const uint8_t* dex_begin, 277c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson const uint8_t* dex_end, 278c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson DexFile::MapItemType map_item_type, 279c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson const DexFile::MapItem** result_item) { 280c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson *result_item = nullptr; 281c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson 282c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson const DexFile::Header* header = 283c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson BoundsCheckedCast<const DexFile::Header*>(dex_begin, dex_begin, dex_end); 284c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson if (nullptr == header) return false; 285c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson 286c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson if (!DexFile::IsMagicValid(header->magic_)) return true; // Not a dex file, not an error. 287c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson 288c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson const DexFile::MapList* map_list = 289c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson BoundsCheckedCast<const DexFile::MapList*>(dex_begin + header->map_off_, dex_begin, dex_end); 290c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson if (nullptr == map_list) return false; 291c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson 292c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson const DexFile::MapItem* map_item = map_list->list_; 293c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson size_t count = map_list->size_; 294c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson while (count--) { 295c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson if (map_item->type_ == static_cast<uint16_t>(map_item_type)) { 296c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson *result_item = map_item; 297c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson break; 298c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson } 299c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson map_item = BoundsCheckedCast<const DexFile::MapItem*>(map_item + 1, dex_begin, dex_end); 300c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson if (nullptr == map_item) return false; 301c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson } 302c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson 303c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson return true; 304c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson} 305c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson 306049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) { 307f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom if (!GetOatHeader().IsValid()) { 3082bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe std::string cause = GetOatHeader().GetValidationErrorMessage(); 30906d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("Invalid oat header for '%s': %s", 31006d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 3112bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe cause.c_str()); 312f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom return false; 313f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom } 31413735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* oat = Begin(); 315e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat += sizeof(OatHeader); 316fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom if (oat > End()) { 3178d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader", GetLocation().c_str()); 318fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 319fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 320fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom 32122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe oat += GetOatHeader().GetKeyValueStoreSize(); 322fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom if (oat > End()) { 32322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe *error_msg = StringPrintf("In oat file '%s' found truncated variable-size data: " 32406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko "%p + %zu + %u <= %p", 32506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 32606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko Begin(), 32706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko sizeof(OatHeader), 32806d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetOatHeader().GetKeyValueStoreSize(), 3298d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers End()); 330fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 331fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 33281f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom 333aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko if (!IsAligned<alignof(GcRoot<mirror::Object>)>(bss_begin_) || 334aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_roots_) || 335aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_end_)) { 336aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found unaligned bss symbol(s): " 337aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko "begin = %p, roots = %p, end = %p", 338aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko GetLocation().c_str(), 339aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko bss_begin_, 340aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko bss_roots_, 341aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko bss_end_); 342aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko return false; 343aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko } 344aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko 345aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko if (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) { 346aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found bss roots outside .bss: " 347aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko "%p is outside range [%p, %p]", 348aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko GetLocation().c_str(), 349aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko bss_roots_, 350aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko bss_begin_, 351aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko bss_end_); 352aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko return false; 353aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko } 354aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko 355542451cc546779f5c67840e105c51205a1b0a8fdAndreas Gampe PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet()); 3561998cd02603197f2acdc0734397a6d48b2f59b80Vladimir Marko uint8_t* dex_cache_arrays = (bss_begin_ == bss_roots_) ? nullptr : bss_begin_; 3571998cd02603197f2acdc0734397a6d48b2f59b80Vladimir Marko uint8_t* dex_cache_arrays_end = 3581998cd02603197f2acdc0734397a6d48b2f59b80Vladimir Marko (bss_begin_ == bss_roots_) ? nullptr : (bss_roots_ != nullptr) ? bss_roots_ : bss_end_; 3591998cd02603197f2acdc0734397a6d48b2f59b80Vladimir Marko DCHECK_EQ(dex_cache_arrays != nullptr, dex_cache_arrays_end != nullptr); 360aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko uint32_t dex_file_count = GetOatHeader().GetDexFileCount(); 361aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko oat_dex_files_storage_.reserve(dex_file_count); 362aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko for (size_t i = 0; i < dex_file_count; i++) { 36306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko uint32_t dex_file_location_size; 36406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) { 36506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file " 36606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko "location size", 36706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 36806d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko i); 369fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 370fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 37106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko if (UNLIKELY(dex_file_location_size == 0U)) { 37206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name", 37306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 37406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko i); 375fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 376fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 3779bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) { 37806d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file " 37906d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko "location", 38006d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 38106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko i); 382fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 383fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 3849bdf108885a27ba05fae8501725649574d7c491bVladimir Marko const char* dex_file_location_data = reinterpret_cast<const char*>(oat); 3859bdf108885a27ba05fae8501725649574d7c491bVladimir Marko oat += dex_file_location_size; 386e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 387e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler std::string dex_file_location = ResolveRelativeEncodedDexLocation( 388e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler abs_dex_location, 389e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler std::string(dex_file_location_data, dex_file_location_size)); 390e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 39106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko uint32_t dex_file_checksum; 39206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) { 39306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after " 39406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko "dex file checksum", 39506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 39606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko i, 3978d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers dex_file_location.c_str()); 398fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 399fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 400e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 40106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko uint32_t dex_file_offset; 40206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) { 40306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated " 40406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko "after dex file offsets", 40506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 40606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko i, 40706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko dex_file_location.c_str()); 408fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 409fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 41006d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko if (UNLIKELY(dex_file_offset == 0U)) { 41106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with zero dex " 41206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko "file offset", 41306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 41406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko i, 41506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko dex_file_location.c_str()); 416fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 417fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 4187b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil if (UNLIKELY(dex_file_offset > DexSize())) { 41906d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file " 42006d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko "offset %u > %zu", 42106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 42206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko i, 42306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko dex_file_location.c_str(), 42406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko dex_file_offset, 4257b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil DexSize()); 426fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 427fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 4287b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) { 4299bdf108885a27ba05fae8501725649574d7c491bVladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file " 4309bdf108885a27ba05fae8501725649574d7c491bVladimir Marko "offset %u of %zu but the size of dex file header is %zu", 4319bdf108885a27ba05fae8501725649574d7c491bVladimir Marko GetLocation().c_str(), 4329bdf108885a27ba05fae8501725649574d7c491bVladimir Marko i, 4339bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file_location.c_str(), 4349bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file_offset, 4357b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil DexSize(), 4369bdf108885a27ba05fae8501725649574d7c491bVladimir Marko sizeof(DexFile::Header)); 4379bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 4389bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 43989521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 4407b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil const uint8_t* dex_file_pointer = DexBegin() + dex_file_offset; 4418d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) { 44206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid " 44306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko "dex file magic '%s'", 44406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 44506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko i, 44606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko dex_file_location.c_str(), 44706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko dex_file_pointer); 448fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 449fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 4508d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) { 45106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid " 45206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko "dex file version '%s'", 45306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 45406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko i, 45506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko dex_file_location.c_str(), 45606d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko dex_file_pointer); 457fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 458fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 4596e3b1d900cc456a2717944f1f562a2f4df000705Brian Carlstrom const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer); 4607b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil if (DexSize() - dex_file_offset < header->file_size_) { 4619bdf108885a27ba05fae8501725649574d7c491bVladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file " 4629bdf108885a27ba05fae8501725649574d7c491bVladimir Marko "offset %u and size %u truncated at %zu", 4639bdf108885a27ba05fae8501725649574d7c491bVladimir Marko GetLocation().c_str(), 4649bdf108885a27ba05fae8501725649574d7c491bVladimir Marko i, 4659bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file_location.c_str(), 4669bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file_offset, 4679bdf108885a27ba05fae8501725649574d7c491bVladimir Marko header->file_size_, 4687b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil DexSize()); 4699bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 4709bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 471d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko 4729bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t class_offsets_offset; 4739bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) { 4749bdf108885a27ba05fae8501725649574d7c491bVladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated " 4759bdf108885a27ba05fae8501725649574d7c491bVladimir Marko "after class offsets offset", 4769bdf108885a27ba05fae8501725649574d7c491bVladimir Marko GetLocation().c_str(), 4779bdf108885a27ba05fae8501725649574d7c491bVladimir Marko i, 478d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko dex_file_location.c_str()); 479d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko return false; 480d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko } 4819bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (UNLIKELY(class_offsets_offset > Size()) || 4829bdf108885a27ba05fae8501725649574d7c491bVladimir Marko UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) { 4839bdf108885a27ba05fae8501725649574d7c491bVladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated " 4849bdf108885a27ba05fae8501725649574d7c491bVladimir Marko "class offsets, offset %u of %zu, class defs %u", 4859bdf108885a27ba05fae8501725649574d7c491bVladimir Marko GetLocation().c_str(), 4869bdf108885a27ba05fae8501725649574d7c491bVladimir Marko i, 4879bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file_location.c_str(), 4889bdf108885a27ba05fae8501725649574d7c491bVladimir Marko class_offsets_offset, 4899bdf108885a27ba05fae8501725649574d7c491bVladimir Marko Size(), 4909bdf108885a27ba05fae8501725649574d7c491bVladimir Marko header->class_defs_size_); 4919bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 4929bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 4939bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) { 4949bdf108885a27ba05fae8501725649574d7c491bVladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned " 4959bdf108885a27ba05fae8501725649574d7c491bVladimir Marko "class offsets, offset %u", 4969bdf108885a27ba05fae8501725649574d7c491bVladimir Marko GetLocation().c_str(), 4979bdf108885a27ba05fae8501725649574d7c491bVladimir Marko i, 4989bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file_location.c_str(), 4999bdf108885a27ba05fae8501725649574d7c491bVladimir Marko class_offsets_offset); 5009bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 5019bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 5029bdf108885a27ba05fae8501725649574d7c491bVladimir Marko const uint32_t* class_offsets_pointer = 5039bdf108885a27ba05fae8501725649574d7c491bVladimir Marko reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset); 5049bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 5059bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t lookup_table_offset; 5069bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) { 5079bdf108885a27ba05fae8501725649574d7c491bVladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated " 5089bdf108885a27ba05fae8501725649574d7c491bVladimir Marko "after lookup table offset", 5099bdf108885a27ba05fae8501725649574d7c491bVladimir Marko GetLocation().c_str(), 5109bdf108885a27ba05fae8501725649574d7c491bVladimir Marko i, 511d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko dex_file_location.c_str()); 512d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko return false; 513d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko } 514d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko const uint8_t* lookup_table_data = lookup_table_offset != 0u 515d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko ? Begin() + lookup_table_offset 516d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko : nullptr; 5179bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (lookup_table_offset != 0u && 5189bdf108885a27ba05fae8501725649574d7c491bVladimir Marko (UNLIKELY(lookup_table_offset > Size()) || 5199bdf108885a27ba05fae8501725649574d7c491bVladimir Marko UNLIKELY(Size() - lookup_table_offset < 5209bdf108885a27ba05fae8501725649574d7c491bVladimir Marko TypeLookupTable::RawDataLength(header->class_defs_size_)))) { 52106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated " 5229bdf108885a27ba05fae8501725649574d7c491bVladimir Marko "type lookup table, offset %u of %zu, class defs %u", 52306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 52406d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko i, 5259bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file_location.c_str(), 5269bdf108885a27ba05fae8501725649574d7c491bVladimir Marko lookup_table_offset, 5279bdf108885a27ba05fae8501725649574d7c491bVladimir Marko Size(), 5289bdf108885a27ba05fae8501725649574d7c491bVladimir Marko header->class_defs_size_); 529fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom return false; 530fb331d7ca004f39608fcfdae49d38df90c702ea9Brian Carlstrom } 531e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 53206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko uint8_t* current_dex_cache_arrays = nullptr; 53309d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko if (dex_cache_arrays != nullptr) { 534c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson // All DexCache types except for CallSite have their instance counts in the 535c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson // DexFile header. For CallSites, we need to read the info from the MapList. 536c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson const DexFile::MapItem* call_sites_item = nullptr; 537c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson if (!FindDexFileMapItem(DexBegin(), 538c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson DexEnd(), 539c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson DexFile::MapItemType::kDexTypeCallSiteIdItem, 540c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson &call_sites_item)) { 541c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson *error_msg = StringPrintf("In oat file '%s' could not read data from truncated DexFile map", 542c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson GetLocation().c_str()); 543c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson return false; 544c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson } 545c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson size_t num_call_sites = call_sites_item == nullptr ? 0 : call_sites_item->size_; 546c069a30d42aefd902c20e8bc09dfad1683f07dedOrion Hodson DexCacheArraysLayout layout(pointer_size, *header, num_call_sites); 54709d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko if (layout.Size() != 0u) { 548aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko if (static_cast<size_t>(dex_cache_arrays_end - dex_cache_arrays) < layout.Size()) { 54906d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with " 55006d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko "truncated dex cache arrays, %zu < %zu.", 55106d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko GetLocation().c_str(), 55206d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko i, 55306d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko dex_file_location.c_str(), 554aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko static_cast<size_t>(dex_cache_arrays_end - dex_cache_arrays), 55506d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko layout.Size()); 55609d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko return false; 55709d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko } 55809d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko current_dex_cache_arrays = dex_cache_arrays; 55909d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko dex_cache_arrays += layout.Size(); 56009d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko } 56109d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko } 56209d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko 563aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str()); 564aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko 565aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko // Create the OatDexFile and add it to the owning container. 566539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko OatDexFile* oat_dex_file = new OatDexFile(this, 567539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko dex_file_location, 568aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko canonical_location, 569539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko dex_file_checksum, 570539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko dex_file_pointer, 571d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko lookup_table_data, 5729bdf108885a27ba05fae8501725649574d7c491bVladimir Marko class_offsets_pointer, 57309d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko current_dex_cache_arrays); 574aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko oat_dex_files_storage_.push_back(oat_dex_file); 575aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko 576aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko // Add the location and canonical location (if different) to the oat_dex_files_ table. 5773f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko StringPiece key(oat_dex_file->GetDexFileLocation()); 578539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko oat_dex_files_.Put(key, oat_dex_file); 579aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko if (canonical_location != dex_file_location) { 580aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko StringPiece canonical_key(oat_dex_file->GetCanonicalDexFileLocation()); 581aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko oat_dex_files_.Put(canonical_key, oat_dex_file); 582aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko } 583e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 58409d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko 585aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko if (dex_cache_arrays != dex_cache_arrays_end) { 58609d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko // We expect the bss section to be either empty (dex_cache_arrays and bss_end_ 587aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko // both null) or contain just the dex cache arrays and optionally some GC roots. 58806d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko *error_msg = StringPrintf("In oat file '%s' found unexpected bss size bigger by %zu bytes.", 58909d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko GetLocation().c_str(), 59009d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko static_cast<size_t>(bss_end_ - dex_cache_arrays)); 59109d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko return false; 59209d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko } 593f1b3030832bb33efb9161d851b2915d7d94bedf7Brian Carlstrom return true; 594e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 595e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 596049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe//////////////////////// 597049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// OatFile via dlopen // 598049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe//////////////////////// 599049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 600049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampeclass DlOpenOatFile FINAL : public OatFileBase { 601049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe public: 602049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe DlOpenOatFile(const std::string& filename, bool executable) 603049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe : OatFileBase(filename, executable), 604049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe dlopen_handle_(nullptr), 605a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler shared_objects_before_(0) { 606049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 607049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 608049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe ~DlOpenOatFile() { 609049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (dlopen_handle_ != nullptr) { 610a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler if (!kIsTargetBuild) { 611a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_); 612a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler host_dlopen_handles_.erase(dlopen_handle_); 613c7d3f4b8c294f36209ea2c129f9714a36ae1ec6bMathieu Chartier dlclose(dlopen_handle_); 614c7d3f4b8c294f36209ea2c129f9714a36ae1ec6bMathieu Chartier } else { 615c7d3f4b8c294f36209ea2c129f9714a36ae1ec6bMathieu Chartier dlclose(dlopen_handle_); 616a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler } 617049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 618049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 619049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 620049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe protected: 621049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name, 622049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) const OVERRIDE { 623049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const uint8_t* ptr = 624049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe reinterpret_cast<const uint8_t*>(dlsym(dlopen_handle_, symbol_name.c_str())); 625049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (ptr == nullptr) { 626049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = dlerror(); 627049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 628049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return ptr; 629049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 630049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 6314075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe void PreLoad() OVERRIDE; 6324075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe 633049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool Load(const std::string& elf_filename, 634049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, 635049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool writable, 636049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool executable, 6370b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool low_4gb, 638049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) OVERRIDE; 639049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 640049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions. 641049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe void PreSetup(const std::string& elf_filename) OVERRIDE; 642049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 643049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe private: 644049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool Dlopen(const std::string& elf_filename, 645049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, 646049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg); 647049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 648a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler // On the host, if the same library is loaded again with dlopen the same 649a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler // file handle is returned. This differs from the behavior of dlopen on the 650a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler // target, where dlopen reloads the library at a different address every 651a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler // time you load it. The runtime relies on the target behavior to ensure 652a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler // each instance of the loaded library has a unique dex cache. To avoid 653a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler // problems, we fall back to our own linker in the case when the same 654a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler // library is opened multiple times on host. dlopen_handles_ is used to 655a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler // detect that case. 656a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler // Guarded by host_dlopen_handles_lock_; 657a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler static std::unordered_set<void*> host_dlopen_handles_; 658a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler 659049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // dlopen handle during runtime. 660049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe void* dlopen_handle_; // TODO: Unique_ptr with custom deleter. 661049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 662049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // Dummy memory map objects corresponding to the regions mapped by dlopen. 663049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::vector<std::unique_ptr<MemMap>> dlopen_mmaps_; 664049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 6654075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe // The number of shared objects the linker told us about before loading. Used to 6664075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe // (optimistically) optimize the PreSetup stage (see comment there). 6674075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe size_t shared_objects_before_; 6684075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe 669049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile); 670049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}; 671049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 672a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhlerstd::unordered_set<void*> DlOpenOatFile::host_dlopen_handles_; 673a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler 6744075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampevoid DlOpenOatFile::PreLoad() { 6754075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe#ifdef __APPLE__ 67639004a6fa5566007354379dfc4ae59823146e23eAndreas Gampe UNUSED(shared_objects_before_); 6774075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe LOG(FATAL) << "Should not reach here."; 6784075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe UNREACHABLE(); 6794075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe#else 6804075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe // Count the entries in dl_iterate_phdr we get at this point in time. 6814075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe struct dl_iterate_context { 6824075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe static int callback(struct dl_phdr_info *info ATTRIBUTE_UNUSED, 6834075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe size_t size ATTRIBUTE_UNUSED, 6844075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe void *data) { 6854075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe reinterpret_cast<dl_iterate_context*>(data)->count++; 6864075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe return 0; // Continue iteration. 6874075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe } 6884075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe size_t count = 0; 6894075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe } context; 6904075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe 6914075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe dl_iterate_phdr(dl_iterate_context::callback, &context); 6924075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe shared_objects_before_ = context.count; 6934075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe#endif 6944075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe} 6954075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe 696049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool DlOpenOatFile::Load(const std::string& elf_filename, 697049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, 698049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool writable, 699049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool executable, 7000b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool low_4gb, 701049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) { 702049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // Use dlopen only when flagged to do so, and when it's OK to load things executable. 703049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // TODO: Also try when not executable? The issue here could be re-mapping as writable (as 704049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // !executable is a sign that we may want to patch), which may not be allowed for 705049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // various reasons. 706049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (!kUseDlopen) { 707049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = "DlOpen is disabled."; 708049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return false; 709049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 7100b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier if (low_4gb) { 7110b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier *error_msg = "DlOpen does not support low 4gb loading."; 7120b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier return false; 7130b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier } 714049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (writable) { 715049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = "DlOpen does not support writable loading."; 716049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return false; 717049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 718049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (!executable) { 719049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = "DlOpen does not support non-executable loading."; 720049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return false; 721049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 722049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 723049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // dlopen always returns the same library if it is already opened on the host. For this reason 724049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // we only use dlopen if we are the target or we do not already have the dex file opened. Having 725049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // the same library loaded multiple times at different addresses is required for class unloading 726049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // and for having dex caches arrays in the .bss section. 727049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (!kIsTargetBuild) { 728049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (!kUseDlopenOnHost) { 729049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = "DlOpen disabled for host."; 730049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return false; 731049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 732049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 733049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 734049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool success = Dlopen(elf_filename, oat_file_begin, error_msg); 735049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe DCHECK(dlopen_handle_ != nullptr || !success); 736049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 737049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return success; 738049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 739049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 740049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool DlOpenOatFile::Dlopen(const std::string& elf_filename, 741049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, 742049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) { 743049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe#ifdef __APPLE__ 744049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // The dl_iterate_phdr syscall is missing. There is similar API on OSX, 745049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // but let's fallback to the custom loading code for the time being. 746049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe UNUSED(elf_filename, oat_file_begin); 747049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = "Dlopen unsupported on Mac."; 748049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return false; 749049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe#else 750049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe { 751049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe UniqueCPtr<char> absolute_path(realpath(elf_filename.c_str(), nullptr)); 752049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (absolute_path == nullptr) { 753049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str()); 754049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return false; 755049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 756bb661c0f0cb72d4bbfc2e251f6ded6949a713292Bilyan Borisov#ifdef ART_TARGET_ANDROID 7573a2e78ebade9f7e0444be6f6817cbf116b34e7b1Anton Kirilov android_dlextinfo extinfo = {}; 758049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe extinfo.flags = ANDROID_DLEXT_FORCE_LOAD | // Force-load, don't reuse handle 759049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // (open oat files multiple 760049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // times). 761049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe ANDROID_DLEXT_FORCE_FIXED_VADDR; // Take a non-zero vaddr as absolute 762049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // (non-pic boot image). 763226b91e2ab5e33969cbbae5ba8f2f611e522fe31Andreas Gampe if (oat_file_begin != nullptr) { // 764226b91e2ab5e33969cbbae5ba8f2f611e522fe31Andreas Gampe extinfo.flags |= ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS; // Use the requested addr if 765226b91e2ab5e33969cbbae5ba8f2f611e522fe31Andreas Gampe extinfo.reserved_addr = oat_file_begin; // vaddr = 0. 766226b91e2ab5e33969cbbae5ba8f2f611e522fe31Andreas Gampe } // (pic boot image). 767049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo); 768049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe#else 769049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe UNUSED(oat_file_begin); 7701af0c4ff8b79ad44a4e12d7271a66d4e775ba224Julien Duraj static_assert(!kIsTargetBuild || kIsTargetLinux, "host_dlopen_handles_ will leak handles"); 771c7d3f4b8c294f36209ea2c129f9714a36ae1ec6bMathieu Chartier MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_); 772a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW); 773a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler if (dlopen_handle_ != nullptr) { 774a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler if (!host_dlopen_handles_.insert(dlopen_handle_).second) { 775a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler dlclose(dlopen_handle_); 776a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler dlopen_handle_ = nullptr; 777a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler *error_msg = StringPrintf("host dlopen re-opened '%s'", elf_filename.c_str()); 778a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler return false; 779a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler } 780a206c745dbb64b14f05c87891d425475c2f6d63aRichard Uhler } 781bb661c0f0cb72d4bbfc2e251f6ded6949a713292Bilyan Borisov#endif // ART_TARGET_ANDROID 782049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 783049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (dlopen_handle_ == nullptr) { 784049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror()); 785049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return false; 786049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 787049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return true; 788049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe#endif 789049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 790049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 791049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampevoid DlOpenOatFile::PreSetup(const std::string& elf_filename) { 79274f07b5264811263497c39853549ccb321f0973cAndreas Gampe#ifdef __APPLE__ 79374f07b5264811263497c39853549ccb321f0973cAndreas Gampe UNUSED(elf_filename); 79474f07b5264811263497c39853549ccb321f0973cAndreas Gampe LOG(FATAL) << "Should not reach here."; 79574f07b5264811263497c39853549ccb321f0973cAndreas Gampe UNREACHABLE(); 79674f07b5264811263497c39853549ccb321f0973cAndreas Gampe#else 797049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe struct dl_iterate_context { 798049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe static int callback(struct dl_phdr_info *info, size_t /* size */, void *data) { 799049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe auto* context = reinterpret_cast<dl_iterate_context*>(data); 8004075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe context->shared_objects_seen++; 8014075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe if (context->shared_objects_seen < context->shared_objects_before) { 8024075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe // We haven't been called yet for anything we haven't seen before. Just continue. 8034075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe // Note: this is aggressively optimistic. If another thread was unloading a library, 8044075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe // we may miss out here. However, this does not happen often in practice. 8054075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe return 0; 8064075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe } 8074075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe 808049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // See whether this callback corresponds to the file which we have just loaded. 809049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool contains_begin = false; 810049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe for (int i = 0; i < info->dlpi_phnum; i++) { 811049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (info->dlpi_phdr[i].p_type == PT_LOAD) { 812049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr + 813049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe info->dlpi_phdr[i].p_vaddr); 814049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe size_t memsz = info->dlpi_phdr[i].p_memsz; 815049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) { 816049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe contains_begin = true; 817049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe break; 818049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 819049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 820049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 821049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // Add dummy mmaps for this file. 822049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (contains_begin) { 823049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe for (int i = 0; i < info->dlpi_phnum; i++) { 824049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (info->dlpi_phdr[i].p_type == PT_LOAD) { 825049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr + 826049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe info->dlpi_phdr[i].p_vaddr); 827049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe size_t memsz = info->dlpi_phdr[i].p_memsz; 828049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe MemMap* mmap = MemMap::MapDummy(info->dlpi_name, vaddr, memsz); 829049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe context->dlopen_mmaps_->push_back(std::unique_ptr<MemMap>(mmap)); 830049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 831049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 832049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return 1; // Stop iteration and return 1 from dl_iterate_phdr. 833049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 834049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished. 835049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 836049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const uint8_t* const begin_; 837049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::vector<std::unique_ptr<MemMap>>* const dlopen_mmaps_; 8384075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe const size_t shared_objects_before; 8394075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe size_t shared_objects_seen; 8404075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe }; 8414075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe dl_iterate_context context = { Begin(), &dlopen_mmaps_, shared_objects_before_, 0}; 842049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 843049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) { 8444075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0 8454075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe // before giving up. This should be unusual. 8464075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before=" 8474075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe << shared_objects_before_; 8484075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe dl_iterate_context context0 = { Begin(), &dlopen_mmaps_, 0, 0}; 8494075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe if (dl_iterate_phdr(dl_iterate_context::callback, &context0) == 0) { 8504075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe // OK, give up and print an error. 8514075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); 8524075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps."; 8534075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe } 854049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 85574f07b5264811263497c39853549ccb321f0973cAndreas Gampe#endif 856049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 857049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 858049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe//////////////////////////////////////////////// 859049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// OatFile via our own ElfFile implementation // 860049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe//////////////////////////////////////////////// 861049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 862049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampeclass ElfOatFile FINAL : public OatFileBase { 863049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe public: 864049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {} 865049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 866049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe static ElfOatFile* OpenElfFile(File* file, 867049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const std::string& location, 868049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* requested_base, 869049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, // Override base if not null 870049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool writable, 871049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool executable, 8720b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool low_4gb, 873049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const char* abs_dex_location, 874049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg); 875049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 876049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool InitializeFromElfFile(ElfFile* elf_file, 877c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil VdexFile* vdex_file, 878049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const char* abs_dex_location, 879049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg); 880049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 881049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe protected: 882049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name, 883049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) const OVERRIDE { 884049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const uint8_t* ptr = elf_file_->FindDynamicSymbolAddress(symbol_name); 885049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (ptr == nullptr) { 886049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = "(Internal implementation could not find symbol)"; 887049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 888049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return ptr; 889049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 890049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 8914075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe void PreLoad() OVERRIDE { 8924075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe } 8934075f830c58e38f1ac88a6b3c663fafefdb4b414Andreas Gampe 894049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool Load(const std::string& elf_filename, 895049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, // Override where the file is loaded to if not null 896049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool writable, 897049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool executable, 8980b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool low_4gb, 899049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) OVERRIDE; 900049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 901049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) OVERRIDE { 902049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 903049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 904049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe private: 905049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool ElfFileOpen(File* file, 906049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, // Override where the file is loaded to if not null 907049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool writable, 908049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool executable, 9090b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool low_4gb, 910049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg); 911049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 912049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe private: 913049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // Backing memory map for oat file during cross compilation. 914049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::unique_ptr<ElfFile> elf_file_; 915049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 916049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe DISALLOW_COPY_AND_ASSIGN(ElfOatFile); 917049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe}; 918049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 919049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas GampeElfOatFile* ElfOatFile::OpenElfFile(File* file, 920049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const std::string& location, 921049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* requested_base, 922049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, // Override base if not null 923049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool writable, 924049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool executable, 9250b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool low_4gb, 926049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const char* abs_dex_location, 927049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) { 92832ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace("Open elf file " + location); 929049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, executable)); 9300b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool success = oat_file->ElfFileOpen(file, 9310b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier oat_file_begin, 9320b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier writable, 9330b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier low_4gb, 9340b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier executable, 9350b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier error_msg); 936049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (!success) { 937049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe CHECK(!error_msg->empty()); 938049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return nullptr; 939049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 940049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 941049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // Complete the setup. 942049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (!oat_file->ComputeFields(requested_base, file->GetPath(), error_msg)) { 943049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return nullptr; 944049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 945049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 946049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (!oat_file->Setup(abs_dex_location, error_msg)) { 947049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return nullptr; 948049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 949049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 950049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return oat_file.release(); 951049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 952049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 953049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool ElfOatFile::InitializeFromElfFile(ElfFile* elf_file, 954c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil VdexFile* vdex_file, 955049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const char* abs_dex_location, 956049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) { 95732ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace(__PRETTY_FUNCTION__); 958049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (IsExecutable()) { 959049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = "Cannot initialize from elf file in executable mode."; 960049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return false; 961049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 962049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe elf_file_.reset(elf_file); 963c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil SetVdex(vdex_file); 964049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint64_t offset, size; 965049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size); 966049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe CHECK(has_section); 967049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe SetBegin(elf_file->Begin() + offset); 968049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe SetEnd(elf_file->Begin() + size + offset); 969049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // Ignore the optional .bss section when opening non-executable. 970049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return Setup(abs_dex_location, error_msg); 971049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 972049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 973049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool ElfOatFile::Load(const std::string& elf_filename, 974049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, // Override where the file is loaded to if not null 975049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool writable, 976049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool executable, 9770b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool low_4gb, 978049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) { 97932ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace(__PRETTY_FUNCTION__); 980049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str())); 981049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (file == nullptr) { 982049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno)); 983049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return false; 984049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 985049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return ElfOatFile::ElfFileOpen(file.get(), 986049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe oat_file_begin, 987049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe writable, 988049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe executable, 9890b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier low_4gb, 990049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe error_msg); 991049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 992049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 993049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampebool ElfOatFile::ElfFileOpen(File* file, 994049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, 995049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool writable, 996049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool executable, 9970b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool low_4gb, 998049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) { 99932ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace(__PRETTY_FUNCTION__); 1000049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // TODO: rename requested_base to oat_data_begin 1001049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe elf_file_.reset(ElfFile::Open(file, 1002049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe writable, 1003049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe /*program_header_only*/true, 10040b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier low_4gb, 1005049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe error_msg, 1006049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe oat_file_begin)); 1007049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (elf_file_ == nullptr) { 1008049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe DCHECK(!error_msg->empty()); 1009049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return false; 1010049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 1011f5b0f2cef8554efaa90adc6a1ae04c2b533970edBrian Carlstrom bool loaded = elf_file_->Load(file, executable, low_4gb, error_msg); 1012049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe DCHECK(loaded || !error_msg->empty()); 1013049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return loaded; 1014049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 1015049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 1016049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe////////////////////////// 1017049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe// General OatFile code // 1018049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe////////////////////////// 1019049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 1020049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampestd::string OatFile::ResolveRelativeEncodedDexLocation( 1021049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const char* abs_dex_location, const std::string& rel_dex_location) { 1022049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (abs_dex_location != nullptr && rel_dex_location[0] != '/') { 1023049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // Strip :classes<N>.dex used for secondary multidex files. 1024049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string base = DexFile::GetBaseLocation(rel_dex_location); 1025049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string multidex_suffix = DexFile::GetMultiDexSuffix(rel_dex_location); 1026049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 1027049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // Check if the base is a suffix of the provided abs_dex_location. 1028049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string target_suffix = "/" + base; 1029049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string abs_location(abs_dex_location); 1030049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (abs_location.size() > target_suffix.size()) { 1031049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe size_t pos = abs_location.size() - target_suffix.size(); 1032049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (abs_location.compare(pos, std::string::npos, target_suffix) == 0) { 1033049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return abs_location + multidex_suffix; 1034049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 1035049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 1036049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 1037049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return rel_dex_location; 1038049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 1039049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 1040049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampestatic void CheckLocation(const std::string& location) { 1041049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe CHECK(!location.empty()); 1042049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 1043049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 1044049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas GampeOatFile* OatFile::OpenWithElfFile(ElfFile* elf_file, 1045c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil VdexFile* vdex_file, 1046049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const std::string& location, 1047049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const char* abs_dex_location, 1048049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) { 1049049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, false /* executable */)); 1050c93b3be140f6a57a572f2a4cdaf46aba87235a02David Brazdil return oat_file->InitializeFromElfFile(elf_file, vdex_file, abs_dex_location, error_msg) 1051049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe ? oat_file.release() 1052049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe : nullptr; 1053049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 1054049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 10557b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David BrazdilOatFile* OatFile::Open(const std::string& oat_filename, 10567b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil const std::string& oat_location, 1057049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* requested_base, 1058049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe uint8_t* oat_file_begin, 1059049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bool executable, 10600b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier bool low_4gb, 1061049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const char* abs_dex_location, 1062049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) { 10637b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil ScopedTrace trace("Open oat file " + oat_location); 10647b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil CHECK(!oat_filename.empty()) << oat_location; 10657b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil CheckLocation(oat_location); 106654315c7e452742c6c57649e61c6370c8c2083d96Andreas Gampe 1067cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle std::string vdex_filename = GetVdexFilename(oat_filename); 10687b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil 10697b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil // Check that the files even exist, fast-fail. 10707b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil if (kIsVdexEnabled && !OS::FileExists(vdex_filename.c_str())) { 10717b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil *error_msg = StringPrintf("File %s does not exist.", vdex_filename.c_str()); 10727b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil return nullptr; 10737b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil } else if (!OS::FileExists(oat_filename.c_str())) { 10747b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil *error_msg = StringPrintf("File %s does not exist.", oat_filename.c_str()); 107554315c7e452742c6c57649e61c6370c8c2083d96Andreas Gampe return nullptr; 107654315c7e452742c6c57649e61c6370c8c2083d96Andreas Gampe } 1077049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 1078049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is 1079049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // disabled. 10807b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(vdex_filename, 10817b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil oat_filename, 10827b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil oat_location, 1083049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe requested_base, 1084049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe oat_file_begin, 10857b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil false /* writable */, 1086049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe executable, 10870b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier low_4gb, 1088049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe abs_dex_location, 1089049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe error_msg); 1090049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (with_dlopen != nullptr) { 1091049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return with_dlopen; 1092049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 1093049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe if (kPrintDlOpenErrorMessage) { 10947b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil LOG(ERROR) << "Failed to dlopen: " << oat_filename << " with error " << *error_msg; 1095049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe } 1096049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons: 1097049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // 1098049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // On target, dlopen may fail when compiling due to selinux restrictions on installd. 1099049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // 1100049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // We use our own ELF loader for Quick to deal with legacy apps that 1101049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // open a generated dex file by name, remove the file, then open 1102049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // another generated dex file with the same name. http://b/10614658 1103049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // 1104049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile. 1105049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // 1106049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // 1107049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually 1108049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN. 11097b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(vdex_filename, 11107b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil oat_filename, 11117b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil oat_location, 1112049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe requested_base, 1113049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe oat_file_begin, 11147b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil false /* writable */, 1115049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe executable, 11160b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier low_4gb, 1117049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe abs_dex_location, 1118049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe error_msg); 1119049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return with_internal; 1120049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 1121049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 1122049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas GampeOatFile* OatFile::OpenWritable(File* file, 1123049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const std::string& location, 1124049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const char* abs_dex_location, 1125049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) { 1126049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe CheckLocation(location); 1127049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return ElfOatFile::OpenElfFile(file, 1128049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe location, 1129049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe nullptr, 1130049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe nullptr, 1131049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe true, 1132049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe false, 11330b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier /*low_4gb*/false, 1134049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe abs_dex_location, 1135049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe error_msg); 1136049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 1137049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 1138049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas GampeOatFile* OatFile::OpenReadable(File* file, 1139049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const std::string& location, 1140049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe const char* abs_dex_location, 1141049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe std::string* error_msg) { 1142049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe CheckLocation(location); 1143049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe return ElfOatFile::OpenElfFile(file, 1144049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe location, 1145049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe nullptr, 1146049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe nullptr, 1147049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe false, 1148049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe false, 11490b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier /*low_4gb*/false, 1150049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe abs_dex_location, 1151049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe error_msg); 1152049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 1153049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 1154049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas GampeOatFile::OatFile(const std::string& location, bool is_executable) 1155049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe : location_(location), 11567b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil vdex_(nullptr), 1157049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe begin_(nullptr), 1158049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe end_(nullptr), 1159049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bss_begin_(nullptr), 1160049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe bss_end_(nullptr), 1161aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko bss_roots_(nullptr), 1162049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe is_executable_(is_executable), 1163049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) { 1164049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe CHECK(!location_.empty()); 1165049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 1166049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 1167049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas GampeOatFile::~OatFile() { 1168049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe STLDeleteElements(&oat_dex_files_storage_); 1169049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe} 1170049cff0ed5e28aa17a17e456efe3121b6d58910fAndreas Gampe 1171e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromconst OatHeader& OatFile::GetOatHeader() const { 117230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers return *reinterpret_cast<const OatHeader*>(Begin()); 1173e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1174e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 117513735955f39b3b304c37d2b2840663c131262c18Ian Rogersconst uint8_t* OatFile::Begin() const { 1176fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe CHECK(begin_ != nullptr); 1177700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom return begin_; 1178e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1179e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 118013735955f39b3b304c37d2b2840663c131262c18Ian Rogersconst uint8_t* OatFile::End() const { 1181fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe CHECK(end_ != nullptr); 1182700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom return end_; 1183e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1184e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 11855c42c29b89286e5efa4a4613132b09051ce5945bVladimir Markoconst uint8_t* OatFile::BssBegin() const { 11865c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko return bss_begin_; 11875c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko} 11885c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 11895c42c29b89286e5efa4a4613132b09051ce5945bVladimir Markoconst uint8_t* OatFile::BssEnd() const { 11905c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko return bss_end_; 11915c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko} 11925c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 11937b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdilconst uint8_t* OatFile::DexBegin() const { 11947b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil return kIsVdexEnabled ? vdex_->Begin() : Begin(); 11957b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil} 11967b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil 11977b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdilconst uint8_t* OatFile::DexEnd() const { 11987b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil return kIsVdexEnabled ? vdex_->End() : End(); 11997b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil} 12007b49e6cade09bc65b3b5f22d45fc9d0a7184e4f2David Brazdil 1201aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir MarkoArrayRef<GcRoot<mirror::Object>> OatFile::GetBssGcRoots() const { 1202aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko if (bss_roots_ != nullptr) { 1203aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko auto* roots = reinterpret_cast<GcRoot<mirror::Object>*>(bss_roots_); 1204aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko auto* roots_end = reinterpret_cast<GcRoot<mirror::Object>*>(bss_end_); 1205aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko return ArrayRef<GcRoot<mirror::Object>>(roots, roots_end - roots); 1206aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko } else { 1207aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko return ArrayRef<GcRoot<mirror::Object>>(); 1208aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko } 1209aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko} 1210aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko 12118d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogersconst OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location, 12128d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers const uint32_t* dex_location_checksum, 12139a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler std::string* error_msg) const { 12143f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // NOTE: We assume here that the canonical location for a given dex_location never 12153f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // changes. If it does (i.e. some symlink used by the filename changes) we may return 12163f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // an incorrect OatDexFile. As long as we have a checksum to check, we shall return 12173f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // an identical file or fail; otherwise we may see some unpredictable failures. 12183f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko 12193f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // TODO: Additional analysis of usage patterns to see if this can be simplified 12203f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // without any performance loss, for example by not doing the first lock-free lookup. 12213f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko 12223f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko const OatFile::OatDexFile* oat_dex_file = nullptr; 12233f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko StringPiece key(dex_location); 12243f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations 12253f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // directly mentioned in the oat file and doesn't require locking. 12263f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko auto primary_it = oat_dex_files_.find(key); 12273f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko if (primary_it != oat_dex_files_.end()) { 12283f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko oat_dex_file = primary_it->second; 12293f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko DCHECK(oat_dex_file != nullptr); 12303f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko } else { 12313f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // This dex_location is not one of the dex locations directly mentioned in the 12323f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // oat file. The correct lookup is via the canonical location but first see in 12333f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // the secondary_oat_dex_files_ whether we've looked up this location before. 12343f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko MutexLock mu(Thread::Current(), secondary_lookup_lock_); 12353f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko auto secondary_lb = secondary_oat_dex_files_.lower_bound(key); 12363f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) { 12372cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier oat_dex_file = secondary_lb->second; // May be null. 12383f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko } else { 12393f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // We haven't seen this dex_location before, we must check the canonical location. 12403f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location); 1241aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko if (dex_canonical_location != dex_location) { 1242aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko StringPiece canonical_key(dex_canonical_location); 1243aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko auto canonical_it = oat_dex_files_.find(canonical_key); 1244aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko if (canonical_it != oat_dex_files_.end()) { 1245aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko oat_dex_file = canonical_it->second; 12462cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier } // else keep null. 12472cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier } // else keep null. 12483f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko 12493f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // Copy the key to the string_cache_ and store the result in secondary map. 12503f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko string_cache_.emplace_back(key.data(), key.length()); 12513f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko StringPiece key_copy(string_cache_.back()); 12523f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file); 1253756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom } 1254756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom } 1255756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom 12569a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler if (oat_dex_file == nullptr) { 12579a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler if (error_msg != nullptr) { 12589a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location); 12599a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler *error_msg = "Failed to find OatDexFile for DexFile " + std::string(dex_location) 12609a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation(); 12617fe2c691866ad643b9e21dd2c9d36fa79ec454c3Ian Rogers } 12629a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler return nullptr; 1263aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 12644e1d579d6401fef2dd57b16f8d406e33221a69d9Calin Juravle 12659a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler if (dex_location_checksum != nullptr && 12669a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler oat_dex_file->GetDexFileLocationChecksum() != *dex_location_checksum) { 12679a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler if (error_msg != nullptr) { 12689a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location); 12699a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler std::string checksum = StringPrintf("0x%08x", oat_dex_file->GetDexFileLocationChecksum()); 12709a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler std::string required_checksum = StringPrintf("0x%08x", *dex_location_checksum); 12719a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler *error_msg = "OatDexFile for DexFile " + std::string(dex_location) 12729a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation() 12739a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler + " has checksum " + checksum + " but " + required_checksum + " was required"; 12749a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler } 12759a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler return nullptr; 12769a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler } 12779a37efc6e1a8dd9fe6978f209fb493510267c528Richard Uhler return oat_dex_file; 1278aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom} 1279aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 1280e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::OatDexFile::OatDexFile(const OatFile* oat_file, 1281aa6a588eb83288481389aa08b03105346a87e706Elliott Hughes const std::string& dex_file_location, 1282aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko const std::string& canonical_dex_file_location, 12835b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom uint32_t dex_file_location_checksum, 128413735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* dex_file_pointer, 1285d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko const uint8_t* lookup_table_data, 128609d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko const uint32_t* oat_class_offsets_pointer, 128706d7aaa75f3d6d21fe904d54208b28e486673d97Vladimir Marko uint8_t* dex_cache_arrays) 1288e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom : oat_file_(oat_file), 1289e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_location_(dex_file_location), 1290aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko canonical_dex_file_location_(canonical_dex_file_location), 12915b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom dex_file_location_checksum_(dex_file_location_checksum), 129289521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom dex_file_pointer_(dex_file_pointer), 1293d9786b0e5be23ea0258405165098b4216579209cArtem Udovichenko lookup_table_data_(lookup_table_data), 129409d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko oat_class_offsets_pointer_(oat_class_offsets_pointer), 12959aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr dex_cache_arrays_(dex_cache_arrays) { 12969aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr // Initialize TypeLookupTable. 12979aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr if (lookup_table_data_ != nullptr) { 12989aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr // Peek the number of classes from the DexFile. 12999aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_); 13009aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr const uint32_t num_class_defs = dex_header->class_defs_size_; 13019aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) > GetOatFile()->End()) { 13029aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr LOG(WARNING) << "found truncated lookup table in " << dex_file_location_; 13039aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr } else { 13041b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier lookup_table_ = TypeLookupTable::Open(dex_file_pointer_, lookup_table_data_, num_class_defs); 13059aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr } 13069aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr } 13079aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr} 1308e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 13091b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu ChartierOatFile::OatDexFile::OatDexFile(std::unique_ptr<TypeLookupTable>&& lookup_table) 13101b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier : lookup_table_(std::move(lookup_table)) {} 13111b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier 1312e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatFile::OatDexFile::~OatDexFile() {} 1313e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 131405f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogerssize_t OatFile::OatDexFile::FileSize() const { 131505f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_; 131605f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers} 131705f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers 1318b1d8c314b55bb2df2b2bb72a3daaf5db65b7ebc7Igor Murashkinstd::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const { 131932ce2adefb8a3d0eda59a29f5e87c1eb43eef796Mathieu Chartier ScopedTrace trace(__PRETTY_FUNCTION__); 132037d6a3bbf5826abb73f872ed0bc4c6ae9553e274Aart Bik static constexpr bool kVerify = false; 132137d6a3bbf5826abb73f872ed0bc4c6ae9553e274Aart Bik static constexpr bool kVerifyChecksum = false; 13223a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe return DexFile::Open(dex_file_pointer_, 13233a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe FileSize(), 13243a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe dex_file_location_, 13253a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe dex_file_location_checksum_, 13263a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe this, 132737d6a3bbf5826abb73f872ed0bc4c6ae9553e274Aart Bik kVerify, 132837d6a3bbf5826abb73f872ed0bc4c6ae9553e274Aart Bik kVerifyChecksum, 13293a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe error_msg); 133089521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom} 133189521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom 13322cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromuint32_t OatFile::OatDexFile::GetOatClassOffset(uint16_t class_def_index) const { 13332cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom return oat_class_offsets_pointer_[class_def_index]; 13342cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom} 13352cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom 1336d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir MarkoOatFile::OatClass OatFile::OatDexFile::GetOatClass(uint16_t class_def_index) const { 13372cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom uint32_t oat_class_offset = GetOatClassOffset(class_def_index); 13380755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 133913735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* oat_class_pointer = oat_file_->Begin() + oat_class_offset; 13407571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation(); 13410755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 134213735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* status_pointer = oat_class_pointer; 1343ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation(); 1344ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom mirror::Class::Status status = 1345ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom static_cast<mirror::Class::Status>(*reinterpret_cast<const int16_t*>(status_pointer)); 1346ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LT(status, mirror::Class::kStatusMax); 1347ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 134813735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* type_pointer = status_pointer + sizeof(uint16_t); 1349ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation(); 1350ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom OatClassType type = static_cast<OatClassType>(*reinterpret_cast<const uint16_t*>(type_pointer)); 1351ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_LT(type, kOatClassMax); 1352ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 135313735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* after_type_pointer = type_pointer + sizeof(int16_t); 1354cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom CHECK_LE(after_type_pointer, oat_file_->End()) << oat_file_->GetLocation(); 1355cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom 1356ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t bitmap_size = 0; 135713735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* bitmap_pointer = nullptr; 135813735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* methods_pointer = nullptr; 135997b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers if (type != kOatClassNoneCompiled) { 136097b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers if (type == kOatClassSomeCompiled) { 136197b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers bitmap_size = static_cast<uint32_t>(*reinterpret_cast<const uint32_t*>(after_type_pointer)); 136297b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers bitmap_pointer = after_type_pointer + sizeof(bitmap_size); 136397b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers CHECK_LE(bitmap_pointer, oat_file_->End()) << oat_file_->GetLocation(); 136497b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers methods_pointer = bitmap_pointer + bitmap_size; 136597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers } else { 136697b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers methods_pointer = after_type_pointer; 136797b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers } 136897b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation(); 1369ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 13700755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 137107b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler return OatFile::OatClass(oat_file_, 137207b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler status, 137307b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler type, 137407b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler bitmap_size, 137507b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler reinterpret_cast<const uint32_t*>(bitmap_pointer), 137607b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler reinterpret_cast<const OatMethodOffsets*>(methods_pointer)); 1377e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 1378e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 13799aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehrconst DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_file, 13809aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr const char* descriptor, 13819aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr size_t hash) { 13829aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile(); 13839aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash); 13849aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr if (LIKELY((oat_dex_file != nullptr) && (oat_dex_file->GetTypeLookupTable() != nullptr))) { 13859aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable()->Lookup(descriptor, hash); 13869aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr return (class_def_idx != DexFile::kDexNoIndex) ? &dex_file.GetClassDef(class_def_idx) : nullptr; 13879aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr } 13889aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr // Fast path for rare no class defs case. 13899aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr const uint32_t num_class_defs = dex_file.NumClassDefs(); 13909aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr if (num_class_defs == 0) { 13919aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr return nullptr; 13929aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr } 13939aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr const DexFile::TypeId* type_id = dex_file.FindTypeId(descriptor); 13949aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr if (type_id != nullptr) { 1395a5b09a67034e57a6e10231dd4bd92f4cb50b824cAndreas Gampe dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id); 13969aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr return dex_file.FindClassDef(type_idx); 13979aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr } 13989aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr return nullptr; 13999aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr} 14009aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr 14010755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian CarlstromOatFile::OatClass::OatClass(const OatFile* oat_file, 14022dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class::Status status, 1403ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom OatClassType type, 1404ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t bitmap_size, 1405ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom const uint32_t* bitmap_pointer, 14060755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom const OatMethodOffsets* methods_pointer) 1407ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom : oat_file_(oat_file), status_(status), type_(type), 1408d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko bitmap_(bitmap_pointer), methods_pointer_(methods_pointer) { 1409ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom switch (type_) { 1410ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom case kOatClassAllCompiled: { 1411ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(0U, bitmap_size); 1412cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom CHECK(bitmap_pointer == nullptr); 141397b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers CHECK(methods_pointer != nullptr); 1414ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom break; 1415ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1416ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom case kOatClassSomeCompiled: { 1417ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_NE(0U, bitmap_size); 1418cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom CHECK(bitmap_pointer != nullptr); 141997b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers CHECK(methods_pointer != nullptr); 1420ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom break; 1421ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1422ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom case kOatClassNoneCompiled: { 1423ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(0U, bitmap_size); 1424cd937a9dabaabccdeeafcd7fb69b98752e72dca5Brian Carlstrom CHECK(bitmap_pointer == nullptr); 142597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers CHECK(methods_pointer_ == nullptr); 1426ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom break; 1427ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1428ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom case kOatClassMax: { 1429ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom LOG(FATAL) << "Invalid OatClassType " << type_; 1430ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom break; 1431ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1432ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1433ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom} 1434e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 14352cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromuint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const { 14362cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index); 14372cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom if (oat_method_offsets == nullptr) { 14382cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom return 0u; 14392cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom } 14402cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin(); 14412cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom} 14422cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom 14432cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromconst OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const { 1444d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index. 14452cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom if (methods_pointer_ == nullptr) { 1446ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(kOatClassNoneCompiled, type_); 14472cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom return nullptr; 1448ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1449ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_t methods_pointer_index; 14502cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom if (bitmap_ == nullptr) { 1451ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(kOatClassAllCompiled, type_); 1452ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom methods_pointer_index = method_index; 1453ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } else { 1454ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(kOatClassSomeCompiled, type_); 1455d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko if (!BitVector::IsBitSet(bitmap_, method_index)) { 14562cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom return nullptr; 1457ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1458d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index); 1459d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko methods_pointer_index = num_set_bits; 1460ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1461ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index]; 14622cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom return &oat_method_offsets; 14632cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom} 14642cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom 14652cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstromconst OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const { 14662cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index); 14672cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom if (oat_method_offsets == nullptr) { 1468957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier return OatMethod(nullptr, 0); 14692cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom } 14702cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom if (oat_file_->IsExecutable() || 14712cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom Runtime::Current() == nullptr || // This case applies for oatdump. 1472e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier Runtime::Current()->IsAotCompiler()) { 1473957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_); 14749dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light } 1475e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier // We aren't allowed to use the compiled code. We just force it down the interpreted / jit 1476e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier // version. 1477e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return OatMethod(oat_file_->Begin(), 0); 14783320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom} 14793320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 1480e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid OatFile::OatMethod::LinkMethod(ArtMethod* method) const { 1481fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe CHECK(method != nullptr); 1482ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers method->SetEntryPointFromQuickCompiledCode(GetQuickCode()); 1483ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom} 1484ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 14857ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampebool OatFile::IsPic() const { 148646774767fcf7780d1455e755729198648d08742eIgor Murashkin return GetOatHeader().IsPic(); 14877ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe // TODO: Check against oat_patches. b/18144996 14887ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe} 14897ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe 14900de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertzbool OatFile::IsDebuggable() const { 14910de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz return GetOatHeader().IsDebuggable(); 14920de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz} 14930de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz 149429d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas GampeCompilerFilter::Filter OatFile::GetCompilerFilter() const { 149529d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe return GetOatHeader().GetCompilerFilter(); 1496b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle} 1497b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle 14987848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampestatic constexpr char kDexClassPathEncodingSeparator = '*'; 14997848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 150016d4843433e024100b4ecd183f827ad5bd8772a6Jeff Haostd::string OatFile::EncodeDexFileDependencies(const std::vector<const DexFile*>& dex_files, 150116d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao std::string& base_dir) { 15027848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe std::ostringstream out; 15037848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 15047848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe for (const DexFile* dex_file : dex_files) { 150516d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao const std::string& location = dex_file->GetLocation(); 150616d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao // Find paths that were relative and convert them back from absolute. 150716d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao if (!base_dir.empty() && location.substr(0, base_dir.length()) == base_dir) { 150816d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao out << location.substr(base_dir.length() + 1).c_str(); 150916d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao } else { 151016d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao out << dex_file->GetLocation().c_str(); 151116d4843433e024100b4ecd183f827ad5bd8772a6Jeff Hao } 15127848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe out << kDexClassPathEncodingSeparator; 15137848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe out << dex_file->GetLocationChecksum(); 15147848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe out << kDexClassPathEncodingSeparator; 15157848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe } 15167848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 15177848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe return out.str(); 15187848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe} 15197848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 152097d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir MarkoOatFile::OatClass OatFile::FindOatClass(const DexFile& dex_file, 152197d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko uint16_t class_def_idx, 152297d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko bool* found) { 152397d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16); 152497d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile(); 15251b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) { 152697d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko *found = false; 152797d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko return OatFile::OatClass::Invalid(); 152897d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko } 152997d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko *found = true; 153097d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko return oat_dex_file->GetOatClass(class_def_idx); 153197d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko} 153297d7e1cd7f733cb33a0e238bec6d7ed525638cd1Vladimir Marko 15331b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartiervoid OatFile::OatDexFile::AssertAotCompiler() { 15341b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier CHECK(Runtime::Current()->IsAotCompiler()); 15351b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier} 15361b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier 1537e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} // namespace art 1538