1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "oat_file.h"
18
19 #include <dlfcn.h>
20 #ifndef __APPLE__
21 #include <link.h> // for dl_iterate_phdr.
22 #endif
23 #include <unistd.h>
24
25 #include <cstdlib>
26 #include <cstring>
27 #include <sstream>
28 #include <type_traits>
29 #include <sys/stat.h>
30
31 // dlopen_ext support from bionic.
32 #ifdef ART_TARGET_ANDROID
33 #include "android/dlext.h"
34 #include "nativeloader/dlext_namespaces.h"
35 #endif
36
37 #include <android-base/logging.h>
38 #include "android-base/stringprintf.h"
39
40 #include "arch/instruction_set_features.h"
41 #include "art_method.h"
42 #include "base/bit_vector.h"
43 #include "base/enums.h"
44 #include "base/file_utils.h"
45 #include "base/logging.h" // For VLOG_IS_ON.
46 #include "base/mem_map.h"
47 #include "base/os.h"
48 #include "base/stl_util.h"
49 #include "base/string_view_cpp20.h"
50 #include "base/systrace.h"
51 #include "base/unix_file/fd_file.h"
52 #include "base/utils.h"
53 #include "dex/art_dex_file_loader.h"
54 #include "dex/dex_file.h"
55 #include "dex/dex_file_loader.h"
56 #include "dex/dex_file_structs.h"
57 #include "dex/dex_file_types.h"
58 #include "dex/standard_dex_file.h"
59 #include "dex/type_lookup_table.h"
60 #include "dex/utf-inl.h"
61 #include "elf/elf_utils.h"
62 #include "elf_file.h"
63 #include "gc_root.h"
64 #include "gc/heap.h"
65 #include "gc/space/image_space.h"
66 #include "mirror/class.h"
67 #include "mirror/object-inl.h"
68 #include "oat.h"
69 #include "oat_file-inl.h"
70 #include "oat_file_manager.h"
71 #include "runtime-inl.h"
72 #include "vdex_file.h"
73 #include "verifier/verifier_deps.h"
74
75 namespace art {
76
77 using android::base::StringPrintf;
78
79 // Whether OatFile::Open will try dlopen. Fallback is our own ELF loader.
80 static constexpr bool kUseDlopen = true;
81
82 // Whether OatFile::Open will try dlopen on the host. On the host we're not linking against
83 // bionic, so cannot take advantage of the support for changed semantics (loading the same soname
84 // multiple times). However, if/when we switch the above, we likely want to switch this, too,
85 // to get test coverage of the code paths.
86 static constexpr bool kUseDlopenOnHost = true;
87
88 // For debugging, Open will print DlOpen error message if set to true.
89 static constexpr bool kPrintDlOpenErrorMessage = false;
90
91 // Note for OatFileBase and descendents:
92 //
93 // These are used in OatFile::Open to try all our loaders.
94 //
95 // The process is simple:
96 //
97 // 1) Allocate an instance through the standard constructor (location, executable)
98 // 2) Load() to try to open the file.
99 // 3) ComputeFields() to populate the OatFile fields like begin_, using FindDynamicSymbolAddress.
100 // 4) PreSetup() for any steps that should be done before the final setup.
101 // 5) Setup() to complete the procedure.
102
103 class OatFileBase : public OatFile {
104 public:
~OatFileBase()105 virtual ~OatFileBase() {}
106
107 template <typename kOatFileBaseSubType>
108 static OatFileBase* OpenOatFile(int zip_fd,
109 const std::string& vdex_filename,
110 const std::string& elf_filename,
111 const std::string& location,
112 bool writable,
113 bool executable,
114 bool low_4gb,
115 ArrayRef<const std::string> dex_filenames,
116 /*inout*/MemMap* reservation, // Where to load if not null.
117 /*out*/std::string* error_msg);
118
119 template <typename kOatFileBaseSubType>
120 static OatFileBase* OpenOatFile(int zip_fd,
121 int vdex_fd,
122 int oat_fd,
123 const std::string& vdex_filename,
124 const std::string& oat_filename,
125 bool writable,
126 bool executable,
127 bool low_4gb,
128 ArrayRef<const std::string> dex_filenames,
129 /*inout*/MemMap* reservation, // Where to load if not null.
130 /*out*/std::string* error_msg);
131
132 protected:
OatFileBase(const std::string & filename,bool executable)133 OatFileBase(const std::string& filename, bool executable) : OatFile(filename, executable) {}
134
135 virtual const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
136 std::string* error_msg) const = 0;
137
138 virtual void PreLoad() = 0;
139
140 bool LoadVdex(const std::string& vdex_filename,
141 bool writable,
142 bool low_4gb,
143 std::string* error_msg);
144
145 bool LoadVdex(int vdex_fd,
146 const std::string& vdex_filename,
147 bool writable,
148 bool low_4gb,
149 std::string* error_msg);
150
151 virtual bool Load(const std::string& elf_filename,
152 bool writable,
153 bool executable,
154 bool low_4gb,
155 /*inout*/MemMap* reservation, // Where to load if not null.
156 /*out*/std::string* error_msg) = 0;
157
158 virtual bool Load(int oat_fd,
159 bool writable,
160 bool executable,
161 bool low_4gb,
162 /*inout*/MemMap* reservation, // Where to load if not null.
163 /*out*/std::string* error_msg) = 0;
164
165 bool ComputeFields(const std::string& file_path, std::string* error_msg);
166
167 virtual void PreSetup(const std::string& elf_filename) = 0;
168
169 bool Setup(int zip_fd, ArrayRef<const std::string> dex_filenames, std::string* error_msg);
170
171 void Setup(const std::vector<const DexFile*>& dex_files);
172
173 // Setters exposed for ElfOatFile.
174
SetBegin(const uint8_t * begin)175 void SetBegin(const uint8_t* begin) {
176 begin_ = begin;
177 }
178
SetEnd(const uint8_t * end)179 void SetEnd(const uint8_t* end) {
180 end_ = end;
181 }
182
SetVdex(VdexFile * vdex)183 void SetVdex(VdexFile* vdex) {
184 vdex_.reset(vdex);
185 }
186
187 private:
188 // Returns true if we want to remove quickened opcodes before loading the VDEX file, false
189 // otherwise.
190 bool ShouldUnquickenVDex() const;
191
192 DISALLOW_COPY_AND_ASSIGN(OatFileBase);
193 };
194
195 template <typename kOatFileBaseSubType>
OpenOatFile(int zip_fd,const std::string & vdex_filename,const std::string & elf_filename,const std::string & location,bool writable,bool executable,bool low_4gb,ArrayRef<const std::string> dex_filenames,MemMap * reservation,std::string * error_msg)196 OatFileBase* OatFileBase::OpenOatFile(int zip_fd,
197 const std::string& vdex_filename,
198 const std::string& elf_filename,
199 const std::string& location,
200 bool writable,
201 bool executable,
202 bool low_4gb,
203 ArrayRef<const std::string> dex_filenames,
204 /*inout*/MemMap* reservation,
205 /*out*/std::string* error_msg) {
206 std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable));
207
208 ret->PreLoad();
209
210 if (!ret->Load(elf_filename,
211 writable,
212 executable,
213 low_4gb,
214 reservation,
215 error_msg)) {
216 return nullptr;
217 }
218
219 if (!ret->ComputeFields(elf_filename, error_msg)) {
220 return nullptr;
221 }
222
223 ret->PreSetup(elf_filename);
224
225 if (!ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) {
226 return nullptr;
227 }
228
229 if (!ret->Setup(zip_fd, dex_filenames, error_msg)) {
230 return nullptr;
231 }
232
233 return ret.release();
234 }
235
236 template <typename kOatFileBaseSubType>
OpenOatFile(int zip_fd,int vdex_fd,int oat_fd,const std::string & vdex_location,const std::string & oat_location,bool writable,bool executable,bool low_4gb,ArrayRef<const std::string> dex_filenames,MemMap * reservation,std::string * error_msg)237 OatFileBase* OatFileBase::OpenOatFile(int zip_fd,
238 int vdex_fd,
239 int oat_fd,
240 const std::string& vdex_location,
241 const std::string& oat_location,
242 bool writable,
243 bool executable,
244 bool low_4gb,
245 ArrayRef<const std::string> dex_filenames,
246 /*inout*/MemMap* reservation,
247 /*out*/std::string* error_msg) {
248 std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(oat_location, executable));
249
250 if (!ret->Load(oat_fd,
251 writable,
252 executable,
253 low_4gb,
254 reservation,
255 error_msg)) {
256 return nullptr;
257 }
258
259 if (!ret->ComputeFields(oat_location, error_msg)) {
260 return nullptr;
261 }
262
263 ret->PreSetup(oat_location);
264
265 if (!ret->LoadVdex(vdex_fd, vdex_location, writable, low_4gb, error_msg)) {
266 return nullptr;
267 }
268
269 if (!ret->Setup(zip_fd, dex_filenames, error_msg)) {
270 return nullptr;
271 }
272
273 return ret.release();
274 }
275
ShouldUnquickenVDex() const276 bool OatFileBase::ShouldUnquickenVDex() const {
277 // We sometimes load oat files without a runtime (eg oatdump) and don't want to do anything in
278 // that case. If we are debuggable there are no -quick opcodes to unquicken. If the runtime is not
279 // debuggable we don't care whether there are -quick opcodes or not so no need to do anything.
280 Runtime* runtime = Runtime::Current();
281 return (runtime != nullptr && runtime->IsJavaDebuggable()) &&
282 // Note: This is called before `OatFileBase::Setup()` where we validate the
283 // oat file contents. Check that we have at least a valid header, including
284 // oat file version, to avoid parsing the key-value store for a different
285 // version (out-of-date oat file) which can lead to crashes. b/179221298.
286 // TODO: While this is a poor workaround and the correct solution would be
287 // to postpone the unquickening check until after `OatFileBase::Setup()`,
288 // we prefer to avoid larger rewrites because quickening is deprecated and
289 // should be removed completely anyway. b/170086509
290 (GetOatHeader().IsValid() && !IsDebuggable());
291 }
292
LoadVdex(const std::string & vdex_filename,bool writable,bool low_4gb,std::string * error_msg)293 bool OatFileBase::LoadVdex(const std::string& vdex_filename,
294 bool writable,
295 bool low_4gb,
296 std::string* error_msg) {
297 vdex_ = VdexFile::OpenAtAddress(vdex_begin_,
298 vdex_end_ - vdex_begin_,
299 /*mmap_reuse=*/ vdex_begin_ != nullptr,
300 vdex_filename,
301 writable,
302 low_4gb,
303 ShouldUnquickenVDex(),
304 error_msg);
305 if (vdex_.get() == nullptr) {
306 *error_msg = StringPrintf("Failed to load vdex file '%s' %s",
307 vdex_filename.c_str(),
308 error_msg->c_str());
309 return false;
310 }
311 return true;
312 }
313
LoadVdex(int vdex_fd,const std::string & vdex_filename,bool writable,bool low_4gb,std::string * error_msg)314 bool OatFileBase::LoadVdex(int vdex_fd,
315 const std::string& vdex_filename,
316 bool writable,
317 bool low_4gb,
318 std::string* error_msg) {
319 if (vdex_fd != -1) {
320 struct stat s;
321 int rc = TEMP_FAILURE_RETRY(fstat(vdex_fd, &s));
322 if (rc == -1) {
323 PLOG(WARNING) << "Failed getting length of vdex file";
324 } else {
325 vdex_ = VdexFile::OpenAtAddress(
326 vdex_begin_,
327 vdex_end_ - vdex_begin_,
328 /*mmap_reuse=*/ vdex_begin_ != nullptr,
329 vdex_fd,
330 s.st_size,
331 vdex_filename,
332 writable,
333 low_4gb,
334 ShouldUnquickenVDex(),
335 error_msg);
336 if (vdex_.get() == nullptr) {
337 *error_msg = "Failed opening vdex file.";
338 return false;
339 }
340 }
341 }
342 return true;
343 }
344
ComputeFields(const std::string & file_path,std::string * error_msg)345 bool OatFileBase::ComputeFields(const std::string& file_path, std::string* error_msg) {
346 std::string symbol_error_msg;
347 begin_ = FindDynamicSymbolAddress("oatdata", &symbol_error_msg);
348 if (begin_ == nullptr) {
349 *error_msg = StringPrintf("Failed to find oatdata symbol in '%s' %s",
350 file_path.c_str(),
351 symbol_error_msg.c_str());
352 return false;
353 }
354 end_ = FindDynamicSymbolAddress("oatlastword", &symbol_error_msg);
355 if (end_ == nullptr) {
356 *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s' %s",
357 file_path.c_str(),
358 symbol_error_msg.c_str());
359 return false;
360 }
361 // Readjust to be non-inclusive upper bound.
362 end_ += sizeof(uint32_t);
363
364 data_bimg_rel_ro_begin_ = FindDynamicSymbolAddress("oatdatabimgrelro", &symbol_error_msg);
365 if (data_bimg_rel_ro_begin_ != nullptr) {
366 data_bimg_rel_ro_end_ =
367 FindDynamicSymbolAddress("oatdatabimgrelrolastword", &symbol_error_msg);
368 if (data_bimg_rel_ro_end_ == nullptr) {
369 *error_msg =
370 StringPrintf("Failed to find oatdatabimgrelrolastword symbol in '%s'", file_path.c_str());
371 return false;
372 }
373 // Readjust to be non-inclusive upper bound.
374 data_bimg_rel_ro_end_ += sizeof(uint32_t);
375 }
376
377 bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg));
378 if (bss_begin_ == nullptr) {
379 // No .bss section.
380 bss_end_ = nullptr;
381 } else {
382 bss_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbsslastword", &symbol_error_msg));
383 if (bss_end_ == nullptr) {
384 *error_msg = StringPrintf("Failed to find oatbsslastword symbol in '%s'", file_path.c_str());
385 return false;
386 }
387 // Readjust to be non-inclusive upper bound.
388 bss_end_ += sizeof(uint32_t);
389 // Find bss methods if present.
390 bss_methods_ =
391 const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssmethods", &symbol_error_msg));
392 // Find bss roots if present.
393 bss_roots_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssroots", &symbol_error_msg));
394 }
395
396 vdex_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatdex", &symbol_error_msg));
397 if (vdex_begin_ == nullptr) {
398 // No .vdex section.
399 vdex_end_ = nullptr;
400 } else {
401 vdex_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatdexlastword", &symbol_error_msg));
402 if (vdex_end_ == nullptr) {
403 *error_msg = StringPrintf("Failed to find oatdexlastword symbol in '%s'", file_path.c_str());
404 return false;
405 }
406 // Readjust to be non-inclusive upper bound.
407 vdex_end_ += sizeof(uint32_t);
408 }
409
410 return true;
411 }
412
413 // Read an unaligned entry from the OatDexFile data in OatFile and advance the read
414 // position by the number of bytes read, i.e. sizeof(T).
415 // Return true on success, false if the read would go beyond the end of the OatFile.
416 template <typename T>
ReadOatDexFileData(const OatFile & oat_file,const uint8_t ** oat,T * value)417 inline static bool ReadOatDexFileData(const OatFile& oat_file,
418 /*inout*/const uint8_t** oat,
419 /*out*/T* value) {
420 DCHECK(oat != nullptr);
421 DCHECK(value != nullptr);
422 DCHECK_LE(*oat, oat_file.End());
423 if (UNLIKELY(static_cast<size_t>(oat_file.End() - *oat) < sizeof(T))) {
424 return false;
425 }
426 static_assert(std::is_trivial<T>::value, "T must be a trivial type");
427 using unaligned_type __attribute__((__aligned__(1))) = T;
428 *value = *reinterpret_cast<const unaligned_type*>(*oat);
429 *oat += sizeof(T);
430 return true;
431 }
432
ReadIndexBssMapping(OatFile * oat_file,const uint8_t ** oat,size_t dex_file_index,const std::string & dex_file_location,const char * tag,const IndexBssMapping ** mapping,std::string * error_msg)433 static bool ReadIndexBssMapping(OatFile* oat_file,
434 /*inout*/const uint8_t** oat,
435 size_t dex_file_index,
436 const std::string& dex_file_location,
437 const char* tag,
438 /*out*/const IndexBssMapping** mapping,
439 std::string* error_msg) {
440 uint32_t index_bss_mapping_offset;
441 if (UNLIKELY(!ReadOatDexFileData(*oat_file, oat, &index_bss_mapping_offset))) {
442 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
443 "after %s bss mapping offset",
444 oat_file->GetLocation().c_str(),
445 dex_file_index,
446 dex_file_location.c_str(),
447 tag);
448 return false;
449 }
450 const bool readable_index_bss_mapping_size =
451 index_bss_mapping_offset != 0u &&
452 index_bss_mapping_offset <= oat_file->Size() &&
453 IsAligned<alignof(IndexBssMapping)>(index_bss_mapping_offset) &&
454 oat_file->Size() - index_bss_mapping_offset >= IndexBssMapping::ComputeSize(0);
455 const IndexBssMapping* index_bss_mapping = readable_index_bss_mapping_size
456 ? reinterpret_cast<const IndexBssMapping*>(oat_file->Begin() + index_bss_mapping_offset)
457 : nullptr;
458 if (index_bss_mapping_offset != 0u &&
459 (UNLIKELY(index_bss_mapping == nullptr) ||
460 UNLIKELY(index_bss_mapping->size() == 0u) ||
461 UNLIKELY(oat_file->Size() - index_bss_mapping_offset <
462 IndexBssMapping::ComputeSize(index_bss_mapping->size())))) {
463 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned or "
464 " truncated %s bss mapping, offset %u of %zu, length %zu",
465 oat_file->GetLocation().c_str(),
466 dex_file_index,
467 dex_file_location.c_str(),
468 tag,
469 index_bss_mapping_offset,
470 oat_file->Size(),
471 index_bss_mapping != nullptr ? index_bss_mapping->size() : 0u);
472 return false;
473 }
474
475 *mapping = index_bss_mapping;
476 return true;
477 }
478
Setup(const std::vector<const DexFile * > & dex_files)479 void OatFileBase::Setup(const std::vector<const DexFile*>& dex_files) {
480 uint32_t i = 0;
481 const uint8_t* type_lookup_table_start = nullptr;
482 for (const DexFile* dex_file : dex_files) {
483 type_lookup_table_start = vdex_->GetNextTypeLookupTableData(type_lookup_table_start, i++);
484 std::string dex_location = dex_file->GetLocation();
485 std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location.c_str());
486
487 const uint8_t* type_lookup_table_data = nullptr;
488 if (type_lookup_table_start != nullptr &&
489 (reinterpret_cast<uint32_t*>(type_lookup_table_start[0]) != 0)) {
490 type_lookup_table_data = type_lookup_table_start + sizeof(uint32_t);
491 }
492 // Create an OatDexFile and add it to the owning container.
493 OatDexFile* oat_dex_file = new OatDexFile(
494 this,
495 dex_file->Begin(),
496 dex_file->GetLocationChecksum(),
497 dex_location,
498 canonical_location,
499 type_lookup_table_data);
500 dex_file->SetOatDexFile(oat_dex_file);
501 oat_dex_files_storage_.push_back(oat_dex_file);
502
503 // Add the location and canonical location (if different) to the oat_dex_files_ table.
504 std::string_view key(oat_dex_file->GetDexFileLocation());
505 oat_dex_files_.Put(key, oat_dex_file);
506 if (canonical_location != dex_location) {
507 std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
508 oat_dex_files_.Put(canonical_key, oat_dex_file);
509 }
510 }
511 }
512
Setup(int zip_fd,ArrayRef<const std::string> dex_filenames,std::string * error_msg)513 bool OatFileBase::Setup(int zip_fd,
514 ArrayRef<const std::string> dex_filenames,
515 std::string* error_msg) {
516 if (!GetOatHeader().IsValid()) {
517 std::string cause = GetOatHeader().GetValidationErrorMessage();
518 *error_msg = StringPrintf("Invalid oat header for '%s': %s",
519 GetLocation().c_str(),
520 cause.c_str());
521 return false;
522 }
523 PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
524 size_t key_value_store_size =
525 (Size() >= sizeof(OatHeader)) ? GetOatHeader().GetKeyValueStoreSize() : 0u;
526 if (Size() < sizeof(OatHeader) + key_value_store_size) {
527 *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader, "
528 "size = %zu < %zu + %zu",
529 GetLocation().c_str(),
530 Size(),
531 sizeof(OatHeader),
532 key_value_store_size);
533 return false;
534 }
535
536 size_t oat_dex_files_offset = GetOatHeader().GetOatDexFilesOffset();
537 if (oat_dex_files_offset < GetOatHeader().GetHeaderSize() || oat_dex_files_offset > Size()) {
538 *error_msg = StringPrintf("In oat file '%s' found invalid oat dex files offset: "
539 "%zu is not in [%zu, %zu]",
540 GetLocation().c_str(),
541 oat_dex_files_offset,
542 GetOatHeader().GetHeaderSize(),
543 Size());
544 return false;
545 }
546 const uint8_t* oat = Begin() + oat_dex_files_offset; // Jump to the OatDexFile records.
547
548 if (!IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_begin_) ||
549 !IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_end_) ||
550 data_bimg_rel_ro_begin_ > data_bimg_rel_ro_end_) {
551 *error_msg = StringPrintf("In oat file '%s' found unaligned or unordered databimgrelro "
552 "symbol(s): begin = %p, end = %p",
553 GetLocation().c_str(),
554 data_bimg_rel_ro_begin_,
555 data_bimg_rel_ro_end_);
556 return false;
557 }
558
559 DCHECK_GE(static_cast<size_t>(pointer_size), alignof(GcRoot<mirror::Object>));
560 if (!IsAligned<kPageSize>(bss_begin_) ||
561 !IsAlignedParam(bss_methods_, static_cast<size_t>(pointer_size)) ||
562 !IsAlignedParam(bss_roots_, static_cast<size_t>(pointer_size)) ||
563 !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_end_)) {
564 *error_msg = StringPrintf("In oat file '%s' found unaligned bss symbol(s): "
565 "begin = %p, methods_ = %p, roots = %p, end = %p",
566 GetLocation().c_str(),
567 bss_begin_,
568 bss_methods_,
569 bss_roots_,
570 bss_end_);
571 return false;
572 }
573
574 if ((bss_methods_ != nullptr && (bss_methods_ < bss_begin_ || bss_methods_ > bss_end_)) ||
575 (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) ||
576 (bss_methods_ != nullptr && bss_roots_ != nullptr && bss_methods_ > bss_roots_)) {
577 *error_msg = StringPrintf("In oat file '%s' found bss symbol(s) outside .bss or unordered: "
578 "begin = %p, methods = %p, roots = %p, end = %p",
579 GetLocation().c_str(),
580 bss_begin_,
581 bss_methods_,
582 bss_roots_,
583 bss_end_);
584 return false;
585 }
586
587 if (bss_methods_ != nullptr && bss_methods_ != bss_begin_) {
588 *error_msg = StringPrintf("In oat file '%s' found unexpected .bss gap before 'oatbssmethods': "
589 "begin = %p, methods = %p",
590 GetLocation().c_str(),
591 bss_begin_,
592 bss_methods_);
593 return false;
594 }
595
596 std::string_view primary_location;
597 std::string_view primary_location_replacement;
598 size_t dex_filenames_pos = 0u;
599 uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
600 oat_dex_files_storage_.reserve(dex_file_count);
601 for (size_t i = 0; i < dex_file_count; i++) {
602 uint32_t dex_file_location_size;
603 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
604 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file "
605 "location size",
606 GetLocation().c_str(),
607 i);
608 return false;
609 }
610 if (UNLIKELY(dex_file_location_size == 0U)) {
611 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name",
612 GetLocation().c_str(),
613 i);
614 return false;
615 }
616 if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) {
617 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file "
618 "location",
619 GetLocation().c_str(),
620 i);
621 return false;
622 }
623 const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
624 oat += dex_file_location_size;
625
626 // Location encoded in the oat file. We will use this for multidex naming.
627 std::string_view oat_dex_file_location(dex_file_location_data, dex_file_location_size);
628 std::string dex_file_location(oat_dex_file_location);
629 bool is_multidex = DexFileLoader::IsMultiDexLocation(dex_file_location.c_str());
630 // Check that `is_multidex` does not clash with other indicators. The first dex location
631 // must be primary location and, if we're opening external dex files, the location must
632 // be multi-dex if and only if we already have a dex file opened for it.
633 if ((i == 0 && is_multidex) ||
634 (!external_dex_files_.empty() && (is_multidex != (i < external_dex_files_.size())))) {
635 *error_msg = StringPrintf("In oat file '%s' found unexpected %s location '%s'",
636 GetLocation().c_str(),
637 is_multidex ? "multi-dex" : "primary",
638 dex_file_location.c_str());
639 return false;
640 }
641 // Remember the primary location and, if provided, the replacement from `dex_filenames`.
642 if (!is_multidex) {
643 primary_location = oat_dex_file_location;
644 if (!dex_filenames.empty()) {
645 if (dex_filenames_pos == dex_filenames.size()) {
646 *error_msg = StringPrintf("In oat file '%s' found excessive primary location '%s'"
647 ", expected only %zu primary locations",
648 GetLocation().c_str(),
649 dex_file_location.c_str(),
650 dex_filenames.size());
651 return false;
652 }
653 primary_location_replacement = dex_filenames[dex_filenames_pos];
654 ++dex_filenames_pos;
655 }
656 }
657 // Check that the base location of a multidex location matches the last seen primary location.
658 if (is_multidex &&
659 (!StartsWith(dex_file_location, primary_location) ||
660 dex_file_location[primary_location.size()] != DexFileLoader::kMultiDexSeparator)) {
661 *error_msg = StringPrintf("In oat file '%s' found unexpected multidex location '%s',"
662 " unrelated to '%s'",
663 GetLocation().c_str(),
664 dex_file_location.c_str(),
665 std::string(primary_location).c_str());
666 return false;
667 }
668 std::string dex_file_name = dex_file_location;
669 if (!dex_filenames.empty()) {
670 dex_file_name.replace(/*pos*/ 0u, primary_location.size(), primary_location_replacement);
671 // If the location does not contain path and matches the file name component,
672 // use the provided file name also as the location.
673 // TODO: Do we need this for anything other than tests?
674 if (dex_file_location.find('/') == std::string::npos &&
675 dex_file_name.size() > dex_file_location.size() &&
676 dex_file_name[dex_file_name.size() - dex_file_location.size() - 1u] == '/' &&
677 EndsWith(dex_file_name, dex_file_location)) {
678 dex_file_location = dex_file_name;
679 }
680 }
681
682 uint32_t dex_file_checksum;
683 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
684 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after "
685 "dex file checksum",
686 GetLocation().c_str(),
687 i,
688 dex_file_location.c_str());
689 return false;
690 }
691
692 uint32_t dex_file_offset;
693 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
694 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
695 "after dex file offsets",
696 GetLocation().c_str(),
697 i,
698 dex_file_location.c_str());
699 return false;
700 }
701 if (UNLIKELY(dex_file_offset > DexSize())) {
702 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
703 "offset %u > %zu",
704 GetLocation().c_str(),
705 i,
706 dex_file_location.c_str(),
707 dex_file_offset,
708 DexSize());
709 return false;
710 }
711 const uint8_t* dex_file_pointer = nullptr;
712 if (UNLIKELY(dex_file_offset == 0U)) {
713 // Do not support mixed-mode oat files.
714 if (i != 0u && external_dex_files_.empty()) {
715 *error_msg = StringPrintf("In oat file '%s', unsupported uncompressed-dex-file for dex "
716 "file %zu (%s)",
717 GetLocation().c_str(),
718 i,
719 dex_file_location.c_str());
720 return false;
721 }
722 DCHECK_LE(i, external_dex_files_.size());
723 if (i == external_dex_files_.size()) {
724 std::vector<std::unique_ptr<const DexFile>> new_dex_files;
725 // No dex files, load it from location.
726 const ArtDexFileLoader dex_file_loader;
727 bool loaded = false;
728 if (zip_fd != -1) {
729 loaded = dex_file_loader.OpenZip(zip_fd,
730 dex_file_location,
731 /*verify=*/ false,
732 /*verify_checksum=*/ false,
733 error_msg,
734 &new_dex_files);
735 } else {
736 loaded = dex_file_loader.Open(dex_file_name.c_str(),
737 dex_file_location,
738 /*verify=*/ false,
739 /*verify_checksum=*/ false,
740 error_msg,
741 &new_dex_files);
742 }
743 if (!loaded) {
744 if (Runtime::Current() == nullptr) {
745 // If there's no runtime, we're running oatdump, so return
746 // a half constructed oat file that oatdump knows how to deal with.
747 LOG(WARNING) << "Could not find associated dex files of oat file. "
748 << "Oatdump will only dump the header.";
749 return true;
750 } else {
751 return false;
752 }
753 }
754 // The oat file may be out of date wrt/ the dex-file location. We need to be defensive
755 // here and ensure that at least the number of dex files still matches.
756 // If we have a zip_fd, or reached the end of provided `dex_filenames`, we must
757 // load all dex files from that file, otherwise we may open multiple files.
758 // Note: actual checksum comparisons are the duty of the OatFileAssistant and will be
759 // done after loading the OatFile.
760 size_t max_dex_files = dex_file_count - external_dex_files_.size();
761 bool expect_all =
762 (zip_fd != -1) || (!dex_filenames.empty() && dex_filenames_pos == dex_filenames.size());
763 if (expect_all ? new_dex_files.size() != max_dex_files
764 : new_dex_files.size() > max_dex_files) {
765 *error_msg = StringPrintf("In oat file '%s', expected %s%zu uncompressed dex files, but "
766 "found %zu in '%s'",
767 GetLocation().c_str(),
768 (expect_all ? "" : "<="),
769 max_dex_files,
770 new_dex_files.size(),
771 dex_file_location.c_str());
772 return false;
773 }
774 for (std::unique_ptr<const DexFile>& dex_file : new_dex_files) {
775 external_dex_files_.push_back(std::move(dex_file));
776 }
777 }
778 dex_file_pointer = external_dex_files_[i]->Begin();
779 } else {
780 // Do not support mixed-mode oat files.
781 if (!external_dex_files_.empty()) {
782 *error_msg = StringPrintf("In oat file '%s', unsupported embedded dex-file for dex file "
783 "%zu (%s)",
784 GetLocation().c_str(),
785 i,
786 dex_file_location.c_str());
787 return false;
788 }
789 if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
790 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
791 "offset %u of %zu but the size of dex file header is %zu",
792 GetLocation().c_str(),
793 i,
794 dex_file_location.c_str(),
795 dex_file_offset,
796 DexSize(),
797 sizeof(DexFile::Header));
798 return false;
799 }
800 dex_file_pointer = DexBegin() + dex_file_offset;
801 }
802
803 const bool valid_magic = DexFileLoader::IsMagicValid(dex_file_pointer);
804 if (UNLIKELY(!valid_magic)) {
805 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
806 "dex file magic",
807 GetLocation().c_str(),
808 i,
809 dex_file_location.c_str());
810 return false;
811 }
812 if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_pointer))) {
813 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
814 "dex file version",
815 GetLocation().c_str(),
816 i,
817 dex_file_location.c_str());
818 return false;
819 }
820 const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
821 if (dex_file_offset != 0 && (DexSize() - dex_file_offset < header->file_size_)) {
822 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
823 "offset %u and size %u truncated at %zu",
824 GetLocation().c_str(),
825 i,
826 dex_file_location.c_str(),
827 dex_file_offset,
828 header->file_size_,
829 DexSize());
830 return false;
831 }
832
833 uint32_t class_offsets_offset;
834 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {
835 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
836 "after class offsets offset",
837 GetLocation().c_str(),
838 i,
839 dex_file_location.c_str());
840 return false;
841 }
842 if (UNLIKELY(class_offsets_offset > Size()) ||
843 UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) {
844 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
845 "class offsets, offset %u of %zu, class defs %u",
846 GetLocation().c_str(),
847 i,
848 dex_file_location.c_str(),
849 class_offsets_offset,
850 Size(),
851 header->class_defs_size_);
852 return false;
853 }
854 if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) {
855 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned "
856 "class offsets, offset %u",
857 GetLocation().c_str(),
858 i,
859 dex_file_location.c_str(),
860 class_offsets_offset);
861 return false;
862 }
863 const uint32_t* class_offsets_pointer =
864 reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset);
865
866 uint32_t lookup_table_offset;
867 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {
868 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
869 "after lookup table offset",
870 GetLocation().c_str(),
871 i,
872 dex_file_location.c_str());
873 return false;
874 }
875 const uint8_t* lookup_table_data = lookup_table_offset != 0u
876 ? DexBegin() + lookup_table_offset
877 : nullptr;
878 if (lookup_table_offset != 0u &&
879 (UNLIKELY(lookup_table_offset > DexSize()) ||
880 UNLIKELY(DexSize() - lookup_table_offset <
881 TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
882 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
883 "type lookup table, offset %u of %zu, class defs %u",
884 GetLocation().c_str(),
885 i,
886 dex_file_location.c_str(),
887 lookup_table_offset,
888 Size(),
889 header->class_defs_size_);
890 return false;
891 }
892
893 uint32_t dex_layout_sections_offset;
894 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_layout_sections_offset))) {
895 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
896 "after dex layout sections offset",
897 GetLocation().c_str(),
898 i,
899 dex_file_location.c_str());
900 return false;
901 }
902 const DexLayoutSections* const dex_layout_sections = dex_layout_sections_offset != 0
903 ? reinterpret_cast<const DexLayoutSections*>(Begin() + dex_layout_sections_offset)
904 : nullptr;
905
906 const IndexBssMapping* method_bss_mapping;
907 const IndexBssMapping* type_bss_mapping;
908 const IndexBssMapping* public_type_bss_mapping;
909 const IndexBssMapping* package_type_bss_mapping;
910 const IndexBssMapping* string_bss_mapping;
911 if (!ReadIndexBssMapping(
912 this, &oat, i, dex_file_location, "method", &method_bss_mapping, error_msg) ||
913 !ReadIndexBssMapping(
914 this, &oat, i, dex_file_location, "type", &type_bss_mapping, error_msg) ||
915 !ReadIndexBssMapping(
916 this, &oat, i, dex_file_location, "type", &public_type_bss_mapping, error_msg) ||
917 !ReadIndexBssMapping(
918 this, &oat, i, dex_file_location, "type", &package_type_bss_mapping, error_msg) ||
919 !ReadIndexBssMapping(
920 this, &oat, i, dex_file_location, "string", &string_bss_mapping, error_msg)) {
921 return false;
922 }
923
924 // Create the OatDexFile and add it to the owning container.
925 OatDexFile* oat_dex_file = new OatDexFile(
926 this,
927 dex_file_location,
928 DexFileLoader::GetDexCanonicalLocation(dex_file_name.c_str()),
929 dex_file_checksum,
930 dex_file_pointer,
931 lookup_table_data,
932 method_bss_mapping,
933 type_bss_mapping,
934 public_type_bss_mapping,
935 package_type_bss_mapping,
936 string_bss_mapping,
937 class_offsets_pointer,
938 dex_layout_sections);
939 oat_dex_files_storage_.push_back(oat_dex_file);
940
941 // Add the location and canonical location (if different) to the oat_dex_files_ table.
942 // Note: We do not add the non-canonical `dex_file_name`. If it is different from both
943 // the location and canonical location, GetOatDexFile() shall canonicalize it when
944 // requested and match the canonical path.
945 std::string_view key = oat_dex_file_location; // References oat file data.
946 std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
947 oat_dex_files_.Put(key, oat_dex_file);
948 if (canonical_key != key) {
949 oat_dex_files_.Put(canonical_key, oat_dex_file);
950 }
951 }
952 if (!dex_filenames.empty() && dex_filenames_pos != dex_filenames.size()) {
953 *error_msg = StringPrintf("Oat file '%s' contains only %zu primary dex locations, expected %zu",
954 GetLocation().c_str(),
955 dex_filenames_pos,
956 dex_filenames.size());
957 return false;
958 }
959
960 if (DataBimgRelRoBegin() != nullptr) {
961 // Make .data.bimg.rel.ro read only. ClassLinker shall temporarily make it writable for
962 // relocation when we register a dex file from this oat file. We do not do the relocation
963 // here to avoid dirtying the pages if the code is never actually ready to be executed.
964 uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin());
965 CheckedCall(mprotect, "protect relocations", reloc_begin, DataBimgRelRoSize(), PROT_READ);
966 // Make sure the file lists a boot image dependency, otherwise the .data.bimg.rel.ro
967 // section is bogus. The full dependency is checked before the code is executed.
968 // We cannot do this check if we do not have a key-value store, i.e. for secondary
969 // oat files for boot image extensions.
970 if (GetOatHeader().GetKeyValueStoreSize() != 0u) {
971 const char* boot_class_path_checksum =
972 GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey);
973 if (boot_class_path_checksum == nullptr ||
974 boot_class_path_checksum[0] != gc::space::ImageSpace::kImageChecksumPrefix) {
975 *error_msg = StringPrintf("Oat file '%s' contains .data.bimg.rel.ro section "
976 "without boot image dependency.",
977 GetLocation().c_str());
978 return false;
979 }
980 }
981 }
982
983 return true;
984 }
985
986 ////////////////////////
987 // OatFile via dlopen //
988 ////////////////////////
989
990 class DlOpenOatFile final : public OatFileBase {
991 public:
DlOpenOatFile(const std::string & filename,bool executable)992 DlOpenOatFile(const std::string& filename, bool executable)
993 : OatFileBase(filename, executable),
994 dlopen_handle_(nullptr),
995 shared_objects_before_(0) {
996 }
997
~DlOpenOatFile()998 ~DlOpenOatFile() {
999 if (dlopen_handle_ != nullptr) {
1000 if (!kIsTargetBuild) {
1001 MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
1002 host_dlopen_handles_.erase(dlopen_handle_);
1003 dlclose(dlopen_handle_);
1004 } else {
1005 dlclose(dlopen_handle_);
1006 }
1007 }
1008 }
1009
1010 protected:
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const1011 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
1012 std::string* error_msg) const override {
1013 const uint8_t* ptr =
1014 reinterpret_cast<const uint8_t*>(dlsym(dlopen_handle_, symbol_name.c_str()));
1015 if (ptr == nullptr) {
1016 *error_msg = dlerror();
1017 }
1018 return ptr;
1019 }
1020
1021 void PreLoad() override;
1022
1023 bool Load(const std::string& elf_filename,
1024 bool writable,
1025 bool executable,
1026 bool low_4gb,
1027 /*inout*/MemMap* reservation, // Where to load if not null.
1028 /*out*/std::string* error_msg) override;
1029
Load(int oat_fd ATTRIBUTE_UNUSED,bool writable ATTRIBUTE_UNUSED,bool executable ATTRIBUTE_UNUSED,bool low_4gb ATTRIBUTE_UNUSED,MemMap * reservation ATTRIBUTE_UNUSED,std::string * error_msg ATTRIBUTE_UNUSED)1030 bool Load(int oat_fd ATTRIBUTE_UNUSED,
1031 bool writable ATTRIBUTE_UNUSED,
1032 bool executable ATTRIBUTE_UNUSED,
1033 bool low_4gb ATTRIBUTE_UNUSED,
1034 /*inout*/MemMap* reservation ATTRIBUTE_UNUSED,
1035 /*out*/std::string* error_msg ATTRIBUTE_UNUSED) override {
1036 return false;
1037 }
1038
1039 // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
1040 void PreSetup(const std::string& elf_filename) override;
1041
1042 private:
1043 bool Dlopen(const std::string& elf_filename,
1044 /*inout*/MemMap* reservation, // Where to load if not null.
1045 /*out*/std::string* error_msg);
1046
1047 // On the host, if the same library is loaded again with dlopen the same
1048 // file handle is returned. This differs from the behavior of dlopen on the
1049 // target, where dlopen reloads the library at a different address every
1050 // time you load it. The runtime relies on the target behavior to ensure
1051 // each instance of the loaded library has a unique dex cache. To avoid
1052 // problems, we fall back to our own linker in the case when the same
1053 // library is opened multiple times on host. dlopen_handles_ is used to
1054 // detect that case.
1055 // Guarded by host_dlopen_handles_lock_;
1056 static std::unordered_set<void*> host_dlopen_handles_;
1057
1058 // Reservation and placeholder memory map objects corresponding to the regions mapped by dlopen.
1059 // Note: Must be destroyed after dlclose() as it can hold the owning reservation.
1060 std::vector<MemMap> dlopen_mmaps_;
1061
1062 // dlopen handle during runtime.
1063 void* dlopen_handle_; // TODO: Unique_ptr with custom deleter.
1064
1065 // The number of shared objects the linker told us about before loading. Used to
1066 // (optimistically) optimize the PreSetup stage (see comment there).
1067 size_t shared_objects_before_;
1068
1069 DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile);
1070 };
1071
1072 std::unordered_set<void*> DlOpenOatFile::host_dlopen_handles_;
1073
PreLoad()1074 void DlOpenOatFile::PreLoad() {
1075 #ifdef __APPLE__
1076 UNUSED(shared_objects_before_);
1077 LOG(FATAL) << "Should not reach here.";
1078 UNREACHABLE();
1079 #else
1080 // Count the entries in dl_iterate_phdr we get at this point in time.
1081 struct dl_iterate_context {
1082 static int callback(dl_phdr_info* info ATTRIBUTE_UNUSED,
1083 size_t size ATTRIBUTE_UNUSED,
1084 void* data) {
1085 reinterpret_cast<dl_iterate_context*>(data)->count++;
1086 return 0; // Continue iteration.
1087 }
1088 size_t count = 0;
1089 } context;
1090
1091 dl_iterate_phdr(dl_iterate_context::callback, &context);
1092 shared_objects_before_ = context.count;
1093 #endif
1094 }
1095
Load(const std::string & elf_filename,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1096 bool DlOpenOatFile::Load(const std::string& elf_filename,
1097 bool writable,
1098 bool executable,
1099 bool low_4gb,
1100 /*inout*/MemMap* reservation, // Where to load if not null.
1101 /*out*/std::string* error_msg) {
1102 // Use dlopen only when flagged to do so, and when it's OK to load things executable.
1103 // TODO: Also try when not executable? The issue here could be re-mapping as writable (as
1104 // !executable is a sign that we may want to patch), which may not be allowed for
1105 // various reasons.
1106 if (!kUseDlopen) {
1107 *error_msg = "DlOpen is disabled.";
1108 return false;
1109 }
1110 if (low_4gb) {
1111 *error_msg = "DlOpen does not support low 4gb loading.";
1112 return false;
1113 }
1114 if (writable) {
1115 *error_msg = "DlOpen does not support writable loading.";
1116 return false;
1117 }
1118 if (!executable) {
1119 *error_msg = "DlOpen does not support non-executable loading.";
1120 return false;
1121 }
1122
1123 // dlopen always returns the same library if it is already opened on the host. For this reason
1124 // we only use dlopen if we are the target or we do not already have the dex file opened. Having
1125 // the same library loaded multiple times at different addresses is required for class unloading
1126 // and for having dex caches arrays in the .bss section.
1127 if (!kIsTargetBuild) {
1128 if (!kUseDlopenOnHost) {
1129 *error_msg = "DlOpen disabled for host.";
1130 return false;
1131 }
1132 }
1133
1134 bool success = Dlopen(elf_filename, reservation, error_msg);
1135 DCHECK(dlopen_handle_ != nullptr || !success);
1136
1137 return success;
1138 }
1139
1140 #ifdef ART_TARGET_ANDROID
GetSystemLinkerNamespace()1141 static struct android_namespace_t* GetSystemLinkerNamespace() {
1142 static struct android_namespace_t* system_ns = []() {
1143 // The system namespace is called "default" for binaries in /system and
1144 // "system" for those in the ART APEX. Try "system" first since "default"
1145 // always exists.
1146 // TODO(b/185587109): Get rid of this error prone logic.
1147 struct android_namespace_t* ns = android_get_exported_namespace("system");
1148 if (ns == nullptr) {
1149 ns = android_get_exported_namespace("default");
1150 if (ns == nullptr) {
1151 LOG(FATAL) << "Failed to get system namespace for loading OAT files";
1152 }
1153 }
1154 return ns;
1155 }();
1156 return system_ns;
1157 }
1158 #endif // ART_TARGET_ANDROID
1159
Dlopen(const std::string & elf_filename,MemMap * reservation,std::string * error_msg)1160 bool DlOpenOatFile::Dlopen(const std::string& elf_filename,
1161 /*inout*/MemMap* reservation,
1162 /*out*/std::string* error_msg) {
1163 #ifdef __APPLE__
1164 // The dl_iterate_phdr syscall is missing. There is similar API on OSX,
1165 // but let's fallback to the custom loading code for the time being.
1166 UNUSED(elf_filename, reservation);
1167 *error_msg = "Dlopen unsupported on Mac.";
1168 return false;
1169 #else
1170 {
1171 UniqueCPtr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
1172 if (absolute_path == nullptr) {
1173 *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
1174 return false;
1175 }
1176 #ifdef ART_TARGET_ANDROID
1177 android_dlextinfo extinfo = {};
1178 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD; // Force-load, don't reuse handle
1179 // (open oat files multiple times).
1180 if (reservation != nullptr) {
1181 if (!reservation->IsValid()) {
1182 *error_msg = StringPrintf("Invalid reservation for %s", elf_filename.c_str());
1183 return false;
1184 }
1185 extinfo.flags |= ANDROID_DLEXT_RESERVED_ADDRESS; // Use the reserved memory range.
1186 extinfo.reserved_addr = reservation->Begin();
1187 extinfo.reserved_size = reservation->Size();
1188 }
1189
1190 if (strncmp(kAndroidArtApexDefaultPath,
1191 absolute_path.get(),
1192 sizeof(kAndroidArtApexDefaultPath) - 1) != 0 ||
1193 absolute_path.get()[sizeof(kAndroidArtApexDefaultPath) - 1] != '/') {
1194 // Use the system namespace for OAT files outside the ART APEX. Search
1195 // paths and links don't matter here, but permitted paths do, and the
1196 // system namespace is configured to allow loading from all appropriate
1197 // locations.
1198 extinfo.flags |= ANDROID_DLEXT_USE_NAMESPACE;
1199 extinfo.library_namespace = GetSystemLinkerNamespace();
1200 }
1201
1202 dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
1203 if (reservation != nullptr && dlopen_handle_ != nullptr) {
1204 // Find used pages from the reservation.
1205 struct dl_iterate_context {
1206 static int callback(dl_phdr_info* info, size_t size ATTRIBUTE_UNUSED, void* data) {
1207 auto* context = reinterpret_cast<dl_iterate_context*>(data);
1208 static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1209 using Elf_Half = Elf64_Half;
1210
1211 // See whether this callback corresponds to the file which we have just loaded.
1212 uint8_t* reservation_begin = context->reservation->Begin();
1213 bool contained_in_reservation = false;
1214 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1215 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1216 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1217 info->dlpi_phdr[i].p_vaddr);
1218 size_t memsz = info->dlpi_phdr[i].p_memsz;
1219 size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1220 if (offset < context->reservation->Size()) {
1221 contained_in_reservation = true;
1222 DCHECK_LE(memsz, context->reservation->Size() - offset);
1223 } else if (vaddr < reservation_begin) {
1224 // Check that there's no overlap with the reservation.
1225 DCHECK_LE(memsz, static_cast<size_t>(reservation_begin - vaddr));
1226 }
1227 break; // It is sufficient to check the first PT_LOAD header.
1228 }
1229 }
1230
1231 if (contained_in_reservation) {
1232 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1233 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1234 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1235 info->dlpi_phdr[i].p_vaddr);
1236 size_t memsz = info->dlpi_phdr[i].p_memsz;
1237 size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1238 DCHECK_LT(offset, context->reservation->Size());
1239 DCHECK_LE(memsz, context->reservation->Size() - offset);
1240 context->max_size = std::max(context->max_size, offset + memsz);
1241 }
1242 }
1243
1244 return 1; // Stop iteration and return 1 from dl_iterate_phdr.
1245 }
1246 return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished.
1247 }
1248
1249 const MemMap* const reservation;
1250 size_t max_size = 0u;
1251 };
1252 dl_iterate_context context = { reservation };
1253
1254 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1255 LOG(FATAL) << "Could not find the shared object mmapped to the reservation.";
1256 UNREACHABLE();
1257 }
1258
1259 // Take ownership of the memory used by the shared object. dlopen() does not assume
1260 // full ownership of this memory and dlclose() shall just remap it as zero pages with
1261 // PROT_NONE. We need to unmap the memory when destroying this oat file.
1262 dlopen_mmaps_.push_back(reservation->TakeReservedMemory(context.max_size));
1263 }
1264 #else
1265 static_assert(!kIsTargetBuild || kIsTargetLinux || kIsTargetFuchsia,
1266 "host_dlopen_handles_ will leak handles");
1267 if (reservation != nullptr) {
1268 *error_msg = StringPrintf("dlopen() into reserved memory is unsupported on host for '%s'.",
1269 elf_filename.c_str());
1270 return false;
1271 }
1272 MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
1273 dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
1274 if (dlopen_handle_ != nullptr) {
1275 if (!host_dlopen_handles_.insert(dlopen_handle_).second) {
1276 dlclose(dlopen_handle_);
1277 dlopen_handle_ = nullptr;
1278 *error_msg = StringPrintf("host dlopen re-opened '%s'", elf_filename.c_str());
1279 return false;
1280 }
1281 }
1282 #endif // ART_TARGET_ANDROID
1283 }
1284 if (dlopen_handle_ == nullptr) {
1285 *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
1286 return false;
1287 }
1288 return true;
1289 #endif
1290 }
1291
PreSetup(const std::string & elf_filename)1292 void DlOpenOatFile::PreSetup(const std::string& elf_filename) {
1293 #ifdef __APPLE__
1294 UNUSED(elf_filename);
1295 LOG(FATAL) << "Should not reach here.";
1296 UNREACHABLE();
1297 #else
1298 struct PlaceholderMapData {
1299 const char* name;
1300 uint8_t* vaddr;
1301 size_t memsz;
1302 };
1303 struct dl_iterate_context {
1304 static int callback(dl_phdr_info* info, size_t size ATTRIBUTE_UNUSED, void* data) {
1305 auto* context = reinterpret_cast<dl_iterate_context*>(data);
1306 static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1307 using Elf_Half = Elf64_Half;
1308
1309 context->shared_objects_seen++;
1310 if (context->shared_objects_seen < context->shared_objects_before) {
1311 // We haven't been called yet for anything we haven't seen before. Just continue.
1312 // Note: this is aggressively optimistic. If another thread was unloading a library,
1313 // we may miss out here. However, this does not happen often in practice.
1314 return 0;
1315 }
1316
1317 // See whether this callback corresponds to the file which we have just loaded.
1318 bool contains_begin = false;
1319 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1320 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1321 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1322 info->dlpi_phdr[i].p_vaddr);
1323 size_t memsz = info->dlpi_phdr[i].p_memsz;
1324 if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
1325 contains_begin = true;
1326 break;
1327 }
1328 }
1329 }
1330 // Add placeholder mmaps for this file.
1331 if (contains_begin) {
1332 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1333 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1334 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1335 info->dlpi_phdr[i].p_vaddr);
1336 size_t memsz = info->dlpi_phdr[i].p_memsz;
1337 size_t name_size = strlen(info->dlpi_name) + 1u;
1338 std::vector<char>* placeholder_maps_names = context->placeholder_maps_names_;
1339 // We must not allocate any memory in the callback, see b/156312036 .
1340 if (name_size < placeholder_maps_names->capacity() - placeholder_maps_names->size() &&
1341 context->placeholder_maps_data_->size() <
1342 context->placeholder_maps_data_->capacity()) {
1343 placeholder_maps_names->insert(
1344 placeholder_maps_names->end(), info->dlpi_name, info->dlpi_name + name_size);
1345 const char* name =
1346 &(*placeholder_maps_names)[placeholder_maps_names->size() - name_size];
1347 context->placeholder_maps_data_->push_back({ name, vaddr, memsz });
1348 }
1349 context->num_placeholder_maps_ += 1u;
1350 context->placeholder_maps_names_size_ += name_size;
1351 }
1352 }
1353 return 1; // Stop iteration and return 1 from dl_iterate_phdr.
1354 }
1355 return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished.
1356 }
1357 const uint8_t* const begin_;
1358 std::vector<PlaceholderMapData>* placeholder_maps_data_;
1359 size_t num_placeholder_maps_;
1360 std::vector<char>* placeholder_maps_names_;
1361 size_t placeholder_maps_names_size_;
1362 size_t shared_objects_before;
1363 size_t shared_objects_seen;
1364 };
1365
1366 // We must not allocate any memory in the callback, see b/156312036 .
1367 // Therefore we pre-allocate storage for the data we need for creating the placeholder maps.
1368 std::vector<PlaceholderMapData> placeholder_maps_data;
1369 placeholder_maps_data.reserve(32); // 32 should be enough. If not, we'll retry.
1370 std::vector<char> placeholder_maps_names;
1371 placeholder_maps_names.reserve(4 * KB); // 4KiB should be enough. If not, we'll retry.
1372
1373 dl_iterate_context context = {
1374 Begin(),
1375 &placeholder_maps_data,
1376 /*num_placeholder_maps_*/ 0u,
1377 &placeholder_maps_names,
1378 /*placeholder_maps_names_size_*/ 0u,
1379 shared_objects_before_,
1380 /*shared_objects_seen*/ 0u
1381 };
1382
1383 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1384 // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0
1385 // before giving up. This should be unusual.
1386 VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before="
1387 << shared_objects_before_;
1388 DCHECK(placeholder_maps_data.empty());
1389 DCHECK_EQ(context.num_placeholder_maps_, 0u);
1390 DCHECK(placeholder_maps_names.empty());
1391 DCHECK_EQ(context.placeholder_maps_names_size_, 0u);
1392 context.shared_objects_before = 0u;
1393 context.shared_objects_seen = 0u;
1394 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1395 // OK, give up and print an error.
1396 PrintFileToLog("/proc/self/maps", android::base::LogSeverity::WARNING);
1397 LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps.";
1398 }
1399 }
1400
1401 if (placeholder_maps_data.size() < context.num_placeholder_maps_) {
1402 // Insufficient capacity. Reserve more space and retry.
1403 placeholder_maps_data.clear();
1404 placeholder_maps_data.reserve(context.num_placeholder_maps_);
1405 context.num_placeholder_maps_ = 0u;
1406 placeholder_maps_names.clear();
1407 placeholder_maps_names.reserve(context.placeholder_maps_names_size_);
1408 context.placeholder_maps_names_size_ = 0u;
1409 context.shared_objects_before = 0u;
1410 context.shared_objects_seen = 0u;
1411 bool success = (dl_iterate_phdr(dl_iterate_context::callback, &context) != 0);
1412 CHECK(success);
1413 }
1414
1415 CHECK_EQ(placeholder_maps_data.size(), context.num_placeholder_maps_);
1416 CHECK_EQ(placeholder_maps_names.size(), context.placeholder_maps_names_size_);
1417 DCHECK_EQ(static_cast<size_t>(std::count(placeholder_maps_names.begin(),
1418 placeholder_maps_names.end(), '\0')),
1419 context.num_placeholder_maps_);
1420 for (const PlaceholderMapData& data : placeholder_maps_data) {
1421 MemMap mmap = MemMap::MapPlaceholder(data.name, data.vaddr, data.memsz);
1422 dlopen_mmaps_.push_back(std::move(mmap));
1423 }
1424 #endif
1425 }
1426
1427 ////////////////////////////////////////////////
1428 // OatFile via our own ElfFile implementation //
1429 ////////////////////////////////////////////////
1430
1431 class ElfOatFile final : public OatFileBase {
1432 public:
ElfOatFile(const std::string & filename,bool executable)1433 ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {}
1434
1435 bool InitializeFromElfFile(int zip_fd,
1436 ElfFile* elf_file,
1437 VdexFile* vdex_file,
1438 ArrayRef<const std::string> dex_filenames,
1439 std::string* error_msg);
1440
1441 protected:
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const1442 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
1443 std::string* error_msg) const override {
1444 const uint8_t* ptr = elf_file_->FindDynamicSymbolAddress(symbol_name);
1445 if (ptr == nullptr) {
1446 *error_msg = "(Internal implementation could not find symbol)";
1447 }
1448 return ptr;
1449 }
1450
PreLoad()1451 void PreLoad() override {
1452 }
1453
1454 bool Load(const std::string& elf_filename,
1455 bool writable,
1456 bool executable,
1457 bool low_4gb,
1458 /*inout*/MemMap* reservation, // Where to load if not null.
1459 /*out*/std::string* error_msg) override;
1460
1461 bool Load(int oat_fd,
1462 bool writable,
1463 bool executable,
1464 bool low_4gb,
1465 /*inout*/MemMap* reservation, // Where to load if not null.
1466 /*out*/std::string* error_msg) override;
1467
PreSetup(const std::string & elf_filename ATTRIBUTE_UNUSED)1468 void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) override {
1469 }
1470
1471 private:
1472 bool ElfFileOpen(File* file,
1473 bool writable,
1474 bool executable,
1475 bool low_4gb,
1476 /*inout*/MemMap* reservation, // Where to load if not null.
1477 /*out*/std::string* error_msg);
1478
1479 private:
1480 // Backing memory map for oat file during cross compilation.
1481 std::unique_ptr<ElfFile> elf_file_;
1482
1483 DISALLOW_COPY_AND_ASSIGN(ElfOatFile);
1484 };
1485
InitializeFromElfFile(int zip_fd,ElfFile * elf_file,VdexFile * vdex_file,ArrayRef<const std::string> dex_filenames,std::string * error_msg)1486 bool ElfOatFile::InitializeFromElfFile(int zip_fd,
1487 ElfFile* elf_file,
1488 VdexFile* vdex_file,
1489 ArrayRef<const std::string> dex_filenames,
1490 std::string* error_msg) {
1491 ScopedTrace trace(__PRETTY_FUNCTION__);
1492 if (IsExecutable()) {
1493 *error_msg = "Cannot initialize from elf file in executable mode.";
1494 return false;
1495 }
1496 elf_file_.reset(elf_file);
1497 SetVdex(vdex_file);
1498 uint64_t offset, size;
1499 bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
1500 CHECK(has_section);
1501 SetBegin(elf_file->Begin() + offset);
1502 SetEnd(elf_file->Begin() + size + offset);
1503 // Ignore the optional .bss section when opening non-executable.
1504 return Setup(zip_fd, dex_filenames, error_msg);
1505 }
1506
Load(const std::string & elf_filename,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1507 bool ElfOatFile::Load(const std::string& elf_filename,
1508 bool writable,
1509 bool executable,
1510 bool low_4gb,
1511 /*inout*/MemMap* reservation,
1512 /*out*/std::string* error_msg) {
1513 ScopedTrace trace(__PRETTY_FUNCTION__);
1514 std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
1515 if (file == nullptr) {
1516 *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
1517 return false;
1518 }
1519 return ElfOatFile::ElfFileOpen(file.get(),
1520 writable,
1521 executable,
1522 low_4gb,
1523 reservation,
1524 error_msg);
1525 }
1526
Load(int oat_fd,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1527 bool ElfOatFile::Load(int oat_fd,
1528 bool writable,
1529 bool executable,
1530 bool low_4gb,
1531 /*inout*/MemMap* reservation,
1532 /*out*/std::string* error_msg) {
1533 ScopedTrace trace(__PRETTY_FUNCTION__);
1534 if (oat_fd != -1) {
1535 int duped_fd = DupCloexec(oat_fd);
1536 std::unique_ptr<File> file = std::make_unique<File>(duped_fd, false);
1537 if (file == nullptr) {
1538 *error_msg = StringPrintf("Failed to open oat filename for reading: %s",
1539 strerror(errno));
1540 return false;
1541 }
1542 return ElfOatFile::ElfFileOpen(file.get(),
1543 writable,
1544 executable,
1545 low_4gb,
1546 reservation,
1547 error_msg);
1548 }
1549 return false;
1550 }
1551
ElfFileOpen(File * file,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1552 bool ElfOatFile::ElfFileOpen(File* file,
1553 bool writable,
1554 bool executable,
1555 bool low_4gb,
1556 /*inout*/MemMap* reservation,
1557 /*out*/std::string* error_msg) {
1558 ScopedTrace trace(__PRETTY_FUNCTION__);
1559 elf_file_.reset(ElfFile::Open(file,
1560 writable,
1561 /*program_header_only=*/ true,
1562 low_4gb,
1563 error_msg));
1564 if (elf_file_ == nullptr) {
1565 DCHECK(!error_msg->empty());
1566 return false;
1567 }
1568 bool loaded = elf_file_->Load(file, executable, low_4gb, reservation, error_msg);
1569 DCHECK(loaded || !error_msg->empty());
1570 return loaded;
1571 }
1572
1573 class OatFileBackedByVdex final : public OatFileBase {
1574 public:
OatFileBackedByVdex(const std::string & filename)1575 explicit OatFileBackedByVdex(const std::string& filename)
1576 : OatFileBase(filename, /*executable=*/ false) {}
1577
Open(const std::vector<const DexFile * > & dex_files,std::unique_ptr<VdexFile> && vdex_file,const std::string & location)1578 static OatFileBackedByVdex* Open(const std::vector<const DexFile*>& dex_files,
1579 std::unique_ptr<VdexFile>&& vdex_file,
1580 const std::string& location) {
1581 std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(location));
1582 // SetVdex will take ownership of the VdexFile.
1583 oat_file->SetVdex(vdex_file.release());
1584 oat_file->SetupHeader(dex_files.size());
1585 // Initialize OatDexFiles.
1586 oat_file->Setup(dex_files);
1587 return oat_file.release();
1588 }
1589
Open(int zip_fd,std::unique_ptr<VdexFile> && unique_vdex_file,const std::string & dex_location,std::string * error_msg)1590 static OatFileBackedByVdex* Open(int zip_fd,
1591 std::unique_ptr<VdexFile>&& unique_vdex_file,
1592 const std::string& dex_location,
1593 std::string* error_msg) {
1594 VdexFile* vdex_file = unique_vdex_file.get();
1595 std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(vdex_file->GetName()));
1596 // SetVdex will take ownership of the VdexFile.
1597 oat_file->SetVdex(unique_vdex_file.release());
1598 if (vdex_file->HasDexSection()) {
1599 uint32_t i = 0;
1600 const uint8_t* type_lookup_table_start = nullptr;
1601 for (const uint8_t* dex_file_start = vdex_file->GetNextDexFileData(nullptr, i);
1602 dex_file_start != nullptr;
1603 dex_file_start = vdex_file->GetNextDexFileData(dex_file_start, ++i)) {
1604 if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_start))) {
1605 *error_msg =
1606 StringPrintf("In vdex file '%s' found dex file with invalid dex file version",
1607 dex_location.c_str());
1608 return nullptr;
1609 }
1610 // Create the OatDexFile and add it to the owning container.
1611 std::string location = DexFileLoader::GetMultiDexLocation(i, dex_location.c_str());
1612 std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(location.c_str());
1613 type_lookup_table_start = vdex_file->GetNextTypeLookupTableData(type_lookup_table_start, i);
1614 const uint8_t* type_lookup_table_data = nullptr;
1615 if (type_lookup_table_start != nullptr &&
1616 (reinterpret_cast<uint32_t*>(type_lookup_table_start[0]) != 0)) {
1617 type_lookup_table_data = type_lookup_table_start + sizeof(uint32_t);
1618 }
1619 OatDexFile* oat_dex_file = new OatDexFile(oat_file.get(),
1620 dex_file_start,
1621 vdex_file->GetLocationChecksum(i),
1622 location,
1623 canonical_location,
1624 type_lookup_table_data);
1625 oat_file->oat_dex_files_storage_.push_back(oat_dex_file);
1626
1627 std::string_view key(oat_dex_file->GetDexFileLocation());
1628 oat_file->oat_dex_files_.Put(key, oat_dex_file);
1629 if (canonical_location != location) {
1630 std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
1631 oat_file->oat_dex_files_.Put(canonical_key, oat_dex_file);
1632 }
1633 }
1634 oat_file->SetupHeader(oat_file->oat_dex_files_storage_.size());
1635 } else {
1636 // No need for any verification when loading dex files as we already have
1637 // a vdex file.
1638 const ArtDexFileLoader dex_file_loader;
1639 bool loaded = false;
1640 if (zip_fd != -1) {
1641 loaded = dex_file_loader.OpenZip(zip_fd,
1642 dex_location,
1643 /*verify=*/ false,
1644 /*verify_checksum=*/ false,
1645 error_msg,
1646 &oat_file->external_dex_files_);
1647 } else {
1648 loaded = dex_file_loader.Open(dex_location.c_str(),
1649 dex_location,
1650 /*verify=*/ false,
1651 /*verify_checksum=*/ false,
1652 error_msg,
1653 &oat_file->external_dex_files_);
1654 }
1655 if (!loaded) {
1656 return nullptr;
1657 }
1658 oat_file->SetupHeader(oat_file->external_dex_files_.size());
1659 oat_file->Setup(MakeNonOwningPointerVector(oat_file->external_dex_files_));
1660 }
1661
1662 return oat_file.release();
1663 }
1664
SetupHeader(size_t number_of_dex_files)1665 void SetupHeader(size_t number_of_dex_files) {
1666 DCHECK(!IsExecutable());
1667
1668 // Create a fake OatHeader with a key store to help debugging.
1669 std::unique_ptr<const InstructionSetFeatures> isa_features =
1670 InstructionSetFeatures::FromCppDefines();
1671 SafeMap<std::string, std::string> store;
1672 store.Put(OatHeader::kCompilerFilter, CompilerFilter::NameOfFilter(CompilerFilter::kVerify));
1673 store.Put(OatHeader::kCompilationReasonKey, "vdex");
1674 store.Put(OatHeader::kConcurrentCopying,
1675 kUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
1676 oat_header_.reset(OatHeader::Create(kRuntimeISA,
1677 isa_features.get(),
1678 number_of_dex_files,
1679 &store));
1680 const uint8_t* begin = reinterpret_cast<const uint8_t*>(oat_header_.get());
1681 SetBegin(begin);
1682 SetEnd(begin + oat_header_->GetHeaderSize());
1683 }
1684
1685 protected:
PreLoad()1686 void PreLoad() override {}
1687
Load(const std::string & elf_filename ATTRIBUTE_UNUSED,bool writable ATTRIBUTE_UNUSED,bool executable ATTRIBUTE_UNUSED,bool low_4gb ATTRIBUTE_UNUSED,MemMap * reservation ATTRIBUTE_UNUSED,std::string * error_msg ATTRIBUTE_UNUSED)1688 bool Load(const std::string& elf_filename ATTRIBUTE_UNUSED,
1689 bool writable ATTRIBUTE_UNUSED,
1690 bool executable ATTRIBUTE_UNUSED,
1691 bool low_4gb ATTRIBUTE_UNUSED,
1692 MemMap* reservation ATTRIBUTE_UNUSED,
1693 std::string* error_msg ATTRIBUTE_UNUSED) override {
1694 LOG(FATAL) << "Unsupported";
1695 UNREACHABLE();
1696 }
1697
Load(int oat_fd ATTRIBUTE_UNUSED,bool writable ATTRIBUTE_UNUSED,bool executable ATTRIBUTE_UNUSED,bool low_4gb ATTRIBUTE_UNUSED,MemMap * reservation ATTRIBUTE_UNUSED,std::string * error_msg ATTRIBUTE_UNUSED)1698 bool Load(int oat_fd ATTRIBUTE_UNUSED,
1699 bool writable ATTRIBUTE_UNUSED,
1700 bool executable ATTRIBUTE_UNUSED,
1701 bool low_4gb ATTRIBUTE_UNUSED,
1702 MemMap* reservation ATTRIBUTE_UNUSED,
1703 std::string* error_msg ATTRIBUTE_UNUSED) override {
1704 LOG(FATAL) << "Unsupported";
1705 UNREACHABLE();
1706 }
1707
PreSetup(const std::string & elf_filename ATTRIBUTE_UNUSED)1708 void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) override {}
1709
FindDynamicSymbolAddress(const std::string & symbol_name ATTRIBUTE_UNUSED,std::string * error_msg) const1710 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name ATTRIBUTE_UNUSED,
1711 std::string* error_msg) const override {
1712 *error_msg = "Unsupported";
1713 return nullptr;
1714 }
1715
1716 private:
1717 std::unique_ptr<OatHeader> oat_header_;
1718
1719 DISALLOW_COPY_AND_ASSIGN(OatFileBackedByVdex);
1720 };
1721
1722 //////////////////////////
1723 // General OatFile code //
1724 //////////////////////////
1725
CheckLocation(const std::string & location)1726 static void CheckLocation(const std::string& location) {
1727 CHECK(!location.empty());
1728 }
1729
Open(int zip_fd,const std::string & oat_filename,const std::string & oat_location,bool executable,bool low_4gb,ArrayRef<const std::string> dex_filenames,MemMap * reservation,std::string * error_msg)1730 OatFile* OatFile::Open(int zip_fd,
1731 const std::string& oat_filename,
1732 const std::string& oat_location,
1733 bool executable,
1734 bool low_4gb,
1735 ArrayRef<const std::string> dex_filenames,
1736 /*inout*/MemMap* reservation,
1737 /*out*/std::string* error_msg) {
1738 ScopedTrace trace("Open oat file " + oat_location);
1739 CHECK(!oat_filename.empty()) << oat_location;
1740 CheckLocation(oat_location);
1741
1742 std::string vdex_filename = GetVdexFilename(oat_filename);
1743
1744 // Check that the vdex file even exists, fast-fail. We don't check the odex
1745 // file as we use the absence of an odex file for test the functionality of
1746 // vdex-only.
1747 if (!OS::FileExists(vdex_filename.c_str())) {
1748 *error_msg = StringPrintf("File %s does not exist.", vdex_filename.c_str());
1749 return nullptr;
1750 }
1751
1752 // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
1753 // disabled.
1754 OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(zip_fd,
1755 vdex_filename,
1756 oat_filename,
1757 oat_location,
1758 /*writable=*/ false,
1759 executable,
1760 low_4gb,
1761 dex_filenames,
1762 reservation,
1763 error_msg);
1764 if (with_dlopen != nullptr) {
1765 Runtime* runtime = Runtime::Current();
1766 // The runtime might not be available at this point if we're running
1767 // dex2oat or oatdump.
1768 if (runtime != nullptr) {
1769 size_t madvise_size_limit = runtime->GetMadviseWillNeedSizeOdex();
1770 Runtime::MadviseFileForRange(madvise_size_limit,
1771 with_dlopen->Size(),
1772 with_dlopen->Begin(),
1773 with_dlopen->End(),
1774 oat_location);
1775 }
1776 return with_dlopen;
1777 }
1778 if (kPrintDlOpenErrorMessage) {
1779 LOG(ERROR) << "Failed to dlopen: " << oat_filename << " with error " << *error_msg;
1780 }
1781 // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
1782 //
1783 // On target, dlopen may fail when compiling due to selinux restrictions on installd.
1784 //
1785 // We use our own ELF loader for Quick to deal with legacy apps that
1786 // open a generated dex file by name, remove the file, then open
1787 // another generated dex file with the same name. http://b/10614658
1788 //
1789 // On host, dlopen is expected to fail when cross compiling, so fall back to ElfOatFile.
1790 //
1791 //
1792 // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
1793 // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN.
1794 OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1795 vdex_filename,
1796 oat_filename,
1797 oat_location,
1798 /*writable=*/ false,
1799 executable,
1800 low_4gb,
1801 dex_filenames,
1802 reservation,
1803 error_msg);
1804 return with_internal;
1805 }
1806
Open(int zip_fd,int vdex_fd,int oat_fd,const std::string & oat_location,bool executable,bool low_4gb,ArrayRef<const std::string> dex_filenames,MemMap * reservation,std::string * error_msg)1807 OatFile* OatFile::Open(int zip_fd,
1808 int vdex_fd,
1809 int oat_fd,
1810 const std::string& oat_location,
1811 bool executable,
1812 bool low_4gb,
1813 ArrayRef<const std::string> dex_filenames,
1814 /*inout*/MemMap* reservation,
1815 /*out*/std::string* error_msg) {
1816 CHECK(!oat_location.empty()) << oat_location;
1817
1818 std::string vdex_location = GetVdexFilename(oat_location);
1819
1820 OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1821 vdex_fd,
1822 oat_fd,
1823 vdex_location,
1824 oat_location,
1825 /*writable=*/ false,
1826 executable,
1827 low_4gb,
1828 dex_filenames,
1829 reservation,
1830 error_msg);
1831 return with_internal;
1832 }
1833
OpenFromVdex(const std::vector<const DexFile * > & dex_files,std::unique_ptr<VdexFile> && vdex_file,const std::string & location)1834 OatFile* OatFile::OpenFromVdex(const std::vector<const DexFile*>& dex_files,
1835 std::unique_ptr<VdexFile>&& vdex_file,
1836 const std::string& location) {
1837 CheckLocation(location);
1838 return OatFileBackedByVdex::Open(dex_files, std::move(vdex_file), location);
1839 }
1840
OpenFromVdex(int zip_fd,std::unique_ptr<VdexFile> && vdex_file,const std::string & location,std::string * error_msg)1841 OatFile* OatFile::OpenFromVdex(int zip_fd,
1842 std::unique_ptr<VdexFile>&& vdex_file,
1843 const std::string& location,
1844 std::string* error_msg) {
1845 CheckLocation(location);
1846 return OatFileBackedByVdex::Open(zip_fd, std::move(vdex_file), location, error_msg);
1847 }
1848
OatFile(const std::string & location,bool is_executable)1849 OatFile::OatFile(const std::string& location, bool is_executable)
1850 : location_(location),
1851 vdex_(nullptr),
1852 begin_(nullptr),
1853 end_(nullptr),
1854 data_bimg_rel_ro_begin_(nullptr),
1855 data_bimg_rel_ro_end_(nullptr),
1856 bss_begin_(nullptr),
1857 bss_end_(nullptr),
1858 bss_methods_(nullptr),
1859 bss_roots_(nullptr),
1860 is_executable_(is_executable),
1861 vdex_begin_(nullptr),
1862 vdex_end_(nullptr),
1863 secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
1864 CHECK(!location_.empty());
1865 }
1866
~OatFile()1867 OatFile::~OatFile() {
1868 STLDeleteElements(&oat_dex_files_storage_);
1869 }
1870
GetOatHeader() const1871 const OatHeader& OatFile::GetOatHeader() const {
1872 return *reinterpret_cast<const OatHeader*>(Begin());
1873 }
1874
Begin() const1875 const uint8_t* OatFile::Begin() const {
1876 CHECK(begin_ != nullptr);
1877 return begin_;
1878 }
1879
End() const1880 const uint8_t* OatFile::End() const {
1881 CHECK(end_ != nullptr);
1882 return end_;
1883 }
1884
DexBegin() const1885 const uint8_t* OatFile::DexBegin() const {
1886 return vdex_->Begin();
1887 }
1888
DexEnd() const1889 const uint8_t* OatFile::DexEnd() const {
1890 return vdex_->End();
1891 }
1892
GetBootImageRelocations() const1893 ArrayRef<const uint32_t> OatFile::GetBootImageRelocations() const {
1894 if (data_bimg_rel_ro_begin_ != nullptr) {
1895 const uint32_t* relocations = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_begin_);
1896 const uint32_t* relocations_end = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_end_);
1897 return ArrayRef<const uint32_t>(relocations, relocations_end - relocations);
1898 } else {
1899 return ArrayRef<const uint32_t>();
1900 }
1901 }
1902
GetBssMethods() const1903 ArrayRef<ArtMethod*> OatFile::GetBssMethods() const {
1904 if (bss_methods_ != nullptr) {
1905 ArtMethod** methods = reinterpret_cast<ArtMethod**>(bss_methods_);
1906 ArtMethod** methods_end =
1907 reinterpret_cast<ArtMethod**>(bss_roots_ != nullptr ? bss_roots_ : bss_end_);
1908 return ArrayRef<ArtMethod*>(methods, methods_end - methods);
1909 } else {
1910 return ArrayRef<ArtMethod*>();
1911 }
1912 }
1913
GetBssGcRoots() const1914 ArrayRef<GcRoot<mirror::Object>> OatFile::GetBssGcRoots() const {
1915 if (bss_roots_ != nullptr) {
1916 auto* roots = reinterpret_cast<GcRoot<mirror::Object>*>(bss_roots_);
1917 auto* roots_end = reinterpret_cast<GcRoot<mirror::Object>*>(bss_end_);
1918 return ArrayRef<GcRoot<mirror::Object>>(roots, roots_end - roots);
1919 } else {
1920 return ArrayRef<GcRoot<mirror::Object>>();
1921 }
1922 }
1923
GetOatDexFile(const char * dex_location,const uint32_t * dex_location_checksum,std::string * error_msg) const1924 const OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
1925 const uint32_t* dex_location_checksum,
1926 std::string* error_msg) const {
1927 // NOTE: We assume here that the canonical location for a given dex_location never
1928 // changes. If it does (i.e. some symlink used by the filename changes) we may return
1929 // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
1930 // an identical file or fail; otherwise we may see some unpredictable failures.
1931
1932 // TODO: Additional analysis of usage patterns to see if this can be simplified
1933 // without any performance loss, for example by not doing the first lock-free lookup.
1934
1935 const OatDexFile* oat_dex_file = nullptr;
1936 std::string_view key(dex_location);
1937 // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
1938 // directly mentioned in the oat file and doesn't require locking.
1939 auto primary_it = oat_dex_files_.find(key);
1940 if (primary_it != oat_dex_files_.end()) {
1941 oat_dex_file = primary_it->second;
1942 DCHECK(oat_dex_file != nullptr);
1943 } else {
1944 // This dex_location is not one of the dex locations directly mentioned in the
1945 // oat file. The correct lookup is via the canonical location but first see in
1946 // the secondary_oat_dex_files_ whether we've looked up this location before.
1947 MutexLock mu(Thread::Current(), secondary_lookup_lock_);
1948 auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
1949 if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
1950 oat_dex_file = secondary_lb->second; // May be null.
1951 } else {
1952 // We haven't seen this dex_location before, we must check the canonical location.
1953 std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
1954 if (dex_canonical_location != dex_location) {
1955 std::string_view canonical_key(dex_canonical_location);
1956 auto canonical_it = oat_dex_files_.find(canonical_key);
1957 if (canonical_it != oat_dex_files_.end()) {
1958 oat_dex_file = canonical_it->second;
1959 } // else keep null.
1960 } // else keep null.
1961
1962 // Copy the key to the string_cache_ and store the result in secondary map.
1963 string_cache_.emplace_back(key.data(), key.length());
1964 std::string_view key_copy(string_cache_.back());
1965 secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
1966 }
1967 }
1968
1969 if (oat_dex_file == nullptr) {
1970 if (error_msg != nullptr) {
1971 std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
1972 *error_msg = "Failed to find OatDexFile for DexFile " + std::string(dex_location)
1973 + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation();
1974 }
1975 return nullptr;
1976 }
1977
1978 if (dex_location_checksum != nullptr &&
1979 oat_dex_file->GetDexFileLocationChecksum() != *dex_location_checksum) {
1980 if (error_msg != nullptr) {
1981 std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
1982 std::string checksum = StringPrintf("0x%08x", oat_dex_file->GetDexFileLocationChecksum());
1983 std::string required_checksum = StringPrintf("0x%08x", *dex_location_checksum);
1984 *error_msg = "OatDexFile for DexFile " + std::string(dex_location)
1985 + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation()
1986 + " has checksum " + checksum + " but " + required_checksum + " was required";
1987 }
1988 return nullptr;
1989 }
1990 return oat_dex_file;
1991 }
1992
OatDexFile(const OatFile * oat_file,const std::string & dex_file_location,const std::string & canonical_dex_file_location,uint32_t dex_file_location_checksum,const uint8_t * dex_file_pointer,const uint8_t * lookup_table_data,const IndexBssMapping * method_bss_mapping_data,const IndexBssMapping * type_bss_mapping_data,const IndexBssMapping * public_type_bss_mapping_data,const IndexBssMapping * package_type_bss_mapping_data,const IndexBssMapping * string_bss_mapping_data,const uint32_t * oat_class_offsets_pointer,const DexLayoutSections * dex_layout_sections)1993 OatDexFile::OatDexFile(const OatFile* oat_file,
1994 const std::string& dex_file_location,
1995 const std::string& canonical_dex_file_location,
1996 uint32_t dex_file_location_checksum,
1997 const uint8_t* dex_file_pointer,
1998 const uint8_t* lookup_table_data,
1999 const IndexBssMapping* method_bss_mapping_data,
2000 const IndexBssMapping* type_bss_mapping_data,
2001 const IndexBssMapping* public_type_bss_mapping_data,
2002 const IndexBssMapping* package_type_bss_mapping_data,
2003 const IndexBssMapping* string_bss_mapping_data,
2004 const uint32_t* oat_class_offsets_pointer,
2005 const DexLayoutSections* dex_layout_sections)
2006 : oat_file_(oat_file),
2007 dex_file_location_(dex_file_location),
2008 canonical_dex_file_location_(canonical_dex_file_location),
2009 dex_file_location_checksum_(dex_file_location_checksum),
2010 dex_file_pointer_(dex_file_pointer),
2011 lookup_table_data_(lookup_table_data),
2012 method_bss_mapping_(method_bss_mapping_data),
2013 type_bss_mapping_(type_bss_mapping_data),
2014 public_type_bss_mapping_(public_type_bss_mapping_data),
2015 package_type_bss_mapping_(package_type_bss_mapping_data),
2016 string_bss_mapping_(string_bss_mapping_data),
2017 oat_class_offsets_pointer_(oat_class_offsets_pointer),
2018 lookup_table_(),
2019 dex_layout_sections_(dex_layout_sections) {
2020 InitializeTypeLookupTable();
2021 DCHECK(!IsBackedByVdexOnly());
2022 }
2023
InitializeTypeLookupTable()2024 void OatDexFile::InitializeTypeLookupTable() {
2025 // Initialize TypeLookupTable.
2026 if (lookup_table_data_ != nullptr) {
2027 // Peek the number of classes from the DexFile.
2028 const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_);
2029 const uint32_t num_class_defs = dex_header->class_defs_size_;
2030 if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) >
2031 GetOatFile()->DexEnd()) {
2032 LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
2033 } else {
2034 const uint8_t* dex_data = dex_file_pointer_;
2035 // TODO: Clean this up to create the type lookup table after the dex file has been created?
2036 if (CompactDexFile::IsMagicValid(dex_header->magic_)) {
2037 dex_data += dex_header->data_off_;
2038 }
2039 lookup_table_ = TypeLookupTable::Open(dex_data, lookup_table_data_, num_class_defs);
2040 }
2041 }
2042 }
2043
OatDexFile(const OatFile * oat_file,const uint8_t * dex_file_pointer,uint32_t dex_file_location_checksum,const std::string & dex_file_location,const std::string & canonical_dex_file_location,const uint8_t * lookup_table_data)2044 OatDexFile::OatDexFile(const OatFile* oat_file,
2045 const uint8_t* dex_file_pointer,
2046 uint32_t dex_file_location_checksum,
2047 const std::string& dex_file_location,
2048 const std::string& canonical_dex_file_location,
2049 const uint8_t* lookup_table_data)
2050 : oat_file_(oat_file),
2051 dex_file_location_(dex_file_location),
2052 canonical_dex_file_location_(canonical_dex_file_location),
2053 dex_file_location_checksum_(dex_file_location_checksum),
2054 dex_file_pointer_(dex_file_pointer),
2055 lookup_table_data_(lookup_table_data) {
2056 InitializeTypeLookupTable();
2057 DCHECK(IsBackedByVdexOnly());
2058 }
2059
OatDexFile(TypeLookupTable && lookup_table)2060 OatDexFile::OatDexFile(TypeLookupTable&& lookup_table) : lookup_table_(std::move(lookup_table)) {
2061 // Stripped-down OatDexFile only allowed in the compiler, the zygote, or the system server.
2062 CHECK(Runtime::Current() == nullptr ||
2063 Runtime::Current()->IsAotCompiler() ||
2064 Runtime::Current()->IsZygote() ||
2065 Runtime::Current()->IsSystemServer());
2066 }
2067
~OatDexFile()2068 OatDexFile::~OatDexFile() {}
2069
FileSize() const2070 size_t OatDexFile::FileSize() const {
2071 DCHECK(dex_file_pointer_ != nullptr);
2072 return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
2073 }
2074
OpenDexFile(std::string * error_msg) const2075 std::unique_ptr<const DexFile> OatDexFile::OpenDexFile(std::string* error_msg) const {
2076 ScopedTrace trace(__PRETTY_FUNCTION__);
2077 static constexpr bool kVerify = false;
2078 static constexpr bool kVerifyChecksum = false;
2079 const ArtDexFileLoader dex_file_loader;
2080 return dex_file_loader.Open(dex_file_pointer_,
2081 FileSize(),
2082 dex_file_location_,
2083 dex_file_location_checksum_,
2084 this,
2085 kVerify,
2086 kVerifyChecksum,
2087 error_msg);
2088 }
2089
GetOatClassOffset(uint16_t class_def_index) const2090 uint32_t OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
2091 DCHECK(oat_class_offsets_pointer_ != nullptr);
2092 return oat_class_offsets_pointer_[class_def_index];
2093 }
2094
IsBackedByVdexOnly() const2095 bool OatDexFile::IsBackedByVdexOnly() const {
2096 return oat_class_offsets_pointer_ == nullptr;
2097 }
2098
GetOatClass(uint16_t class_def_index) const2099 OatFile::OatClass OatDexFile::GetOatClass(uint16_t class_def_index) const {
2100 if (IsBackedByVdexOnly()) {
2101 // If there is only a vdex file, return that the class is not ready. The
2102 // caller will have to call `VdexFile::ComputeClassStatus` to compute the
2103 // actual class status, because we need to do the assignability type checks.
2104 return OatFile::OatClass(oat_file_,
2105 ClassStatus::kNotReady,
2106 /* type= */ OatClassType::kNoneCompiled,
2107 /* bitmap_size= */ 0u,
2108 /* bitmap_pointer= */ nullptr,
2109 /* methods_pointer= */ nullptr);
2110 }
2111
2112 uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
2113 CHECK_GE(oat_class_offset, sizeof(OatHeader)) << oat_file_->GetLocation();
2114 CHECK_LT(oat_class_offset, oat_file_->Size()) << oat_file_->GetLocation();
2115 CHECK_LE(/* status */ sizeof(uint16_t) + /* type */ sizeof(uint16_t),
2116 oat_file_->Size() - oat_class_offset) << oat_file_->GetLocation();
2117 const uint8_t* current_pointer = oat_file_->Begin() + oat_class_offset;
2118
2119 uint16_t status_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2120 current_pointer += sizeof(uint16_t);
2121 uint16_t type_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2122 current_pointer += sizeof(uint16_t);
2123 CHECK_LE(status_value, enum_cast<uint8_t>(ClassStatus::kLast))
2124 << static_cast<uint32_t>(status_value) << " at " << oat_file_->GetLocation();
2125 CHECK_LT(type_value, enum_cast<uint8_t>(OatClassType::kOatClassMax)) << oat_file_->GetLocation();
2126 ClassStatus status = enum_cast<ClassStatus>(status_value);
2127 OatClassType type = enum_cast<OatClassType>(type_value);
2128
2129 uint32_t num_methods = 0;
2130 const uint32_t* bitmap_pointer = nullptr;
2131 const OatMethodOffsets* methods_pointer = nullptr;
2132 if (type != OatClassType::kNoneCompiled) {
2133 CHECK_LE(sizeof(uint32_t), static_cast<size_t>(oat_file_->End() - current_pointer))
2134 << oat_file_->GetLocation();
2135 num_methods = *reinterpret_cast<const uint32_t*>(current_pointer);
2136 current_pointer += sizeof(uint32_t);
2137 CHECK_NE(num_methods, 0u) << oat_file_->GetLocation();
2138 uint32_t num_method_offsets;
2139 if (type == OatClassType::kSomeCompiled) {
2140 uint32_t bitmap_size = BitVector::BitsToWords(num_methods) * BitVector::kWordBytes;
2141 CHECK_LE(bitmap_size, static_cast<size_t>(oat_file_->End() - current_pointer))
2142 << oat_file_->GetLocation();
2143 bitmap_pointer = reinterpret_cast<const uint32_t*>(current_pointer);
2144 current_pointer += bitmap_size;
2145 // Note: The bits in range [num_methods, bitmap_size * kBitsPerByte)
2146 // should be zero but we're not verifying that.
2147 num_method_offsets = BitVector::NumSetBits(bitmap_pointer, num_methods);
2148 } else {
2149 num_method_offsets = num_methods;
2150 }
2151 CHECK_LE(num_method_offsets,
2152 static_cast<size_t>(oat_file_->End() - current_pointer) / sizeof(OatMethodOffsets))
2153 << oat_file_->GetLocation();
2154 methods_pointer = reinterpret_cast<const OatMethodOffsets*>(current_pointer);
2155 }
2156
2157 return OatFile::OatClass(oat_file_, status, type, num_methods, bitmap_pointer, methods_pointer);
2158 }
2159
FindClassDef(const DexFile & dex_file,const char * descriptor,size_t hash)2160 const dex::ClassDef* OatDexFile::FindClassDef(const DexFile& dex_file,
2161 const char* descriptor,
2162 size_t hash) {
2163 const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2164 DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash);
2165 bool used_lookup_table = false;
2166 const dex::ClassDef* lookup_table_classdef = nullptr;
2167 if (LIKELY((oat_dex_file != nullptr) && oat_dex_file->GetTypeLookupTable().Valid())) {
2168 used_lookup_table = true;
2169 const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable().Lookup(descriptor, hash);
2170 if (class_def_idx != dex::kDexNoIndex) {
2171 CHECK_LT(class_def_idx, dex_file.NumClassDefs()) << oat_dex_file->GetOatFile()->GetLocation();
2172 lookup_table_classdef = &dex_file.GetClassDef(class_def_idx);
2173 }
2174 if (!kIsDebugBuild) {
2175 return lookup_table_classdef;
2176 }
2177 }
2178 // Fast path for rare no class defs case.
2179 const uint32_t num_class_defs = dex_file.NumClassDefs();
2180 if (num_class_defs == 0) {
2181 DCHECK(!used_lookup_table);
2182 return nullptr;
2183 }
2184 const dex::TypeId* type_id = dex_file.FindTypeId(descriptor);
2185 if (type_id != nullptr) {
2186 dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id);
2187 const dex::ClassDef* found_class_def = dex_file.FindClassDef(type_idx);
2188 if (kIsDebugBuild && used_lookup_table) {
2189 DCHECK_EQ(found_class_def, lookup_table_classdef);
2190 }
2191 return found_class_def;
2192 }
2193 return nullptr;
2194 }
2195
2196 // Madvise the dex file based on the state we are moving to.
MadviseDexFile(const DexFile & dex_file,MadviseState state)2197 void OatDexFile::MadviseDexFile(const DexFile& dex_file, MadviseState state) {
2198 Runtime* const runtime = Runtime::Current();
2199 const bool low_ram = runtime->GetHeap()->IsLowMemoryMode();
2200 // TODO: Also do madvise hints for non low ram devices.
2201 if (!low_ram) {
2202 return;
2203 }
2204 if (state == MadviseState::kMadviseStateAtLoad && runtime->MAdviseRandomAccess()) {
2205 // Default every dex file to MADV_RANDOM when its loaded by default for low ram devices.
2206 // Other devices have enough page cache to get performance benefits from loading more pages
2207 // into the page cache.
2208 DexLayoutSection::MadviseLargestPageAlignedRegion(dex_file.Begin(),
2209 dex_file.Begin() + dex_file.Size(),
2210 MADV_RANDOM);
2211 }
2212 const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2213 if (oat_dex_file != nullptr) {
2214 // Should always be there.
2215 const DexLayoutSections* const sections = oat_dex_file->GetDexLayoutSections();
2216 if (sections != nullptr) {
2217 sections->Madvise(&dex_file, state);
2218 } else {
2219 DCHECK(oat_dex_file->IsBackedByVdexOnly());
2220 }
2221 }
2222 }
2223
OatClass(const OatFile * oat_file,ClassStatus status,OatClassType type,uint32_t num_methods,const uint32_t * bitmap_pointer,const OatMethodOffsets * methods_pointer)2224 OatFile::OatClass::OatClass(const OatFile* oat_file,
2225 ClassStatus status,
2226 OatClassType type,
2227 uint32_t num_methods,
2228 const uint32_t* bitmap_pointer,
2229 const OatMethodOffsets* methods_pointer)
2230 : oat_file_(oat_file),
2231 status_(status),
2232 type_(type),
2233 num_methods_(num_methods),
2234 bitmap_(bitmap_pointer),
2235 methods_pointer_(methods_pointer) {
2236 DCHECK_EQ(num_methods != 0u, type != OatClassType::kNoneCompiled);
2237 DCHECK_EQ(bitmap_pointer != nullptr, type == OatClassType::kSomeCompiled);
2238 DCHECK_EQ(methods_pointer != nullptr, type != OatClassType::kNoneCompiled);
2239 }
2240
GetOatMethodOffsetsOffset(uint32_t method_index) const2241 uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
2242 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2243 if (oat_method_offsets == nullptr) {
2244 return 0u;
2245 }
2246 return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
2247 }
2248
GetOatMethodOffsets(uint32_t method_index) const2249 const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
2250 // NOTE: We don't keep the number of methods for `kNoneCompiled` and cannot do
2251 // a bounds check for `method_index` in that case.
2252 if (methods_pointer_ == nullptr) {
2253 CHECK_EQ(OatClassType::kNoneCompiled, type_);
2254 return nullptr;
2255 }
2256 CHECK_LT(method_index, num_methods_) << oat_file_->GetLocation();
2257 size_t methods_pointer_index;
2258 if (bitmap_ == nullptr) {
2259 CHECK_EQ(OatClassType::kAllCompiled, type_);
2260 methods_pointer_index = method_index;
2261 } else {
2262 CHECK_EQ(OatClassType::kSomeCompiled, type_);
2263 if (!BitVector::IsBitSet(bitmap_, method_index)) {
2264 return nullptr;
2265 }
2266 size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
2267 methods_pointer_index = num_set_bits;
2268 }
2269 if (kIsDebugBuild) {
2270 size_t size_until_end = dchecked_integral_cast<size_t>(
2271 oat_file_->End() - reinterpret_cast<const uint8_t*>(methods_pointer_));
2272 CHECK_LE(methods_pointer_index, size_until_end / sizeof(OatMethodOffsets))
2273 << oat_file_->GetLocation();
2274 }
2275 const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
2276 return &oat_method_offsets;
2277 }
2278
GetOatMethod(uint32_t method_index) const2279 const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
2280 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2281 if (oat_method_offsets == nullptr) {
2282 return OatMethod(nullptr, 0);
2283 }
2284 if (oat_file_->IsExecutable() ||
2285 Runtime::Current() == nullptr || // This case applies for oatdump.
2286 Runtime::Current()->IsAotCompiler()) {
2287 return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
2288 }
2289 // We aren't allowed to use the compiled code. We just force it down the interpreted / jit
2290 // version.
2291 return OatMethod(oat_file_->Begin(), 0);
2292 }
2293
IsDebuggable() const2294 bool OatFile::IsDebuggable() const {
2295 return GetOatHeader().IsDebuggable();
2296 }
2297
GetCompilerFilter() const2298 CompilerFilter::Filter OatFile::GetCompilerFilter() const {
2299 return GetOatHeader().GetCompilerFilter();
2300 }
2301
GetClassLoaderContext() const2302 std::string OatFile::GetClassLoaderContext() const {
2303 return GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
2304 }
2305
GetCompilationReason() const2306 const char* OatFile::GetCompilationReason() const {
2307 return GetOatHeader().GetStoreValueByKey(OatHeader::kCompilationReasonKey);
2308 }
2309
FindOatClass(const DexFile & dex_file,uint16_t class_def_idx,bool * found)2310 OatFile::OatClass OatFile::FindOatClass(const DexFile& dex_file,
2311 uint16_t class_def_idx,
2312 bool* found) {
2313 DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
2314 const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2315 if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
2316 *found = false;
2317 return OatFile::OatClass::Invalid();
2318 }
2319 *found = true;
2320 return oat_dex_file->GetOatClass(class_def_idx);
2321 }
2322
RequiresImage() const2323 bool OatFile::RequiresImage() const { return GetOatHeader().RequiresImage(); }
2324
DCheckIndexToBssMapping(const OatFile * oat_file,uint32_t number_of_indexes,size_t slot_size,const IndexBssMapping * index_bss_mapping)2325 static void DCheckIndexToBssMapping(const OatFile* oat_file,
2326 uint32_t number_of_indexes,
2327 size_t slot_size,
2328 const IndexBssMapping* index_bss_mapping) {
2329 if (kIsDebugBuild && index_bss_mapping != nullptr) {
2330 size_t index_bits = IndexBssMappingEntry::IndexBits(number_of_indexes);
2331 const IndexBssMappingEntry* prev_entry = nullptr;
2332 for (const IndexBssMappingEntry& entry : *index_bss_mapping) {
2333 CHECK_ALIGNED_PARAM(entry.bss_offset, slot_size);
2334 CHECK_LT(entry.bss_offset, oat_file->BssSize());
2335 uint32_t mask = entry.GetMask(index_bits);
2336 CHECK_LE(POPCOUNT(mask) * slot_size, entry.bss_offset);
2337 size_t index_mask_span = (mask != 0u) ? 32u - index_bits - CTZ(mask) : 0u;
2338 CHECK_LE(index_mask_span, entry.GetIndex(index_bits));
2339 if (prev_entry != nullptr) {
2340 CHECK_LT(prev_entry->GetIndex(index_bits), entry.GetIndex(index_bits) - index_mask_span);
2341 }
2342 prev_entry = &entry;
2343 }
2344 CHECK(prev_entry != nullptr);
2345 CHECK_LT(prev_entry->GetIndex(index_bits), number_of_indexes);
2346 }
2347 }
2348
InitializeRelocations() const2349 void OatFile::InitializeRelocations() const {
2350 DCHECK(IsExecutable());
2351
2352 // Initialize the .data.bimg.rel.ro section.
2353 if (!GetBootImageRelocations().empty()) {
2354 uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin());
2355 CheckedCall(mprotect,
2356 "un-protect boot image relocations",
2357 reloc_begin,
2358 DataBimgRelRoSize(),
2359 PROT_READ | PROT_WRITE);
2360 uint32_t boot_image_begin = Runtime::Current()->GetHeap()->GetBootImagesStartAddress();
2361 for (const uint32_t& relocation : GetBootImageRelocations()) {
2362 const_cast<uint32_t&>(relocation) += boot_image_begin;
2363 }
2364 CheckedCall(mprotect,
2365 "protect boot image relocations",
2366 reloc_begin,
2367 DataBimgRelRoSize(),
2368 PROT_READ);
2369 }
2370
2371 // Before initializing .bss, check the .bss mappings in debug mode.
2372 if (kIsDebugBuild) {
2373 PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
2374 for (const OatDexFile* odf : GetOatDexFiles()) {
2375 const DexFile::Header* header =
2376 reinterpret_cast<const DexFile::Header*>(odf->GetDexFilePointer());
2377 DCheckIndexToBssMapping(this,
2378 header->method_ids_size_,
2379 static_cast<size_t>(pointer_size),
2380 odf->GetMethodBssMapping());
2381 DCheckIndexToBssMapping(this,
2382 header->type_ids_size_,
2383 sizeof(GcRoot<mirror::Class>),
2384 odf->GetTypeBssMapping());
2385 DCheckIndexToBssMapping(this,
2386 header->string_ids_size_,
2387 sizeof(GcRoot<mirror::String>),
2388 odf->GetStringBssMapping());
2389 }
2390 }
2391
2392 // Initialize the .bss section.
2393 // TODO: Pre-initialize from boot/app image?
2394 ArtMethod* resolution_method = Runtime::Current()->GetResolutionMethod();
2395 for (ArtMethod*& entry : GetBssMethods()) {
2396 entry = resolution_method;
2397 }
2398 }
2399
AssertAotCompiler()2400 void OatDexFile::AssertAotCompiler() {
2401 CHECK(Runtime::Current()->IsAotCompiler());
2402 }
2403
IsBackedByVdexOnly() const2404 bool OatFile::IsBackedByVdexOnly() const {
2405 return oat_dex_files_storage_.size() >= 1 && oat_dex_files_storage_[0]->IsBackedByVdexOnly();
2406 }
2407
2408 } // namespace art
2409