blob: d9cfa533caeb54b9ef4da8cddee11fec095c2233 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brian Carlstrome24fa612011-09-29 00:53:55 -070016
17#include "oat_file.h"
18
Brian Carlstrom700c8d32012-11-05 10:42:02 -080019#include <dlfcn.h>
David Srbecky1baabf02015-06-16 17:12:34 +000020#ifndef __APPLE__
21#include <link.h> // for dl_iterate_phdr.
22#endif
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070023#include <unistd.h>
24
25#include <cstdlib>
26#include <cstring>
Richard Uhlere5fed032015-03-18 08:21:11 -070027#include <sstream>
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070028#include <type_traits>
Richard Uhlere5fed032015-03-18 08:21:11 -070029
Andreas Gampefa8429b2015-04-07 18:34:42 -070030// dlopen_ext support from bionic.
Bilyan Borisovbb661c02016-04-04 16:27:32 +010031#ifdef ART_TARGET_ANDROID
Andreas Gampefa8429b2015-04-07 18:34:42 -070032#include "android/dlext.h"
33#endif
34
Andreas Gampe46ee31b2016-12-14 10:11:49 -080035#include "android-base/stringprintf.h"
36
Andreas Gampec6ea7d02017-02-01 16:46:28 -080037#include "art_method.h"
Brian Carlstromba150c32013-08-27 17:31:03 -070038#include "base/bit_vector.h"
Andreas Gampe542451c2016-07-26 09:02:02 -070039#include "base/enums.h"
Elliott Hughes1aa246d2012-12-13 09:29:36 -080040#include "base/stl_util.h"
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -080041#include "base/systrace.h"
Elliott Hughes76160052012-12-12 16:31:20 -080042#include "base/unix_file/fd_file.h"
Andreas Gampea5b09a62016-11-17 15:21:22 -080043#include "dex_file_types.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080044#include "elf_file.h"
Alex Light84d76052014-08-22 17:49:35 -070045#include "elf_utils.h"
Vladimir Markoaad75c62016-10-03 08:46:48 +000046#include "gc_root.h"
David Srbecky1baabf02015-06-16 17:12:34 +000047#include "mem_map.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080048#include "mirror/class.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070049#include "mirror/object-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070050#include "oat.h"
Nicolas Geoffrayc04c8002015-07-14 11:37:54 +010051#include "oat_file-inl.h"
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -070052#include "oat_file_manager.h"
Brian Carlstrome24fa612011-09-29 00:53:55 -070053#include "os.h"
Andreas Gampe22f8e5c2014-07-09 11:38:21 -070054#include "runtime.h"
Vladimir Marko9bdf1082016-01-21 12:15:52 +000055#include "type_lookup_table.h"
David Sehr9aa352e2016-09-15 18:13:52 -070056#include "utf-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080057#include "utils.h"
Vladimir Marko09d09432015-09-08 13:47:48 +010058#include "utils/dex_cache_arrays_layout-inl.h"
Vladimir Marko97d7e1c2016-10-04 14:44:28 +010059#include "vdex_file.h"
Brian Carlstrome24fa612011-09-29 00:53:55 -070060
61namespace art {
62
Andreas Gampe46ee31b2016-12-14 10:11:49 -080063using android::base::StringPrintf;
64
Andreas Gampe049cff02015-12-01 23:27:12 -080065// Whether OatFile::Open will try dlopen. Fallback is our own ELF loader.
David Srbecky1baabf02015-06-16 17:12:34 +000066static constexpr bool kUseDlopen = true;
Andreas Gampefa8429b2015-04-07 18:34:42 -070067
Andreas Gampe049cff02015-12-01 23:27:12 -080068// Whether OatFile::Open will try dlopen on the host. On the host we're not linking against
Andreas Gampefa8429b2015-04-07 18:34:42 -070069// bionic, so cannot take advantage of the support for changed semantics (loading the same soname
70// multiple times). However, if/when we switch the above, we likely want to switch this, too,
71// to get test coverage of the code paths.
David Srbecky1baabf02015-06-16 17:12:34 +000072static constexpr bool kUseDlopenOnHost = true;
Andreas Gampefa8429b2015-04-07 18:34:42 -070073
74// For debugging, Open will print DlOpen error message if set to true.
75static constexpr bool kPrintDlOpenErrorMessage = false;
76
Mathieu Chartierbe8303d2017-08-17 17:39:39 -070077// If true, we advise the kernel about dex file mem map accesses.
Mathieu Chartier150d25d2017-08-28 09:52:55 -070078static constexpr bool kMadviseDexFileAccesses = true;
Mathieu Chartierbe8303d2017-08-17 17:39:39 -070079
Andreas Gampe049cff02015-12-01 23:27:12 -080080// Note for OatFileBase and descendents:
81//
82// These are used in OatFile::Open to try all our loaders.
83//
84// The process is simple:
85//
86// 1) Allocate an instance through the standard constructor (location, executable)
87// 2) Load() to try to open the file.
88// 3) ComputeFields() to populate the OatFile fields like begin_, using FindDynamicSymbolAddress.
89// 4) PreSetup() for any steps that should be done before the final setup.
90// 5) Setup() to complete the procedure.
Richard Uhlere5fed032015-03-18 08:21:11 -070091
Andreas Gampe049cff02015-12-01 23:27:12 -080092class OatFileBase : public OatFile {
93 public:
94 virtual ~OatFileBase() {}
Richard Uhlere5fed032015-03-18 08:21:11 -070095
Andreas Gampe049cff02015-12-01 23:27:12 -080096 template <typename kOatFileBaseSubType>
David Brazdil7b49e6c2016-09-01 11:06:18 +010097 static OatFileBase* OpenOatFile(const std::string& vdex_filename,
98 const std::string& elf_filename,
Alex Light84d76052014-08-22 17:49:35 -070099 const std::string& location,
Andreas Gampe049cff02015-12-01 23:27:12 -0800100 uint8_t* requested_base,
101 uint8_t* oat_file_begin,
102 bool writable,
103 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800104 bool low_4gb,
Richard Uhlere5fed032015-03-18 08:21:11 -0700105 const char* abs_dex_location,
Andreas Gampe049cff02015-12-01 23:27:12 -0800106 std::string* error_msg);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800107
Andreas Gampe049cff02015-12-01 23:27:12 -0800108 protected:
109 OatFileBase(const std::string& filename, bool executable) : OatFile(filename, executable) {}
Andreas Gampefa8429b2015-04-07 18:34:42 -0700110
Andreas Gampe049cff02015-12-01 23:27:12 -0800111 virtual const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
112 std::string* error_msg) const = 0;
113
Andreas Gampe4075f832016-05-18 13:09:54 -0700114 virtual void PreLoad() = 0;
115
David Brazdil7b49e6c2016-09-01 11:06:18 +0100116 bool LoadVdex(const std::string& vdex_filename,
117 bool writable,
118 bool low_4gb,
119 std::string* error_msg);
120
Andreas Gampe049cff02015-12-01 23:27:12 -0800121 virtual bool Load(const std::string& elf_filename,
122 uint8_t* oat_file_begin,
123 bool writable,
124 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800125 bool low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -0800126 std::string* error_msg) = 0;
127
128 bool ComputeFields(uint8_t* requested_base,
129 const std::string& file_path,
130 std::string* error_msg);
131
132 virtual void PreSetup(const std::string& elf_filename) = 0;
133
134 bool Setup(const char* abs_dex_location, std::string* error_msg);
135
136 // Setters exposed for ElfOatFile.
137
138 void SetBegin(const uint8_t* begin) {
139 begin_ = begin;
Andreas Gampefa8429b2015-04-07 18:34:42 -0700140 }
141
Andreas Gampe049cff02015-12-01 23:27:12 -0800142 void SetEnd(const uint8_t* end) {
143 end_ = end;
144 }
145
David Brazdilc93b3be2016-09-12 18:49:58 +0100146 void SetVdex(VdexFile* vdex) {
147 vdex_.reset(vdex);
148 }
149
Andreas Gampe049cff02015-12-01 23:27:12 -0800150 private:
151 DISALLOW_COPY_AND_ASSIGN(OatFileBase);
152};
153
154template <typename kOatFileBaseSubType>
David Brazdil7b49e6c2016-09-01 11:06:18 +0100155OatFileBase* OatFileBase::OpenOatFile(const std::string& vdex_filename,
156 const std::string& elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -0800157 const std::string& location,
158 uint8_t* requested_base,
159 uint8_t* oat_file_begin,
160 bool writable,
161 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800162 bool low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -0800163 const char* abs_dex_location,
164 std::string* error_msg) {
165 std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable));
Andreas Gampe4075f832016-05-18 13:09:54 -0700166
167 ret->PreLoad();
168
David Brazdil7b49e6c2016-09-01 11:06:18 +0100169 if (kIsVdexEnabled && !ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) {
170 return nullptr;
171 }
172
Andreas Gampe049cff02015-12-01 23:27:12 -0800173 if (!ret->Load(elf_filename,
174 oat_file_begin,
175 writable,
176 executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800177 low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -0800178 error_msg)) {
Elliott Hughes956af0f2014-12-11 14:34:28 -0800179 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800180 }
Elliott Hughes956af0f2014-12-11 14:34:28 -0800181
Andreas Gampe049cff02015-12-01 23:27:12 -0800182 if (!ret->ComputeFields(requested_base, elf_filename, error_msg)) {
183 return nullptr;
184 }
Andreas Gampe4075f832016-05-18 13:09:54 -0700185
Andreas Gampe049cff02015-12-01 23:27:12 -0800186 ret->PreSetup(elf_filename);
187
188 if (!ret->Setup(abs_dex_location, error_msg)) {
189 return nullptr;
190 }
191
Dave Allison69dfe512014-07-11 17:11:58 +0000192 return ret.release();
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800193}
194
David Brazdil7b49e6c2016-09-01 11:06:18 +0100195bool OatFileBase::LoadVdex(const std::string& vdex_filename,
196 bool writable,
197 bool low_4gb,
198 std::string* error_msg) {
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100199 vdex_ = VdexFile::Open(vdex_filename, writable, low_4gb, /* unquicken*/ false, error_msg);
David Brazdil7b49e6c2016-09-01 11:06:18 +0100200 if (vdex_.get() == nullptr) {
201 *error_msg = StringPrintf("Failed to load vdex file '%s' %s",
202 vdex_filename.c_str(),
203 error_msg->c_str());
204 return false;
205 }
206 return true;
207}
208
Andreas Gampe049cff02015-12-01 23:27:12 -0800209bool OatFileBase::ComputeFields(uint8_t* requested_base,
210 const std::string& file_path,
211 std::string* error_msg) {
212 std::string symbol_error_msg;
213 begin_ = FindDynamicSymbolAddress("oatdata", &symbol_error_msg);
Andreas Gampefa8429b2015-04-07 18:34:42 -0700214 if (begin_ == nullptr) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800215 *error_msg = StringPrintf("Failed to find oatdata symbol in '%s' %s",
216 file_path.c_str(),
217 symbol_error_msg.c_str());
Andreas Gampefa8429b2015-04-07 18:34:42 -0700218 return false;
219 }
220 if (requested_base != nullptr && begin_ != requested_base) {
Nicolas Geoffrayf97cf2a2016-03-09 15:36:23 +0000221 // Host can fail this check. Do not dump there to avoid polluting the output.
Andreas Gampe7ec09042016-04-01 17:20:49 -0700222 if (kIsTargetBuild && (kIsDebugBuild || VLOG_IS_ON(oat))) {
Nicolas Geoffrayf97cf2a2016-03-09 15:36:23 +0000223 PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
224 }
Andreas Gampefa8429b2015-04-07 18:34:42 -0700225 *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
Andreas Gampe049cff02015-12-01 23:27:12 -0800226 "oatdata=%p != expected=%p. See process maps in the log.",
227 begin_, requested_base);
Andreas Gampefa8429b2015-04-07 18:34:42 -0700228 return false;
229 }
Andreas Gampe049cff02015-12-01 23:27:12 -0800230 end_ = FindDynamicSymbolAddress("oatlastword", &symbol_error_msg);
Andreas Gampefa8429b2015-04-07 18:34:42 -0700231 if (end_ == nullptr) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800232 *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s' %s",
233 file_path.c_str(),
234 symbol_error_msg.c_str());
Andreas Gampefa8429b2015-04-07 18:34:42 -0700235 return false;
236 }
237 // Readjust to be non-inclusive upper bound.
238 end_ += sizeof(uint32_t);
239
Andreas Gampe049cff02015-12-01 23:27:12 -0800240 bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg));
Andreas Gampefa8429b2015-04-07 18:34:42 -0700241 if (bss_begin_ == nullptr) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800242 // No .bss section.
Andreas Gampefa8429b2015-04-07 18:34:42 -0700243 bss_end_ = nullptr;
Andreas Gampefa8429b2015-04-07 18:34:42 -0700244 } else {
Andreas Gampe049cff02015-12-01 23:27:12 -0800245 bss_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbsslastword", &symbol_error_msg));
Andreas Gampefa8429b2015-04-07 18:34:42 -0700246 if (bss_end_ == nullptr) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800247 *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'", file_path.c_str());
Andreas Gampefa8429b2015-04-07 18:34:42 -0700248 return false;
249 }
250 // Readjust to be non-inclusive upper bound.
251 bss_end_ += sizeof(uint32_t);
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100252 // Find bss methods if present.
253 bss_methods_ =
254 const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssmethods", &symbol_error_msg));
Vladimir Markoaad75c62016-10-03 08:46:48 +0000255 // Find bss roots if present.
256 bss_roots_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssroots", &symbol_error_msg));
Andreas Gampefa8429b2015-04-07 18:34:42 -0700257 }
258
Andreas Gampe049cff02015-12-01 23:27:12 -0800259 return true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800260}
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800261
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100262// Read an unaligned entry from the OatDexFile data in OatFile and advance the read
263// position by the number of bytes read, i.e. sizeof(T).
264// Return true on success, false if the read would go beyond the end of the OatFile.
265template <typename T>
Vladimir Marko722fa982015-10-19 18:18:27 +0100266inline static bool ReadOatDexFileData(const OatFile& oat_file,
267 /*inout*/const uint8_t** oat,
268 /*out*/T* value) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100269 DCHECK(oat != nullptr);
270 DCHECK(value != nullptr);
271 DCHECK_LE(*oat, oat_file.End());
272 if (UNLIKELY(static_cast<size_t>(oat_file.End() - *oat) < sizeof(T))) {
273 return false;
274 }
275 static_assert(std::is_trivial<T>::value, "T must be a trivial type");
276 typedef __attribute__((__aligned__(1))) T unaligned_type;
277 *value = *reinterpret_cast<const unaligned_type*>(*oat);
278 *oat += sizeof(T);
279 return true;
280}
281
Orion Hodsonc069a302017-01-18 09:23:12 +0000282static bool FindDexFileMapItem(const uint8_t* dex_begin,
283 const uint8_t* dex_end,
284 DexFile::MapItemType map_item_type,
285 const DexFile::MapItem** result_item) {
286 *result_item = nullptr;
287
288 const DexFile::Header* header =
289 BoundsCheckedCast<const DexFile::Header*>(dex_begin, dex_begin, dex_end);
290 if (nullptr == header) return false;
291
292 if (!DexFile::IsMagicValid(header->magic_)) return true; // Not a dex file, not an error.
293
294 const DexFile::MapList* map_list =
295 BoundsCheckedCast<const DexFile::MapList*>(dex_begin + header->map_off_, dex_begin, dex_end);
296 if (nullptr == map_list) return false;
297
298 const DexFile::MapItem* map_item = map_list->list_;
299 size_t count = map_list->size_;
300 while (count--) {
301 if (map_item->type_ == static_cast<uint16_t>(map_item_type)) {
302 *result_item = map_item;
303 break;
304 }
305 map_item = BoundsCheckedCast<const DexFile::MapItem*>(map_item + 1, dex_begin, dex_end);
306 if (nullptr == map_item) return false;
307 }
308
309 return true;
310}
311
Andreas Gampe049cff02015-12-01 23:27:12 -0800312bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) {
Brian Carlstromf1b30302013-03-28 10:35:32 -0700313 if (!GetOatHeader().IsValid()) {
Andreas Gampe2bcb3b22014-12-12 15:25:14 -0800314 std::string cause = GetOatHeader().GetValidationErrorMessage();
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100315 *error_msg = StringPrintf("Invalid oat header for '%s': %s",
316 GetLocation().c_str(),
Andreas Gampe2bcb3b22014-12-12 15:25:14 -0800317 cause.c_str());
Brian Carlstromf1b30302013-03-28 10:35:32 -0700318 return false;
319 }
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100320 PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
321 size_t key_value_store_size =
322 (Size() >= sizeof(OatHeader)) ? GetOatHeader().GetKeyValueStoreSize() : 0u;
323 if (Size() < sizeof(OatHeader) + key_value_store_size) {
324 *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader, "
325 "size = %zu < %zu + %zu",
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100326 GetLocation().c_str(),
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100327 Size(),
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100328 sizeof(OatHeader),
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100329 key_value_store_size);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700330 return false;
331 }
332
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100333 size_t oat_dex_files_offset = GetOatHeader().GetOatDexFilesOffset();
334 if (oat_dex_files_offset < GetOatHeader().GetHeaderSize() || oat_dex_files_offset > Size()) {
335 *error_msg = StringPrintf("In oat file '%s' found invalid oat dex files offset: "
336 "%zu is not in [%zu, %zu]",
337 GetLocation().c_str(),
338 oat_dex_files_offset,
339 GetOatHeader().GetHeaderSize(),
340 Size());
341 return false;
342 }
343 const uint8_t* oat = Begin() + oat_dex_files_offset; // Jump to the OatDexFile records.
344
345 DCHECK_GE(static_cast<size_t>(pointer_size), alignof(GcRoot<mirror::Object>));
346 if (!IsAligned<kPageSize>(bss_begin_) ||
347 !IsAlignedParam(bss_methods_, static_cast<size_t>(pointer_size)) ||
348 !IsAlignedParam(bss_roots_, static_cast<size_t>(pointer_size)) ||
Vladimir Markoaad75c62016-10-03 08:46:48 +0000349 !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_end_)) {
350 *error_msg = StringPrintf("In oat file '%s' found unaligned bss symbol(s): "
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100351 "begin = %p, methods_ = %p, roots = %p, end = %p",
Vladimir Markoaad75c62016-10-03 08:46:48 +0000352 GetLocation().c_str(),
353 bss_begin_,
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100354 bss_methods_,
Vladimir Markoaad75c62016-10-03 08:46:48 +0000355 bss_roots_,
356 bss_end_);
357 return false;
358 }
359
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100360 if ((bss_methods_ != nullptr && (bss_methods_ < bss_begin_ || bss_methods_ > bss_end_)) ||
361 (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) ||
362 (bss_methods_ != nullptr && bss_roots_ != nullptr && bss_methods_ > bss_roots_)) {
363 *error_msg = StringPrintf("In oat file '%s' found bss symbol(s) outside .bss or unordered: "
364 "begin = %p, methods_ = %p, roots = %p, end = %p",
Vladimir Markoaad75c62016-10-03 08:46:48 +0000365 GetLocation().c_str(),
Vladimir Markoaad75c62016-10-03 08:46:48 +0000366 bss_begin_,
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100367 bss_methods_,
368 bss_roots_,
Vladimir Markoaad75c62016-10-03 08:46:48 +0000369 bss_end_);
370 return false;
371 }
372
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100373 uint8_t* after_arrays = (bss_methods_ != nullptr) ? bss_methods_ : bss_roots_; // May be null.
374 uint8_t* dex_cache_arrays = (bss_begin_ == after_arrays) ? nullptr : bss_begin_;
Vladimir Marko1998cd02017-01-13 13:02:58 +0000375 uint8_t* dex_cache_arrays_end =
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100376 (bss_begin_ == after_arrays) ? nullptr : (after_arrays != nullptr) ? after_arrays : bss_end_;
Vladimir Marko1998cd02017-01-13 13:02:58 +0000377 DCHECK_EQ(dex_cache_arrays != nullptr, dex_cache_arrays_end != nullptr);
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100378 uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
379 oat_dex_files_storage_.reserve(dex_file_count);
380 for (size_t i = 0; i < dex_file_count; i++) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100381 uint32_t dex_file_location_size;
382 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
383 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file "
384 "location size",
385 GetLocation().c_str(),
386 i);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700387 return false;
388 }
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100389 if (UNLIKELY(dex_file_location_size == 0U)) {
390 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name",
391 GetLocation().c_str(),
392 i);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700393 return false;
394 }
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000395 if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100396 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file "
397 "location",
398 GetLocation().c_str(),
399 i);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700400 return false;
401 }
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000402 const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
403 oat += dex_file_location_size;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700404
Richard Uhlere5fed032015-03-18 08:21:11 -0700405 std::string dex_file_location = ResolveRelativeEncodedDexLocation(
406 abs_dex_location,
407 std::string(dex_file_location_data, dex_file_location_size));
Brian Carlstrome24fa612011-09-29 00:53:55 -0700408
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100409 uint32_t dex_file_checksum;
410 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
411 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after "
412 "dex file checksum",
413 GetLocation().c_str(),
414 i,
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700415 dex_file_location.c_str());
Brian Carlstromfb331d72013-07-25 22:00:16 -0700416 return false;
417 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700418
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100419 uint32_t dex_file_offset;
420 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
421 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
422 "after dex file offsets",
423 GetLocation().c_str(),
424 i,
425 dex_file_location.c_str());
426 return false;
427 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700428 if (UNLIKELY(dex_file_offset == 0U)) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100429 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with zero dex "
430 "file offset",
431 GetLocation().c_str(),
432 i,
433 dex_file_location.c_str());
Brian Carlstromfb331d72013-07-25 22:00:16 -0700434 return false;
435 }
David Brazdil7b49e6c2016-09-01 11:06:18 +0100436 if (UNLIKELY(dex_file_offset > DexSize())) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100437 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
438 "offset %u > %zu",
439 GetLocation().c_str(),
440 i,
441 dex_file_location.c_str(),
442 dex_file_offset,
David Brazdil7b49e6c2016-09-01 11:06:18 +0100443 DexSize());
Brian Carlstromfb331d72013-07-25 22:00:16 -0700444 return false;
445 }
David Brazdil7b49e6c2016-09-01 11:06:18 +0100446 if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000447 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
448 "offset %u of %zu but the size of dex file header is %zu",
449 GetLocation().c_str(),
450 i,
451 dex_file_location.c_str(),
452 dex_file_offset,
David Brazdil7b49e6c2016-09-01 11:06:18 +0100453 DexSize(),
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000454 sizeof(DexFile::Header));
455 return false;
456 }
Brian Carlstrom89521892011-12-07 22:05:07 -0800457
David Brazdil7b49e6c2016-09-01 11:06:18 +0100458 const uint8_t* dex_file_pointer = DexBegin() + dex_file_offset;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700459 if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100460 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
461 "dex file magic '%s'",
462 GetLocation().c_str(),
463 i,
464 dex_file_location.c_str(),
465 dex_file_pointer);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700466 return false;
467 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700468 if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100469 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
470 "dex file version '%s'",
471 GetLocation().c_str(),
472 i,
473 dex_file_location.c_str(),
474 dex_file_pointer);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700475 return false;
476 }
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800477 const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
David Brazdil7b49e6c2016-09-01 11:06:18 +0100478 if (DexSize() - dex_file_offset < header->file_size_) {
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000479 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
480 "offset %u and size %u truncated at %zu",
481 GetLocation().c_str(),
482 i,
483 dex_file_location.c_str(),
484 dex_file_offset,
485 header->file_size_,
David Brazdil7b49e6c2016-09-01 11:06:18 +0100486 DexSize());
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000487 return false;
488 }
Artem Udovichenkod9786b02015-10-14 16:36:55 +0300489
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000490 uint32_t class_offsets_offset;
491 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {
492 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
493 "after class offsets offset",
494 GetLocation().c_str(),
495 i,
Artem Udovichenkod9786b02015-10-14 16:36:55 +0300496 dex_file_location.c_str());
497 return false;
498 }
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000499 if (UNLIKELY(class_offsets_offset > Size()) ||
500 UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) {
501 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
502 "class offsets, offset %u of %zu, class defs %u",
503 GetLocation().c_str(),
504 i,
505 dex_file_location.c_str(),
506 class_offsets_offset,
507 Size(),
508 header->class_defs_size_);
509 return false;
510 }
511 if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) {
512 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned "
513 "class offsets, offset %u",
514 GetLocation().c_str(),
515 i,
516 dex_file_location.c_str(),
517 class_offsets_offset);
518 return false;
519 }
520 const uint32_t* class_offsets_pointer =
521 reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset);
522
523 uint32_t lookup_table_offset;
524 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {
525 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
526 "after lookup table offset",
527 GetLocation().c_str(),
528 i,
Artem Udovichenkod9786b02015-10-14 16:36:55 +0300529 dex_file_location.c_str());
530 return false;
531 }
532 const uint8_t* lookup_table_data = lookup_table_offset != 0u
533 ? Begin() + lookup_table_offset
534 : nullptr;
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000535 if (lookup_table_offset != 0u &&
536 (UNLIKELY(lookup_table_offset > Size()) ||
537 UNLIKELY(Size() - lookup_table_offset <
538 TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100539 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000540 "type lookup table, offset %u of %zu, class defs %u",
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100541 GetLocation().c_str(),
542 i,
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000543 dex_file_location.c_str(),
544 lookup_table_offset,
545 Size(),
546 header->class_defs_size_);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700547 return false;
548 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700549
Mathieu Chartier120aa282017-08-05 16:03:03 -0700550 uint32_t dex_layout_sections_offset;
551 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_layout_sections_offset))) {
552 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
553 "after dex layout sections offset",
554 GetLocation().c_str(),
555 i,
556 dex_file_location.c_str());
557 return false;
558 }
559 const DexLayoutSections* const dex_layout_sections = dex_layout_sections_offset != 0
560 ? reinterpret_cast<const DexLayoutSections*>(Begin() + dex_layout_sections_offset)
561 : nullptr;
562
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100563 uint32_t method_bss_mapping_offset;
564 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &method_bss_mapping_offset))) {
565 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
566 "after method bss mapping offset",
567 GetLocation().c_str(),
568 i,
569 dex_file_location.c_str());
570 return false;
571 }
572 const bool readable_method_bss_mapping_size =
573 method_bss_mapping_offset != 0u &&
574 method_bss_mapping_offset <= Size() &&
575 IsAligned<alignof(MethodBssMapping)>(method_bss_mapping_offset) &&
576 Size() - method_bss_mapping_offset >= MethodBssMapping::ComputeSize(0);
577 const MethodBssMapping* method_bss_mapping = readable_method_bss_mapping_size
578 ? reinterpret_cast<const MethodBssMapping*>(Begin() + method_bss_mapping_offset)
579 : nullptr;
580 if (method_bss_mapping_offset != 0u &&
581 (UNLIKELY(method_bss_mapping == nullptr) ||
582 UNLIKELY(method_bss_mapping->size() == 0u) ||
583 UNLIKELY(Size() - method_bss_mapping_offset <
584 MethodBssMapping::ComputeSize(method_bss_mapping->size())))) {
585 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned or "
586 " truncated method bss mapping, offset %u of %zu, length %zu",
587 GetLocation().c_str(),
588 i,
589 dex_file_location.c_str(),
590 method_bss_mapping_offset,
591 Size(),
592 method_bss_mapping != nullptr ? method_bss_mapping->size() : 0u);
593 return false;
594 }
595 if (kIsDebugBuild && method_bss_mapping != nullptr) {
596 const MethodBssMappingEntry* prev_entry = nullptr;
597 for (const MethodBssMappingEntry& entry : *method_bss_mapping) {
598 CHECK_ALIGNED_PARAM(entry.bss_offset, static_cast<size_t>(pointer_size));
599 CHECK_LT(entry.bss_offset, BssSize());
600 CHECK_LE(POPCOUNT(entry.index_mask) * static_cast<size_t>(pointer_size), entry.bss_offset);
601 size_t index_mask_span = (entry.index_mask != 0u) ? 16u - CTZ(entry.index_mask) : 0u;
602 CHECK_LE(index_mask_span, entry.method_index);
603 if (prev_entry != nullptr) {
604 CHECK_LT(prev_entry->method_index, entry.method_index - index_mask_span);
605 }
606 prev_entry = &entry;
607 }
608 CHECK_LT(prev_entry->method_index,
609 reinterpret_cast<const DexFile::Header*>(dex_file_pointer)->method_ids_size_);
610 }
611
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100612 uint8_t* current_dex_cache_arrays = nullptr;
Vladimir Marko09d09432015-09-08 13:47:48 +0100613 if (dex_cache_arrays != nullptr) {
Orion Hodsonc069a302017-01-18 09:23:12 +0000614 // All DexCache types except for CallSite have their instance counts in the
615 // DexFile header. For CallSites, we need to read the info from the MapList.
616 const DexFile::MapItem* call_sites_item = nullptr;
617 if (!FindDexFileMapItem(DexBegin(),
618 DexEnd(),
619 DexFile::MapItemType::kDexTypeCallSiteIdItem,
620 &call_sites_item)) {
621 *error_msg = StringPrintf("In oat file '%s' could not read data from truncated DexFile map",
622 GetLocation().c_str());
623 return false;
624 }
625 size_t num_call_sites = call_sites_item == nullptr ? 0 : call_sites_item->size_;
626 DexCacheArraysLayout layout(pointer_size, *header, num_call_sites);
Vladimir Marko09d09432015-09-08 13:47:48 +0100627 if (layout.Size() != 0u) {
Vladimir Markoaad75c62016-10-03 08:46:48 +0000628 if (static_cast<size_t>(dex_cache_arrays_end - dex_cache_arrays) < layout.Size()) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100629 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with "
630 "truncated dex cache arrays, %zu < %zu.",
631 GetLocation().c_str(),
632 i,
633 dex_file_location.c_str(),
Vladimir Markoaad75c62016-10-03 08:46:48 +0000634 static_cast<size_t>(dex_cache_arrays_end - dex_cache_arrays),
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100635 layout.Size());
Vladimir Marko09d09432015-09-08 13:47:48 +0100636 return false;
637 }
638 current_dex_cache_arrays = dex_cache_arrays;
639 dex_cache_arrays += layout.Size();
640 }
641 }
642
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100643 std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str());
644
645 // Create the OatDexFile and add it to the owning container.
Vladimir Marko539690a2014-06-05 18:36:42 +0100646 OatDexFile* oat_dex_file = new OatDexFile(this,
647 dex_file_location,
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100648 canonical_location,
Vladimir Marko539690a2014-06-05 18:36:42 +0100649 dex_file_checksum,
650 dex_file_pointer,
Artem Udovichenkod9786b02015-10-14 16:36:55 +0300651 lookup_table_data,
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100652 method_bss_mapping,
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000653 class_offsets_pointer,
Mathieu Chartier120aa282017-08-05 16:03:03 -0700654 current_dex_cache_arrays,
655 dex_layout_sections);
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100656 oat_dex_files_storage_.push_back(oat_dex_file);
657
658 // Add the location and canonical location (if different) to the oat_dex_files_ table.
Vladimir Marko3f5838d2014-08-07 18:07:18 +0100659 StringPiece key(oat_dex_file->GetDexFileLocation());
Vladimir Marko539690a2014-06-05 18:36:42 +0100660 oat_dex_files_.Put(key, oat_dex_file);
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100661 if (canonical_location != dex_file_location) {
662 StringPiece canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
663 oat_dex_files_.Put(canonical_key, oat_dex_file);
664 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700665 }
Vladimir Marko09d09432015-09-08 13:47:48 +0100666
Vladimir Markoaad75c62016-10-03 08:46:48 +0000667 if (dex_cache_arrays != dex_cache_arrays_end) {
Vladimir Marko09d09432015-09-08 13:47:48 +0100668 // We expect the bss section to be either empty (dex_cache_arrays and bss_end_
Vladimir Markoaad75c62016-10-03 08:46:48 +0000669 // both null) or contain just the dex cache arrays and optionally some GC roots.
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100670 *error_msg = StringPrintf("In oat file '%s' found unexpected bss size bigger by %zu bytes.",
Vladimir Marko09d09432015-09-08 13:47:48 +0100671 GetLocation().c_str(),
672 static_cast<size_t>(bss_end_ - dex_cache_arrays));
673 return false;
674 }
Brian Carlstromf1b30302013-03-28 10:35:32 -0700675 return true;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700676}
677
Andreas Gampe049cff02015-12-01 23:27:12 -0800678////////////////////////
679// OatFile via dlopen //
680////////////////////////
681
Andreas Gampe049cff02015-12-01 23:27:12 -0800682class DlOpenOatFile FINAL : public OatFileBase {
683 public:
684 DlOpenOatFile(const std::string& filename, bool executable)
685 : OatFileBase(filename, executable),
686 dlopen_handle_(nullptr),
Richard Uhlera206c742016-05-24 15:04:22 -0700687 shared_objects_before_(0) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800688 }
689
690 ~DlOpenOatFile() {
691 if (dlopen_handle_ != nullptr) {
Richard Uhlera206c742016-05-24 15:04:22 -0700692 if (!kIsTargetBuild) {
693 MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
694 host_dlopen_handles_.erase(dlopen_handle_);
Mathieu Chartierc7d3f4b2016-06-01 10:48:19 -0700695 dlclose(dlopen_handle_);
696 } else {
697 dlclose(dlopen_handle_);
Richard Uhlera206c742016-05-24 15:04:22 -0700698 }
Andreas Gampe049cff02015-12-01 23:27:12 -0800699 }
Andreas Gampe049cff02015-12-01 23:27:12 -0800700 }
701
702 protected:
703 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
704 std::string* error_msg) const OVERRIDE {
705 const uint8_t* ptr =
706 reinterpret_cast<const uint8_t*>(dlsym(dlopen_handle_, symbol_name.c_str()));
707 if (ptr == nullptr) {
708 *error_msg = dlerror();
709 }
710 return ptr;
711 }
712
Andreas Gampe4075f832016-05-18 13:09:54 -0700713 void PreLoad() OVERRIDE;
714
Andreas Gampe049cff02015-12-01 23:27:12 -0800715 bool Load(const std::string& elf_filename,
716 uint8_t* oat_file_begin,
717 bool writable,
718 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800719 bool low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -0800720 std::string* error_msg) OVERRIDE;
721
722 // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
723 void PreSetup(const std::string& elf_filename) OVERRIDE;
724
725 private:
726 bool Dlopen(const std::string& elf_filename,
727 uint8_t* oat_file_begin,
728 std::string* error_msg);
729
Richard Uhlera206c742016-05-24 15:04:22 -0700730 // On the host, if the same library is loaded again with dlopen the same
731 // file handle is returned. This differs from the behavior of dlopen on the
732 // target, where dlopen reloads the library at a different address every
733 // time you load it. The runtime relies on the target behavior to ensure
734 // each instance of the loaded library has a unique dex cache. To avoid
735 // problems, we fall back to our own linker in the case when the same
736 // library is opened multiple times on host. dlopen_handles_ is used to
737 // detect that case.
738 // Guarded by host_dlopen_handles_lock_;
739 static std::unordered_set<void*> host_dlopen_handles_;
740
Andreas Gampe049cff02015-12-01 23:27:12 -0800741 // dlopen handle during runtime.
742 void* dlopen_handle_; // TODO: Unique_ptr with custom deleter.
743
744 // Dummy memory map objects corresponding to the regions mapped by dlopen.
745 std::vector<std::unique_ptr<MemMap>> dlopen_mmaps_;
746
Andreas Gampe4075f832016-05-18 13:09:54 -0700747 // The number of shared objects the linker told us about before loading. Used to
748 // (optimistically) optimize the PreSetup stage (see comment there).
749 size_t shared_objects_before_;
750
Andreas Gampe049cff02015-12-01 23:27:12 -0800751 DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile);
752};
753
Richard Uhlera206c742016-05-24 15:04:22 -0700754std::unordered_set<void*> DlOpenOatFile::host_dlopen_handles_;
755
Andreas Gampe4075f832016-05-18 13:09:54 -0700756void DlOpenOatFile::PreLoad() {
757#ifdef __APPLE__
Andreas Gampe39004a62016-05-18 21:27:00 -0700758 UNUSED(shared_objects_before_);
Andreas Gampe4075f832016-05-18 13:09:54 -0700759 LOG(FATAL) << "Should not reach here.";
760 UNREACHABLE();
761#else
762 // Count the entries in dl_iterate_phdr we get at this point in time.
763 struct dl_iterate_context {
764 static int callback(struct dl_phdr_info *info ATTRIBUTE_UNUSED,
765 size_t size ATTRIBUTE_UNUSED,
766 void *data) {
767 reinterpret_cast<dl_iterate_context*>(data)->count++;
768 return 0; // Continue iteration.
769 }
770 size_t count = 0;
771 } context;
772
773 dl_iterate_phdr(dl_iterate_context::callback, &context);
774 shared_objects_before_ = context.count;
775#endif
776}
777
Andreas Gampe049cff02015-12-01 23:27:12 -0800778bool DlOpenOatFile::Load(const std::string& elf_filename,
779 uint8_t* oat_file_begin,
780 bool writable,
781 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800782 bool low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -0800783 std::string* error_msg) {
784 // Use dlopen only when flagged to do so, and when it's OK to load things executable.
785 // TODO: Also try when not executable? The issue here could be re-mapping as writable (as
786 // !executable is a sign that we may want to patch), which may not be allowed for
787 // various reasons.
788 if (!kUseDlopen) {
789 *error_msg = "DlOpen is disabled.";
790 return false;
791 }
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800792 if (low_4gb) {
793 *error_msg = "DlOpen does not support low 4gb loading.";
794 return false;
795 }
Andreas Gampe049cff02015-12-01 23:27:12 -0800796 if (writable) {
797 *error_msg = "DlOpen does not support writable loading.";
798 return false;
799 }
800 if (!executable) {
801 *error_msg = "DlOpen does not support non-executable loading.";
802 return false;
803 }
804
805 // dlopen always returns the same library if it is already opened on the host. For this reason
806 // we only use dlopen if we are the target or we do not already have the dex file opened. Having
807 // the same library loaded multiple times at different addresses is required for class unloading
808 // and for having dex caches arrays in the .bss section.
809 if (!kIsTargetBuild) {
810 if (!kUseDlopenOnHost) {
811 *error_msg = "DlOpen disabled for host.";
812 return false;
813 }
Andreas Gampe049cff02015-12-01 23:27:12 -0800814 }
815
816 bool success = Dlopen(elf_filename, oat_file_begin, error_msg);
817 DCHECK(dlopen_handle_ != nullptr || !success);
818
819 return success;
820}
821
822bool DlOpenOatFile::Dlopen(const std::string& elf_filename,
823 uint8_t* oat_file_begin,
824 std::string* error_msg) {
825#ifdef __APPLE__
826 // The dl_iterate_phdr syscall is missing. There is similar API on OSX,
827 // but let's fallback to the custom loading code for the time being.
828 UNUSED(elf_filename, oat_file_begin);
829 *error_msg = "Dlopen unsupported on Mac.";
830 return false;
831#else
832 {
833 UniqueCPtr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
834 if (absolute_path == nullptr) {
835 *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
836 return false;
837 }
Bilyan Borisovbb661c02016-04-04 16:27:32 +0100838#ifdef ART_TARGET_ANDROID
Anton Kirilov3a2e78e2017-01-06 13:33:42 +0000839 android_dlextinfo extinfo = {};
Andreas Gampe049cff02015-12-01 23:27:12 -0800840 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD | // Force-load, don't reuse handle
841 // (open oat files multiple
842 // times).
843 ANDROID_DLEXT_FORCE_FIXED_VADDR; // Take a non-zero vaddr as absolute
844 // (non-pic boot image).
Andreas Gampe226b91e2015-12-02 10:29:33 -0800845 if (oat_file_begin != nullptr) { //
846 extinfo.flags |= ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS; // Use the requested addr if
847 extinfo.reserved_addr = oat_file_begin; // vaddr = 0.
848 } // (pic boot image).
Andreas Gampe049cff02015-12-01 23:27:12 -0800849 dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
850#else
Andreas Gampe049cff02015-12-01 23:27:12 -0800851 UNUSED(oat_file_begin);
Julien Duraj1af0c4f2016-11-16 14:05:48 +0000852 static_assert(!kIsTargetBuild || kIsTargetLinux, "host_dlopen_handles_ will leak handles");
Mathieu Chartierc7d3f4b2016-06-01 10:48:19 -0700853 MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
Richard Uhlera206c742016-05-24 15:04:22 -0700854 dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
855 if (dlopen_handle_ != nullptr) {
Richard Uhlera206c742016-05-24 15:04:22 -0700856 if (!host_dlopen_handles_.insert(dlopen_handle_).second) {
857 dlclose(dlopen_handle_);
858 dlopen_handle_ = nullptr;
859 *error_msg = StringPrintf("host dlopen re-opened '%s'", elf_filename.c_str());
860 return false;
861 }
862 }
Bilyan Borisovbb661c02016-04-04 16:27:32 +0100863#endif // ART_TARGET_ANDROID
Andreas Gampe049cff02015-12-01 23:27:12 -0800864 }
865 if (dlopen_handle_ == nullptr) {
866 *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
867 return false;
868 }
869 return true;
870#endif
871}
872
873void DlOpenOatFile::PreSetup(const std::string& elf_filename) {
Andreas Gampe74f07b52015-12-02 11:53:26 -0800874#ifdef __APPLE__
875 UNUSED(elf_filename);
876 LOG(FATAL) << "Should not reach here.";
877 UNREACHABLE();
878#else
Andreas Gampe049cff02015-12-01 23:27:12 -0800879 struct dl_iterate_context {
880 static int callback(struct dl_phdr_info *info, size_t /* size */, void *data) {
881 auto* context = reinterpret_cast<dl_iterate_context*>(data);
Andreas Gampe4075f832016-05-18 13:09:54 -0700882 context->shared_objects_seen++;
883 if (context->shared_objects_seen < context->shared_objects_before) {
884 // We haven't been called yet for anything we haven't seen before. Just continue.
885 // Note: this is aggressively optimistic. If another thread was unloading a library,
886 // we may miss out here. However, this does not happen often in practice.
887 return 0;
888 }
889
Andreas Gampe049cff02015-12-01 23:27:12 -0800890 // See whether this callback corresponds to the file which we have just loaded.
891 bool contains_begin = false;
892 for (int i = 0; i < info->dlpi_phnum; i++) {
893 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
894 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
895 info->dlpi_phdr[i].p_vaddr);
896 size_t memsz = info->dlpi_phdr[i].p_memsz;
897 if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
898 contains_begin = true;
899 break;
900 }
901 }
902 }
903 // Add dummy mmaps for this file.
904 if (contains_begin) {
905 for (int i = 0; i < info->dlpi_phnum; i++) {
906 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
907 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
908 info->dlpi_phdr[i].p_vaddr);
909 size_t memsz = info->dlpi_phdr[i].p_memsz;
910 MemMap* mmap = MemMap::MapDummy(info->dlpi_name, vaddr, memsz);
911 context->dlopen_mmaps_->push_back(std::unique_ptr<MemMap>(mmap));
912 }
913 }
914 return 1; // Stop iteration and return 1 from dl_iterate_phdr.
915 }
916 return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished.
917 }
918 const uint8_t* const begin_;
919 std::vector<std::unique_ptr<MemMap>>* const dlopen_mmaps_;
Andreas Gampe4075f832016-05-18 13:09:54 -0700920 const size_t shared_objects_before;
921 size_t shared_objects_seen;
922 };
923 dl_iterate_context context = { Begin(), &dlopen_mmaps_, shared_objects_before_, 0};
Andreas Gampe049cff02015-12-01 23:27:12 -0800924
925 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
Andreas Gampe4075f832016-05-18 13:09:54 -0700926 // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0
927 // before giving up. This should be unusual.
928 VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before="
929 << shared_objects_before_;
930 dl_iterate_context context0 = { Begin(), &dlopen_mmaps_, 0, 0};
931 if (dl_iterate_phdr(dl_iterate_context::callback, &context0) == 0) {
932 // OK, give up and print an error.
933 PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
934 LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps.";
935 }
Andreas Gampe049cff02015-12-01 23:27:12 -0800936 }
Andreas Gampe74f07b52015-12-02 11:53:26 -0800937#endif
Andreas Gampe049cff02015-12-01 23:27:12 -0800938}
939
940////////////////////////////////////////////////
941// OatFile via our own ElfFile implementation //
942////////////////////////////////////////////////
943
944class ElfOatFile FINAL : public OatFileBase {
945 public:
946 ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {}
947
948 static ElfOatFile* OpenElfFile(File* file,
949 const std::string& location,
950 uint8_t* requested_base,
951 uint8_t* oat_file_begin, // Override base if not null
952 bool writable,
953 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800954 bool low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -0800955 const char* abs_dex_location,
956 std::string* error_msg);
957
958 bool InitializeFromElfFile(ElfFile* elf_file,
David Brazdilc93b3be2016-09-12 18:49:58 +0100959 VdexFile* vdex_file,
Andreas Gampe049cff02015-12-01 23:27:12 -0800960 const char* abs_dex_location,
961 std::string* error_msg);
962
963 protected:
964 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
965 std::string* error_msg) const OVERRIDE {
966 const uint8_t* ptr = elf_file_->FindDynamicSymbolAddress(symbol_name);
967 if (ptr == nullptr) {
968 *error_msg = "(Internal implementation could not find symbol)";
969 }
970 return ptr;
971 }
972
Andreas Gampe4075f832016-05-18 13:09:54 -0700973 void PreLoad() OVERRIDE {
974 }
975
Andreas Gampe049cff02015-12-01 23:27:12 -0800976 bool Load(const std::string& elf_filename,
977 uint8_t* oat_file_begin, // Override where the file is loaded to if not null
978 bool writable,
979 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800980 bool low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -0800981 std::string* error_msg) OVERRIDE;
982
983 void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) OVERRIDE {
984 }
985
986 private:
987 bool ElfFileOpen(File* file,
988 uint8_t* oat_file_begin, // Override where the file is loaded to if not null
989 bool writable,
990 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800991 bool low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -0800992 std::string* error_msg);
993
994 private:
995 // Backing memory map for oat file during cross compilation.
996 std::unique_ptr<ElfFile> elf_file_;
997
998 DISALLOW_COPY_AND_ASSIGN(ElfOatFile);
999};
1000
1001ElfOatFile* ElfOatFile::OpenElfFile(File* file,
1002 const std::string& location,
1003 uint8_t* requested_base,
1004 uint8_t* oat_file_begin, // Override base if not null
1005 bool writable,
1006 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001007 bool low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -08001008 const char* abs_dex_location,
1009 std::string* error_msg) {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08001010 ScopedTrace trace("Open elf file " + location);
Andreas Gampe049cff02015-12-01 23:27:12 -08001011 std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, executable));
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001012 bool success = oat_file->ElfFileOpen(file,
1013 oat_file_begin,
1014 writable,
1015 low_4gb,
1016 executable,
1017 error_msg);
Andreas Gampe049cff02015-12-01 23:27:12 -08001018 if (!success) {
1019 CHECK(!error_msg->empty());
1020 return nullptr;
1021 }
1022
1023 // Complete the setup.
1024 if (!oat_file->ComputeFields(requested_base, file->GetPath(), error_msg)) {
1025 return nullptr;
1026 }
1027
1028 if (!oat_file->Setup(abs_dex_location, error_msg)) {
1029 return nullptr;
1030 }
1031
1032 return oat_file.release();
1033}
1034
1035bool ElfOatFile::InitializeFromElfFile(ElfFile* elf_file,
David Brazdilc93b3be2016-09-12 18:49:58 +01001036 VdexFile* vdex_file,
Andreas Gampe049cff02015-12-01 23:27:12 -08001037 const char* abs_dex_location,
1038 std::string* error_msg) {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08001039 ScopedTrace trace(__PRETTY_FUNCTION__);
Andreas Gampe049cff02015-12-01 23:27:12 -08001040 if (IsExecutable()) {
1041 *error_msg = "Cannot initialize from elf file in executable mode.";
1042 return false;
1043 }
1044 elf_file_.reset(elf_file);
David Brazdilc93b3be2016-09-12 18:49:58 +01001045 SetVdex(vdex_file);
Andreas Gampe049cff02015-12-01 23:27:12 -08001046 uint64_t offset, size;
1047 bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
1048 CHECK(has_section);
1049 SetBegin(elf_file->Begin() + offset);
1050 SetEnd(elf_file->Begin() + size + offset);
1051 // Ignore the optional .bss section when opening non-executable.
1052 return Setup(abs_dex_location, error_msg);
1053}
1054
1055bool ElfOatFile::Load(const std::string& elf_filename,
1056 uint8_t* oat_file_begin, // Override where the file is loaded to if not null
1057 bool writable,
1058 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001059 bool low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -08001060 std::string* error_msg) {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08001061 ScopedTrace trace(__PRETTY_FUNCTION__);
Andreas Gampe049cff02015-12-01 23:27:12 -08001062 std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
1063 if (file == nullptr) {
1064 *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
1065 return false;
1066 }
1067 return ElfOatFile::ElfFileOpen(file.get(),
1068 oat_file_begin,
1069 writable,
1070 executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001071 low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -08001072 error_msg);
1073}
1074
1075bool ElfOatFile::ElfFileOpen(File* file,
1076 uint8_t* oat_file_begin,
1077 bool writable,
1078 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001079 bool low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -08001080 std::string* error_msg) {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08001081 ScopedTrace trace(__PRETTY_FUNCTION__);
Andreas Gampe049cff02015-12-01 23:27:12 -08001082 // TODO: rename requested_base to oat_data_begin
1083 elf_file_.reset(ElfFile::Open(file,
1084 writable,
1085 /*program_header_only*/true,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001086 low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -08001087 error_msg,
1088 oat_file_begin));
1089 if (elf_file_ == nullptr) {
1090 DCHECK(!error_msg->empty());
1091 return false;
1092 }
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001093 bool loaded = elf_file_->Load(file, executable, low_4gb, error_msg);
Andreas Gampe049cff02015-12-01 23:27:12 -08001094 DCHECK(loaded || !error_msg->empty());
1095 return loaded;
1096}
1097
1098//////////////////////////
1099// General OatFile code //
1100//////////////////////////
1101
1102std::string OatFile::ResolveRelativeEncodedDexLocation(
1103 const char* abs_dex_location, const std::string& rel_dex_location) {
1104 if (abs_dex_location != nullptr && rel_dex_location[0] != '/') {
1105 // Strip :classes<N>.dex used for secondary multidex files.
1106 std::string base = DexFile::GetBaseLocation(rel_dex_location);
1107 std::string multidex_suffix = DexFile::GetMultiDexSuffix(rel_dex_location);
1108
1109 // Check if the base is a suffix of the provided abs_dex_location.
1110 std::string target_suffix = "/" + base;
1111 std::string abs_location(abs_dex_location);
1112 if (abs_location.size() > target_suffix.size()) {
1113 size_t pos = abs_location.size() - target_suffix.size();
1114 if (abs_location.compare(pos, std::string::npos, target_suffix) == 0) {
1115 return abs_location + multidex_suffix;
1116 }
1117 }
1118 }
1119 return rel_dex_location;
1120}
1121
1122static void CheckLocation(const std::string& location) {
1123 CHECK(!location.empty());
1124}
1125
1126OatFile* OatFile::OpenWithElfFile(ElfFile* elf_file,
David Brazdilc93b3be2016-09-12 18:49:58 +01001127 VdexFile* vdex_file,
Andreas Gampe049cff02015-12-01 23:27:12 -08001128 const std::string& location,
1129 const char* abs_dex_location,
1130 std::string* error_msg) {
1131 std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, false /* executable */));
David Brazdilc93b3be2016-09-12 18:49:58 +01001132 return oat_file->InitializeFromElfFile(elf_file, vdex_file, abs_dex_location, error_msg)
Andreas Gampe049cff02015-12-01 23:27:12 -08001133 ? oat_file.release()
1134 : nullptr;
1135}
1136
David Brazdil7b49e6c2016-09-01 11:06:18 +01001137OatFile* OatFile::Open(const std::string& oat_filename,
1138 const std::string& oat_location,
Andreas Gampe049cff02015-12-01 23:27:12 -08001139 uint8_t* requested_base,
1140 uint8_t* oat_file_begin,
1141 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001142 bool low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -08001143 const char* abs_dex_location,
1144 std::string* error_msg) {
David Brazdil7b49e6c2016-09-01 11:06:18 +01001145 ScopedTrace trace("Open oat file " + oat_location);
1146 CHECK(!oat_filename.empty()) << oat_location;
1147 CheckLocation(oat_location);
Andreas Gampe54315c72016-05-18 21:10:42 -07001148
Calin Juravle367b9d82017-05-15 18:18:39 -07001149 std::string vdex_filename = GetVdexFilename(oat_filename);
David Brazdil7b49e6c2016-09-01 11:06:18 +01001150
1151 // Check that the files even exist, fast-fail.
1152 if (kIsVdexEnabled && !OS::FileExists(vdex_filename.c_str())) {
1153 *error_msg = StringPrintf("File %s does not exist.", vdex_filename.c_str());
1154 return nullptr;
1155 } else if (!OS::FileExists(oat_filename.c_str())) {
1156 *error_msg = StringPrintf("File %s does not exist.", oat_filename.c_str());
Andreas Gampe54315c72016-05-18 21:10:42 -07001157 return nullptr;
1158 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001159
1160 // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
1161 // disabled.
David Brazdil7b49e6c2016-09-01 11:06:18 +01001162 OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(vdex_filename,
1163 oat_filename,
1164 oat_location,
Andreas Gampe049cff02015-12-01 23:27:12 -08001165 requested_base,
1166 oat_file_begin,
David Brazdil7b49e6c2016-09-01 11:06:18 +01001167 false /* writable */,
Andreas Gampe049cff02015-12-01 23:27:12 -08001168 executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001169 low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -08001170 abs_dex_location,
1171 error_msg);
1172 if (with_dlopen != nullptr) {
1173 return with_dlopen;
1174 }
1175 if (kPrintDlOpenErrorMessage) {
David Brazdil7b49e6c2016-09-01 11:06:18 +01001176 LOG(ERROR) << "Failed to dlopen: " << oat_filename << " with error " << *error_msg;
Andreas Gampe049cff02015-12-01 23:27:12 -08001177 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001178 // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
1179 //
1180 // On target, dlopen may fail when compiling due to selinux restrictions on installd.
1181 //
1182 // We use our own ELF loader for Quick to deal with legacy apps that
1183 // open a generated dex file by name, remove the file, then open
1184 // another generated dex file with the same name. http://b/10614658
1185 //
1186 // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile.
1187 //
1188 //
1189 // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
1190 // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN.
David Brazdil7b49e6c2016-09-01 11:06:18 +01001191 OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(vdex_filename,
1192 oat_filename,
1193 oat_location,
Andreas Gampe049cff02015-12-01 23:27:12 -08001194 requested_base,
1195 oat_file_begin,
David Brazdil7b49e6c2016-09-01 11:06:18 +01001196 false /* writable */,
Andreas Gampe049cff02015-12-01 23:27:12 -08001197 executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001198 low_4gb,
Andreas Gampe049cff02015-12-01 23:27:12 -08001199 abs_dex_location,
1200 error_msg);
1201 return with_internal;
1202}
1203
1204OatFile* OatFile::OpenWritable(File* file,
1205 const std::string& location,
1206 const char* abs_dex_location,
1207 std::string* error_msg) {
1208 CheckLocation(location);
1209 return ElfOatFile::OpenElfFile(file,
1210 location,
1211 nullptr,
1212 nullptr,
1213 true,
1214 false,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001215 /*low_4gb*/false,
Andreas Gampe049cff02015-12-01 23:27:12 -08001216 abs_dex_location,
1217 error_msg);
1218}
1219
1220OatFile* OatFile::OpenReadable(File* file,
1221 const std::string& location,
1222 const char* abs_dex_location,
1223 std::string* error_msg) {
1224 CheckLocation(location);
1225 return ElfOatFile::OpenElfFile(file,
1226 location,
1227 nullptr,
1228 nullptr,
1229 false,
1230 false,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001231 /*low_4gb*/false,
Andreas Gampe049cff02015-12-01 23:27:12 -08001232 abs_dex_location,
1233 error_msg);
1234}
1235
1236OatFile::OatFile(const std::string& location, bool is_executable)
1237 : location_(location),
David Brazdil7b49e6c2016-09-01 11:06:18 +01001238 vdex_(nullptr),
Andreas Gampe049cff02015-12-01 23:27:12 -08001239 begin_(nullptr),
1240 end_(nullptr),
1241 bss_begin_(nullptr),
1242 bss_end_(nullptr),
Vladimir Marko0eb882b2017-05-15 13:39:18 +01001243 bss_methods_(nullptr),
Vladimir Markoaad75c62016-10-03 08:46:48 +00001244 bss_roots_(nullptr),
Andreas Gampe049cff02015-12-01 23:27:12 -08001245 is_executable_(is_executable),
1246 secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
1247 CHECK(!location_.empty());
1248}
1249
1250OatFile::~OatFile() {
1251 STLDeleteElements(&oat_dex_files_storage_);
1252}
1253
Brian Carlstrome24fa612011-09-29 00:53:55 -07001254const OatHeader& OatFile::GetOatHeader() const {
Ian Rogers30fab402012-01-23 15:43:46 -08001255 return *reinterpret_cast<const OatHeader*>(Begin());
Brian Carlstrome24fa612011-09-29 00:53:55 -07001256}
1257
Ian Rogers13735952014-10-08 12:43:28 -07001258const uint8_t* OatFile::Begin() const {
Andreas Gampefa8429b2015-04-07 18:34:42 -07001259 CHECK(begin_ != nullptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001260 return begin_;
Brian Carlstrome24fa612011-09-29 00:53:55 -07001261}
1262
Ian Rogers13735952014-10-08 12:43:28 -07001263const uint8_t* OatFile::End() const {
Andreas Gampefa8429b2015-04-07 18:34:42 -07001264 CHECK(end_ != nullptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001265 return end_;
Brian Carlstrome24fa612011-09-29 00:53:55 -07001266}
1267
Vladimir Marko5c42c292015-02-25 12:02:49 +00001268const uint8_t* OatFile::BssBegin() const {
1269 return bss_begin_;
1270}
1271
1272const uint8_t* OatFile::BssEnd() const {
1273 return bss_end_;
1274}
1275
David Brazdil7b49e6c2016-09-01 11:06:18 +01001276const uint8_t* OatFile::DexBegin() const {
1277 return kIsVdexEnabled ? vdex_->Begin() : Begin();
1278}
1279
1280const uint8_t* OatFile::DexEnd() const {
1281 return kIsVdexEnabled ? vdex_->End() : End();
1282}
1283
Vladimir Marko0eb882b2017-05-15 13:39:18 +01001284ArrayRef<ArtMethod*> OatFile::GetBssMethods() const {
1285 if (bss_methods_ != nullptr) {
1286 ArtMethod** methods = reinterpret_cast<ArtMethod**>(bss_methods_);
1287 ArtMethod** methods_end =
1288 reinterpret_cast<ArtMethod**>(bss_roots_ != nullptr ? bss_roots_ : bss_end_);
1289 return ArrayRef<ArtMethod*>(methods, methods_end - methods);
1290 } else {
1291 return ArrayRef<ArtMethod*>();
1292 }
1293}
1294
Vladimir Markoaad75c62016-10-03 08:46:48 +00001295ArrayRef<GcRoot<mirror::Object>> OatFile::GetBssGcRoots() const {
1296 if (bss_roots_ != nullptr) {
1297 auto* roots = reinterpret_cast<GcRoot<mirror::Object>*>(bss_roots_);
1298 auto* roots_end = reinterpret_cast<GcRoot<mirror::Object>*>(bss_end_);
1299 return ArrayRef<GcRoot<mirror::Object>>(roots, roots_end - roots);
1300 } else {
1301 return ArrayRef<GcRoot<mirror::Object>>();
1302 }
1303}
1304
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001305const OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
1306 const uint32_t* dex_location_checksum,
Richard Uhler9a37efc2016-08-05 16:32:55 -07001307 std::string* error_msg) const {
Vladimir Marko3f5838d2014-08-07 18:07:18 +01001308 // NOTE: We assume here that the canonical location for a given dex_location never
1309 // changes. If it does (i.e. some symlink used by the filename changes) we may return
1310 // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
1311 // an identical file or fail; otherwise we may see some unpredictable failures.
Calin Juravle4e1d5792014-07-15 23:56:47 +01001312
Vladimir Marko3f5838d2014-08-07 18:07:18 +01001313 // TODO: Additional analysis of usage patterns to see if this can be simplified
1314 // without any performance loss, for example by not doing the first lock-free lookup.
1315
1316 const OatFile::OatDexFile* oat_dex_file = nullptr;
1317 StringPiece key(dex_location);
1318 // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
1319 // directly mentioned in the oat file and doesn't require locking.
1320 auto primary_it = oat_dex_files_.find(key);
1321 if (primary_it != oat_dex_files_.end()) {
1322 oat_dex_file = primary_it->second;
1323 DCHECK(oat_dex_file != nullptr);
1324 } else {
1325 // This dex_location is not one of the dex locations directly mentioned in the
1326 // oat file. The correct lookup is via the canonical location but first see in
1327 // the secondary_oat_dex_files_ whether we've looked up this location before.
1328 MutexLock mu(Thread::Current(), secondary_lookup_lock_);
1329 auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
1330 if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001331 oat_dex_file = secondary_lb->second; // May be null.
Vladimir Marko3f5838d2014-08-07 18:07:18 +01001332 } else {
1333 // We haven't seen this dex_location before, we must check the canonical location.
Vladimir Marko3f5838d2014-08-07 18:07:18 +01001334 std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
Vladimir Markoaa4497d2014-09-05 14:01:17 +01001335 if (dex_canonical_location != dex_location) {
1336 StringPiece canonical_key(dex_canonical_location);
1337 auto canonical_it = oat_dex_files_.find(canonical_key);
1338 if (canonical_it != oat_dex_files_.end()) {
1339 oat_dex_file = canonical_it->second;
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001340 } // else keep null.
1341 } // else keep null.
Vladimir Marko3f5838d2014-08-07 18:07:18 +01001342
1343 // Copy the key to the string_cache_ and store the result in secondary map.
1344 string_cache_.emplace_back(key.data(), key.length());
1345 StringPiece key_copy(string_cache_.back());
1346 secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
Brian Carlstrom756ee4e2013-10-03 15:46:12 -07001347 }
1348 }
Richard Uhler9a37efc2016-08-05 16:32:55 -07001349
1350 if (oat_dex_file == nullptr) {
1351 if (error_msg != nullptr) {
1352 std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
1353 *error_msg = "Failed to find OatDexFile for DexFile " + std::string(dex_location)
1354 + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation();
1355 }
1356 return nullptr;
Vladimir Marko3f5838d2014-08-07 18:07:18 +01001357 }
Brian Carlstrom756ee4e2013-10-03 15:46:12 -07001358
Richard Uhler9a37efc2016-08-05 16:32:55 -07001359 if (dex_location_checksum != nullptr &&
1360 oat_dex_file->GetDexFileLocationChecksum() != *dex_location_checksum) {
1361 if (error_msg != nullptr) {
1362 std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
1363 std::string checksum = StringPrintf("0x%08x", oat_dex_file->GetDexFileLocationChecksum());
1364 std::string required_checksum = StringPrintf("0x%08x", *dex_location_checksum);
1365 *error_msg = "OatDexFile for DexFile " + std::string(dex_location)
1366 + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation()
1367 + " has checksum " + checksum + " but " + required_checksum + " was required";
Brian Carlstrom0d6adac2014-02-05 17:39:16 -08001368 }
Richard Uhler9a37efc2016-08-05 16:32:55 -07001369 return nullptr;
Brian Carlstrome24fa612011-09-29 00:53:55 -07001370 }
Richard Uhler9a37efc2016-08-05 16:32:55 -07001371 return oat_dex_file;
Brian Carlstromaded5f72011-10-07 17:15:04 -07001372}
1373
Brian Carlstrome24fa612011-09-29 00:53:55 -07001374OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
Elliott Hughesaa6a5882012-01-13 19:39:16 -08001375 const std::string& dex_file_location,
Vladimir Markoaa4497d2014-09-05 14:01:17 +01001376 const std::string& canonical_dex_file_location,
Brian Carlstrom5b332c82012-02-01 15:02:31 -08001377 uint32_t dex_file_location_checksum,
Ian Rogers13735952014-10-08 12:43:28 -07001378 const uint8_t* dex_file_pointer,
Artem Udovichenkod9786b02015-10-14 16:36:55 +03001379 const uint8_t* lookup_table_data,
Vladimir Marko0eb882b2017-05-15 13:39:18 +01001380 const MethodBssMapping* method_bss_mapping_data,
Vladimir Marko09d09432015-09-08 13:47:48 +01001381 const uint32_t* oat_class_offsets_pointer,
Mathieu Chartier120aa282017-08-05 16:03:03 -07001382 uint8_t* dex_cache_arrays,
1383 const DexLayoutSections* dex_layout_sections)
Brian Carlstrome24fa612011-09-29 00:53:55 -07001384 : oat_file_(oat_file),
1385 dex_file_location_(dex_file_location),
Vladimir Markoaa4497d2014-09-05 14:01:17 +01001386 canonical_dex_file_location_(canonical_dex_file_location),
Brian Carlstrom5b332c82012-02-01 15:02:31 -08001387 dex_file_location_checksum_(dex_file_location_checksum),
Brian Carlstrom89521892011-12-07 22:05:07 -08001388 dex_file_pointer_(dex_file_pointer),
Artem Udovichenkod9786b02015-10-14 16:36:55 +03001389 lookup_table_data_(lookup_table_data),
Vladimir Marko0eb882b2017-05-15 13:39:18 +01001390 method_bss_mapping_(method_bss_mapping_data),
Vladimir Marko09d09432015-09-08 13:47:48 +01001391 oat_class_offsets_pointer_(oat_class_offsets_pointer),
Mathieu Chartier120aa282017-08-05 16:03:03 -07001392 dex_cache_arrays_(dex_cache_arrays),
1393 dex_layout_sections_(dex_layout_sections) {
David Sehr9aa352e2016-09-15 18:13:52 -07001394 // Initialize TypeLookupTable.
1395 if (lookup_table_data_ != nullptr) {
1396 // Peek the number of classes from the DexFile.
1397 const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_);
1398 const uint32_t num_class_defs = dex_header->class_defs_size_;
1399 if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) > GetOatFile()->End()) {
1400 LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
1401 } else {
Mathieu Chartier1b868492016-11-16 16:22:37 -08001402 lookup_table_ = TypeLookupTable::Open(dex_file_pointer_, lookup_table_data_, num_class_defs);
David Sehr9aa352e2016-09-15 18:13:52 -07001403 }
1404 }
1405}
Brian Carlstrome24fa612011-09-29 00:53:55 -07001406
Mathieu Chartier1b868492016-11-16 16:22:37 -08001407OatFile::OatDexFile::OatDexFile(std::unique_ptr<TypeLookupTable>&& lookup_table)
1408 : lookup_table_(std::move(lookup_table)) {}
1409
Brian Carlstrome24fa612011-09-29 00:53:55 -07001410OatFile::OatDexFile::~OatDexFile() {}
1411
Ian Rogers05f28c62012-10-23 18:12:13 -07001412size_t OatFile::OatDexFile::FileSize() const {
1413 return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
1414}
1415
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001416std::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08001417 ScopedTrace trace(__PRETTY_FUNCTION__);
Aart Bik37d6a3b2016-06-21 18:30:10 -07001418 static constexpr bool kVerify = false;
1419 static constexpr bool kVerifyChecksum = false;
Andreas Gampe3a2bd292016-01-26 17:23:47 -08001420 return DexFile::Open(dex_file_pointer_,
1421 FileSize(),
1422 dex_file_location_,
1423 dex_file_location_checksum_,
1424 this,
Aart Bik37d6a3b2016-06-21 18:30:10 -07001425 kVerify,
1426 kVerifyChecksum,
Andreas Gampe3a2bd292016-01-26 17:23:47 -08001427 error_msg);
Brian Carlstrom89521892011-12-07 22:05:07 -08001428}
1429
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07001430uint32_t OatFile::OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
1431 return oat_class_offsets_pointer_[class_def_index];
1432}
1433
Vladimir Markod3c5beb2014-04-11 16:32:51 +01001434OatFile::OatClass OatFile::OatDexFile::GetOatClass(uint16_t class_def_index) const {
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07001435 uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001436
Ian Rogers13735952014-10-08 12:43:28 -07001437 const uint8_t* oat_class_pointer = oat_file_->Begin() + oat_class_offset;
Brian Carlstrom7571e8b2013-08-12 17:04:14 -07001438 CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation();
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001439
Ian Rogers13735952014-10-08 12:43:28 -07001440 const uint8_t* status_pointer = oat_class_pointer;
Brian Carlstromba150c32013-08-27 17:31:03 -07001441 CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation();
1442 mirror::Class::Status status =
1443 static_cast<mirror::Class::Status>(*reinterpret_cast<const int16_t*>(status_pointer));
1444 CHECK_LT(status, mirror::Class::kStatusMax);
1445
Ian Rogers13735952014-10-08 12:43:28 -07001446 const uint8_t* type_pointer = status_pointer + sizeof(uint16_t);
Brian Carlstromba150c32013-08-27 17:31:03 -07001447 CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation();
1448 OatClassType type = static_cast<OatClassType>(*reinterpret_cast<const uint16_t*>(type_pointer));
1449 CHECK_LT(type, kOatClassMax);
1450
Ian Rogers13735952014-10-08 12:43:28 -07001451 const uint8_t* after_type_pointer = type_pointer + sizeof(int16_t);
Brian Carlstromcd937a92014-03-04 22:53:23 -08001452 CHECK_LE(after_type_pointer, oat_file_->End()) << oat_file_->GetLocation();
Brian Carlstromba150c32013-08-27 17:31:03 -07001453
Brian Carlstromcd937a92014-03-04 22:53:23 -08001454 uint32_t bitmap_size = 0;
Ian Rogers13735952014-10-08 12:43:28 -07001455 const uint8_t* bitmap_pointer = nullptr;
1456 const uint8_t* methods_pointer = nullptr;
Ian Rogers97b52f82014-08-14 11:34:07 -07001457 if (type != kOatClassNoneCompiled) {
1458 if (type == kOatClassSomeCompiled) {
1459 bitmap_size = static_cast<uint32_t>(*reinterpret_cast<const uint32_t*>(after_type_pointer));
1460 bitmap_pointer = after_type_pointer + sizeof(bitmap_size);
1461 CHECK_LE(bitmap_pointer, oat_file_->End()) << oat_file_->GetLocation();
1462 methods_pointer = bitmap_pointer + bitmap_size;
1463 } else {
1464 methods_pointer = after_type_pointer;
1465 }
1466 CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation();
Brian Carlstromcd937a92014-03-04 22:53:23 -08001467 }
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001468
Richard Uhler07b3c232015-03-31 15:57:54 -07001469 return OatFile::OatClass(oat_file_,
1470 status,
1471 type,
1472 bitmap_size,
1473 reinterpret_cast<const uint32_t*>(bitmap_pointer),
1474 reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
Brian Carlstrome24fa612011-09-29 00:53:55 -07001475}
1476
David Sehr9aa352e2016-09-15 18:13:52 -07001477const DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_file,
1478 const char* descriptor,
1479 size_t hash) {
1480 const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
1481 DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash);
1482 if (LIKELY((oat_dex_file != nullptr) && (oat_dex_file->GetTypeLookupTable() != nullptr))) {
1483 const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable()->Lookup(descriptor, hash);
1484 return (class_def_idx != DexFile::kDexNoIndex) ? &dex_file.GetClassDef(class_def_idx) : nullptr;
1485 }
1486 // Fast path for rare no class defs case.
1487 const uint32_t num_class_defs = dex_file.NumClassDefs();
1488 if (num_class_defs == 0) {
1489 return nullptr;
1490 }
1491 const DexFile::TypeId* type_id = dex_file.FindTypeId(descriptor);
1492 if (type_id != nullptr) {
Andreas Gampea5b09a62016-11-17 15:21:22 -08001493 dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id);
David Sehr9aa352e2016-09-15 18:13:52 -07001494 return dex_file.FindClassDef(type_idx);
1495 }
1496 return nullptr;
1497}
1498
Mathieu Chartier120aa282017-08-05 16:03:03 -07001499// Madvise the dex file based on the state we are moving to.
1500void OatDexFile::MadviseDexFile(const DexFile& dex_file, MadviseState state) {
Mathieu Chartier150d25d2017-08-28 09:52:55 -07001501 const bool low_ram = Runtime::Current()->GetHeap()->IsLowMemoryMode();
1502 // TODO: Also do madvise hints for non low ram devices.
1503 if (!kMadviseDexFileAccesses || !low_ram) {
Mathieu Chartierbe8303d2017-08-17 17:39:39 -07001504 return;
1505 }
Mathieu Chartier120aa282017-08-05 16:03:03 -07001506 if (state == MadviseState::kMadviseStateAtLoad) {
Mathieu Chartier150d25d2017-08-28 09:52:55 -07001507 if (low_ram) {
Mathieu Chartier4ec507d2017-08-15 15:21:40 -07001508 // Default every dex file to MADV_RANDOM when its loaded by default for low ram devices.
1509 // Other devices have enough page cache to get performance benefits from loading more pages
1510 // into the page cache.
1511 MadviseLargestPageAlignedRegion(dex_file.Begin(),
1512 dex_file.Begin() + dex_file.Size(),
1513 MADV_RANDOM);
1514 }
Mathieu Chartier120aa282017-08-05 16:03:03 -07001515 }
1516 const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
1517 if (oat_dex_file != nullptr) {
1518 // Should always be there.
1519 const DexLayoutSections* const sections = oat_dex_file->GetDexLayoutSections();
1520 CHECK(sections != nullptr);
1521 sections->Madvise(&dex_file, state);
1522 }
1523}
1524
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001525OatFile::OatClass::OatClass(const OatFile* oat_file,
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001526 mirror::Class::Status status,
Brian Carlstromba150c32013-08-27 17:31:03 -07001527 OatClassType type,
1528 uint32_t bitmap_size,
1529 const uint32_t* bitmap_pointer,
Brian Carlstrom0755ec52012-01-11 15:19:46 -08001530 const OatMethodOffsets* methods_pointer)
Brian Carlstromba150c32013-08-27 17:31:03 -07001531 : oat_file_(oat_file), status_(status), type_(type),
Vladimir Markod3c5beb2014-04-11 16:32:51 +01001532 bitmap_(bitmap_pointer), methods_pointer_(methods_pointer) {
Brian Carlstromba150c32013-08-27 17:31:03 -07001533 switch (type_) {
1534 case kOatClassAllCompiled: {
1535 CHECK_EQ(0U, bitmap_size);
Brian Carlstromcd937a92014-03-04 22:53:23 -08001536 CHECK(bitmap_pointer == nullptr);
Ian Rogers97b52f82014-08-14 11:34:07 -07001537 CHECK(methods_pointer != nullptr);
Brian Carlstromba150c32013-08-27 17:31:03 -07001538 break;
1539 }
1540 case kOatClassSomeCompiled: {
1541 CHECK_NE(0U, bitmap_size);
Brian Carlstromcd937a92014-03-04 22:53:23 -08001542 CHECK(bitmap_pointer != nullptr);
Ian Rogers97b52f82014-08-14 11:34:07 -07001543 CHECK(methods_pointer != nullptr);
Brian Carlstromba150c32013-08-27 17:31:03 -07001544 break;
1545 }
1546 case kOatClassNoneCompiled: {
1547 CHECK_EQ(0U, bitmap_size);
Brian Carlstromcd937a92014-03-04 22:53:23 -08001548 CHECK(bitmap_pointer == nullptr);
Ian Rogers97b52f82014-08-14 11:34:07 -07001549 CHECK(methods_pointer_ == nullptr);
Brian Carlstromba150c32013-08-27 17:31:03 -07001550 break;
1551 }
1552 case kOatClassMax: {
1553 LOG(FATAL) << "Invalid OatClassType " << type_;
1554 break;
1555 }
1556 }
1557}
Brian Carlstrome24fa612011-09-29 00:53:55 -07001558
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07001559uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
1560 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
1561 if (oat_method_offsets == nullptr) {
1562 return 0u;
1563 }
1564 return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
1565}
1566
1567const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
Vladimir Markod3c5beb2014-04-11 16:32:51 +01001568 // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index.
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07001569 if (methods_pointer_ == nullptr) {
Brian Carlstromba150c32013-08-27 17:31:03 -07001570 CHECK_EQ(kOatClassNoneCompiled, type_);
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07001571 return nullptr;
Brian Carlstromba150c32013-08-27 17:31:03 -07001572 }
1573 size_t methods_pointer_index;
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07001574 if (bitmap_ == nullptr) {
Brian Carlstromba150c32013-08-27 17:31:03 -07001575 CHECK_EQ(kOatClassAllCompiled, type_);
1576 methods_pointer_index = method_index;
1577 } else {
1578 CHECK_EQ(kOatClassSomeCompiled, type_);
Vladimir Markod3c5beb2014-04-11 16:32:51 +01001579 if (!BitVector::IsBitSet(bitmap_, method_index)) {
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07001580 return nullptr;
Brian Carlstromba150c32013-08-27 17:31:03 -07001581 }
Vladimir Markod3c5beb2014-04-11 16:32:51 +01001582 size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
1583 methods_pointer_index = num_set_bits;
Brian Carlstromba150c32013-08-27 17:31:03 -07001584 }
1585 const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07001586 return &oat_method_offsets;
1587}
1588
1589const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
1590 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
1591 if (oat_method_offsets == nullptr) {
Mathieu Chartier957ca1c2014-11-21 16:51:29 -08001592 return OatMethod(nullptr, 0);
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07001593 }
1594 if (oat_file_->IsExecutable() ||
1595 Runtime::Current() == nullptr || // This case applies for oatdump.
Mathieu Chartiere5f13e52015-02-24 09:37:21 -08001596 Runtime::Current()->IsAotCompiler()) {
Mathieu Chartier957ca1c2014-11-21 16:51:29 -08001597 return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
Alex Light9dcc4572014-08-14 14:16:26 -07001598 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -08001599 // We aren't allowed to use the compiled code. We just force it down the interpreted / jit
1600 // version.
1601 return OatMethod(oat_file_->Begin(), 0);
Brian Carlstrom3320cf42011-10-04 14:58:28 -07001602}
1603
Mathieu Chartiere401d142015-04-22 13:56:20 -07001604void OatFile::OatMethod::LinkMethod(ArtMethod* method) const {
Andreas Gampefa8429b2015-04-07 18:34:42 -07001605 CHECK(method != nullptr);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001606 method->SetEntryPointFromQuickCompiledCode(GetQuickCode());
Brian Carlstromae826982011-11-09 01:33:42 -08001607}
1608
Andreas Gampe7ba64962014-10-23 11:37:40 -07001609bool OatFile::IsPic() const {
Igor Murashkin46774762014-10-22 11:37:02 -07001610 return GetOatHeader().IsPic();
Andreas Gampe7ba64962014-10-23 11:37:40 -07001611 // TODO: Check against oat_patches. b/18144996
1612}
1613
Sebastien Hertz0de11332015-05-13 12:14:05 +02001614bool OatFile::IsDebuggable() const {
1615 return GetOatHeader().IsDebuggable();
1616}
1617
Andreas Gampe29d38e72016-03-23 15:31:51 +00001618CompilerFilter::Filter OatFile::GetCompilerFilter() const {
1619 return GetOatHeader().GetCompilerFilter();
Calin Juravleb077e152016-02-18 18:47:37 +00001620}
1621
Vladimir Marko97d7e1c2016-10-04 14:44:28 +01001622OatFile::OatClass OatFile::FindOatClass(const DexFile& dex_file,
1623 uint16_t class_def_idx,
1624 bool* found) {
1625 DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
1626 const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
Mathieu Chartier1b868492016-11-16 16:22:37 -08001627 if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
Vladimir Marko97d7e1c2016-10-04 14:44:28 +01001628 *found = false;
1629 return OatFile::OatClass::Invalid();
1630 }
1631 *found = true;
1632 return oat_dex_file->GetOatClass(class_def_idx);
1633}
1634
Mathieu Chartier1b868492016-11-16 16:22:37 -08001635void OatFile::OatDexFile::AssertAotCompiler() {
1636 CHECK(Runtime::Current()->IsAotCompiler());
1637}
1638
Brian Carlstrome24fa612011-09-29 00:53:55 -07001639} // namespace art