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 bool Setup(const std::vector<const DexFile*>& dex_files, std::string* error_msg);
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
ComputeAndCheckTypeLookupTableData(const DexFile::Header & header,const uint8_t * type_lookup_table_start,const VdexFile * vdex_file,const uint8_t ** type_lookup_table_data,std::string * error_msg)479 static bool ComputeAndCheckTypeLookupTableData(const DexFile::Header& header,
480 const uint8_t* type_lookup_table_start,
481 const VdexFile* vdex_file,
482 const uint8_t** type_lookup_table_data,
483 std::string* error_msg) {
484 if (type_lookup_table_start == nullptr ||
485 reinterpret_cast<const uint32_t*>(type_lookup_table_start)[0] == 0) {
486 *type_lookup_table_data = nullptr;
487 return true;
488 }
489
490 *type_lookup_table_data = type_lookup_table_start + sizeof(uint32_t);
491 size_t expected_table_size = TypeLookupTable::RawDataLength(header.class_defs_size_);
492 size_t found_size = reinterpret_cast<const uint32_t*>(type_lookup_table_start)[0];
493 if (UNLIKELY(found_size != expected_table_size)) {
494 *error_msg =
495 StringPrintf("In vdex file '%s' unexpected type lookup table size: found %zu, expected %zu",
496 vdex_file->GetName().c_str(),
497 found_size,
498 expected_table_size);
499 return false;
500 }
501 if (UNLIKELY(!vdex_file->Contains(*type_lookup_table_data))) {
502 *error_msg =
503 StringPrintf("In vdex file '%s' found invalid type lookup table pointer %p not in [%p, %p]",
504 vdex_file->GetName().c_str(),
505 type_lookup_table_data,
506 vdex_file->Begin(),
507 vdex_file->End());
508 return false;
509 }
510 if (UNLIKELY(!vdex_file->Contains(*type_lookup_table_data + expected_table_size - 1))) {
511 *error_msg =
512 StringPrintf("In vdex file '%s' found overflowing type lookup table %p not in [%p, %p]",
513 vdex_file->GetName().c_str(),
514 type_lookup_table_data + expected_table_size,
515 vdex_file->Begin(),
516 vdex_file->End());
517 return false;
518 }
519 if (UNLIKELY(!IsAligned<4>(type_lookup_table_start))) {
520 *error_msg =
521 StringPrintf("In vdex file '%s' found invalid type lookup table alignment %p",
522 vdex_file->GetName().c_str(),
523 type_lookup_table_start);
524 return false;
525 }
526 return true;
527 }
528
Setup(const std::vector<const DexFile * > & dex_files,std::string * error_msg)529 bool OatFileBase::Setup(const std::vector<const DexFile*>& dex_files, std::string* error_msg) {
530 uint32_t i = 0;
531 const uint8_t* type_lookup_table_start = nullptr;
532 for (const DexFile* dex_file : dex_files) {
533 std::string dex_location = dex_file->GetLocation();
534 std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location.c_str());
535
536 type_lookup_table_start = vdex_->GetNextTypeLookupTableData(type_lookup_table_start, i++);
537 const uint8_t* type_lookup_table_data = nullptr;
538 if (!ComputeAndCheckTypeLookupTableData(dex_file->GetHeader(),
539 type_lookup_table_start,
540 vdex_.get(),
541 &type_lookup_table_data,
542 error_msg)) {
543 return false;
544 }
545 // Create an OatDexFile and add it to the owning container.
546 OatDexFile* oat_dex_file = new OatDexFile(
547 this,
548 dex_file->Begin(),
549 dex_file->GetLocationChecksum(),
550 dex_location,
551 canonical_location,
552 type_lookup_table_data);
553 oat_dex_files_storage_.push_back(oat_dex_file);
554
555 // Add the location and canonical location (if different) to the oat_dex_files_ table.
556 std::string_view key(oat_dex_file->GetDexFileLocation());
557 oat_dex_files_.Put(key, oat_dex_file);
558 if (canonical_location != dex_location) {
559 std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
560 oat_dex_files_.Put(canonical_key, oat_dex_file);
561 }
562 }
563 // Now that we've created all the OatDexFile, update the dex files.
564 for (i = 0; i < dex_files.size(); ++i) {
565 dex_files[i]->SetOatDexFile(oat_dex_files_storage_[i]);
566 }
567 return true;
568 }
569
Setup(int zip_fd,ArrayRef<const std::string> dex_filenames,std::string * error_msg)570 bool OatFileBase::Setup(int zip_fd,
571 ArrayRef<const std::string> dex_filenames,
572 std::string* error_msg) {
573 if (!GetOatHeader().IsValid()) {
574 std::string cause = GetOatHeader().GetValidationErrorMessage();
575 *error_msg = StringPrintf("Invalid oat header for '%s': %s",
576 GetLocation().c_str(),
577 cause.c_str());
578 return false;
579 }
580 PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
581 size_t key_value_store_size =
582 (Size() >= sizeof(OatHeader)) ? GetOatHeader().GetKeyValueStoreSize() : 0u;
583 if (Size() < sizeof(OatHeader) + key_value_store_size) {
584 *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader, "
585 "size = %zu < %zu + %zu",
586 GetLocation().c_str(),
587 Size(),
588 sizeof(OatHeader),
589 key_value_store_size);
590 return false;
591 }
592
593 size_t oat_dex_files_offset = GetOatHeader().GetOatDexFilesOffset();
594 if (oat_dex_files_offset < GetOatHeader().GetHeaderSize() || oat_dex_files_offset > Size()) {
595 *error_msg = StringPrintf("In oat file '%s' found invalid oat dex files offset: "
596 "%zu is not in [%zu, %zu]",
597 GetLocation().c_str(),
598 oat_dex_files_offset,
599 GetOatHeader().GetHeaderSize(),
600 Size());
601 return false;
602 }
603 const uint8_t* oat = Begin() + oat_dex_files_offset; // Jump to the OatDexFile records.
604
605 if (!IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_begin_) ||
606 !IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_end_) ||
607 data_bimg_rel_ro_begin_ > data_bimg_rel_ro_end_) {
608 *error_msg = StringPrintf("In oat file '%s' found unaligned or unordered databimgrelro "
609 "symbol(s): begin = %p, end = %p",
610 GetLocation().c_str(),
611 data_bimg_rel_ro_begin_,
612 data_bimg_rel_ro_end_);
613 return false;
614 }
615
616 DCHECK_GE(static_cast<size_t>(pointer_size), alignof(GcRoot<mirror::Object>));
617 if (!IsAligned<kPageSize>(bss_begin_) ||
618 !IsAlignedParam(bss_methods_, static_cast<size_t>(pointer_size)) ||
619 !IsAlignedParam(bss_roots_, static_cast<size_t>(pointer_size)) ||
620 !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_end_)) {
621 *error_msg = StringPrintf("In oat file '%s' found unaligned bss symbol(s): "
622 "begin = %p, methods_ = %p, roots = %p, end = %p",
623 GetLocation().c_str(),
624 bss_begin_,
625 bss_methods_,
626 bss_roots_,
627 bss_end_);
628 return false;
629 }
630
631 if ((bss_methods_ != nullptr && (bss_methods_ < bss_begin_ || bss_methods_ > bss_end_)) ||
632 (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) ||
633 (bss_methods_ != nullptr && bss_roots_ != nullptr && bss_methods_ > bss_roots_)) {
634 *error_msg = StringPrintf("In oat file '%s' found bss symbol(s) outside .bss or unordered: "
635 "begin = %p, methods = %p, roots = %p, end = %p",
636 GetLocation().c_str(),
637 bss_begin_,
638 bss_methods_,
639 bss_roots_,
640 bss_end_);
641 return false;
642 }
643
644 if (bss_methods_ != nullptr && bss_methods_ != bss_begin_) {
645 *error_msg = StringPrintf("In oat file '%s' found unexpected .bss gap before 'oatbssmethods': "
646 "begin = %p, methods = %p",
647 GetLocation().c_str(),
648 bss_begin_,
649 bss_methods_);
650 return false;
651 }
652
653 std::string_view primary_location;
654 std::string_view primary_location_replacement;
655 size_t dex_filenames_pos = 0u;
656 uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
657 oat_dex_files_storage_.reserve(dex_file_count);
658 for (size_t i = 0; i < dex_file_count; i++) {
659 uint32_t dex_file_location_size;
660 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
661 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file "
662 "location size",
663 GetLocation().c_str(),
664 i);
665 return false;
666 }
667 if (UNLIKELY(dex_file_location_size == 0U)) {
668 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name",
669 GetLocation().c_str(),
670 i);
671 return false;
672 }
673 if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) {
674 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file "
675 "location",
676 GetLocation().c_str(),
677 i);
678 return false;
679 }
680 const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
681 oat += dex_file_location_size;
682
683 // Location encoded in the oat file. We will use this for multidex naming.
684 std::string_view oat_dex_file_location(dex_file_location_data, dex_file_location_size);
685 std::string dex_file_location(oat_dex_file_location);
686 bool is_multidex = DexFileLoader::IsMultiDexLocation(dex_file_location.c_str());
687 // Check that `is_multidex` does not clash with other indicators. The first dex location
688 // must be primary location and, if we're opening external dex files, the location must
689 // be multi-dex if and only if we already have a dex file opened for it.
690 if ((i == 0 && is_multidex) ||
691 (!external_dex_files_.empty() && (is_multidex != (i < external_dex_files_.size())))) {
692 *error_msg = StringPrintf("In oat file '%s' found unexpected %s location '%s'",
693 GetLocation().c_str(),
694 is_multidex ? "multi-dex" : "primary",
695 dex_file_location.c_str());
696 return false;
697 }
698 // Remember the primary location and, if provided, the replacement from `dex_filenames`.
699 if (!is_multidex) {
700 primary_location = oat_dex_file_location;
701 if (!dex_filenames.empty()) {
702 if (dex_filenames_pos == dex_filenames.size()) {
703 *error_msg = StringPrintf("In oat file '%s' found excessive primary location '%s'"
704 ", expected only %zu primary locations",
705 GetLocation().c_str(),
706 dex_file_location.c_str(),
707 dex_filenames.size());
708 return false;
709 }
710 primary_location_replacement = dex_filenames[dex_filenames_pos];
711 ++dex_filenames_pos;
712 }
713 }
714 // Check that the base location of a multidex location matches the last seen primary location.
715 if (is_multidex &&
716 (!StartsWith(dex_file_location, primary_location) ||
717 dex_file_location[primary_location.size()] != DexFileLoader::kMultiDexSeparator)) {
718 *error_msg = StringPrintf("In oat file '%s' found unexpected multidex location '%s',"
719 " unrelated to '%s'",
720 GetLocation().c_str(),
721 dex_file_location.c_str(),
722 std::string(primary_location).c_str());
723 return false;
724 }
725 std::string dex_file_name = dex_file_location;
726 if (!dex_filenames.empty()) {
727 dex_file_name.replace(/*pos*/ 0u, primary_location.size(), primary_location_replacement);
728 // If the location does not contain path and matches the file name component,
729 // use the provided file name also as the location.
730 // TODO: Do we need this for anything other than tests?
731 if (dex_file_location.find('/') == std::string::npos &&
732 dex_file_name.size() > dex_file_location.size() &&
733 dex_file_name[dex_file_name.size() - dex_file_location.size() - 1u] == '/' &&
734 EndsWith(dex_file_name, dex_file_location)) {
735 dex_file_location = dex_file_name;
736 }
737 }
738
739 uint32_t dex_file_checksum;
740 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
741 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after "
742 "dex file checksum",
743 GetLocation().c_str(),
744 i,
745 dex_file_location.c_str());
746 return false;
747 }
748
749 uint32_t dex_file_offset;
750 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
751 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
752 "after dex file offsets",
753 GetLocation().c_str(),
754 i,
755 dex_file_location.c_str());
756 return false;
757 }
758 if (UNLIKELY(dex_file_offset > DexSize())) {
759 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
760 "offset %u > %zu",
761 GetLocation().c_str(),
762 i,
763 dex_file_location.c_str(),
764 dex_file_offset,
765 DexSize());
766 return false;
767 }
768 const uint8_t* dex_file_pointer = nullptr;
769 if (UNLIKELY(dex_file_offset == 0U)) {
770 // Do not support mixed-mode oat files.
771 if (i != 0u && external_dex_files_.empty()) {
772 *error_msg = StringPrintf("In oat file '%s', unsupported uncompressed-dex-file for dex "
773 "file %zu (%s)",
774 GetLocation().c_str(),
775 i,
776 dex_file_location.c_str());
777 return false;
778 }
779 DCHECK_LE(i, external_dex_files_.size());
780 if (i == external_dex_files_.size()) {
781 std::vector<std::unique_ptr<const DexFile>> new_dex_files;
782 // No dex files, load it from location.
783 const ArtDexFileLoader dex_file_loader;
784 bool loaded = false;
785 if (zip_fd != -1) {
786 loaded = dex_file_loader.OpenZip(zip_fd,
787 dex_file_location,
788 /*verify=*/ false,
789 /*verify_checksum=*/ false,
790 error_msg,
791 &new_dex_files);
792 } else {
793 loaded = dex_file_loader.Open(dex_file_name.c_str(),
794 dex_file_location,
795 /*verify=*/ false,
796 /*verify_checksum=*/ false,
797 error_msg,
798 &new_dex_files);
799 }
800 if (!loaded) {
801 if (Runtime::Current() == nullptr) {
802 // If there's no runtime, we're running oatdump, so return
803 // a half constructed oat file that oatdump knows how to deal with.
804 LOG(WARNING) << "Could not find associated dex files of oat file. "
805 << "Oatdump will only dump the header.";
806 return true;
807 } else {
808 return false;
809 }
810 }
811 // The oat file may be out of date wrt/ the dex-file location. We need to be defensive
812 // here and ensure that at least the number of dex files still matches.
813 // If we have a zip_fd, or reached the end of provided `dex_filenames`, we must
814 // load all dex files from that file, otherwise we may open multiple files.
815 // Note: actual checksum comparisons are the duty of the OatFileAssistant and will be
816 // done after loading the OatFile.
817 size_t max_dex_files = dex_file_count - external_dex_files_.size();
818 bool expect_all =
819 (zip_fd != -1) || (!dex_filenames.empty() && dex_filenames_pos == dex_filenames.size());
820 if (expect_all ? new_dex_files.size() != max_dex_files
821 : new_dex_files.size() > max_dex_files) {
822 *error_msg = StringPrintf("In oat file '%s', expected %s%zu uncompressed dex files, but "
823 "found %zu in '%s'",
824 GetLocation().c_str(),
825 (expect_all ? "" : "<="),
826 max_dex_files,
827 new_dex_files.size(),
828 dex_file_location.c_str());
829 return false;
830 }
831 for (std::unique_ptr<const DexFile>& dex_file : new_dex_files) {
832 external_dex_files_.push_back(std::move(dex_file));
833 }
834 }
835 dex_file_pointer = external_dex_files_[i]->Begin();
836 } else {
837 // Do not support mixed-mode oat files.
838 if (!external_dex_files_.empty()) {
839 *error_msg = StringPrintf("In oat file '%s', unsupported embedded dex-file for dex file "
840 "%zu (%s)",
841 GetLocation().c_str(),
842 i,
843 dex_file_location.c_str());
844 return false;
845 }
846 if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
847 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
848 "offset %u of %zu but the size of dex file header is %zu",
849 GetLocation().c_str(),
850 i,
851 dex_file_location.c_str(),
852 dex_file_offset,
853 DexSize(),
854 sizeof(DexFile::Header));
855 return false;
856 }
857 dex_file_pointer = DexBegin() + dex_file_offset;
858 }
859
860 const bool valid_magic = DexFileLoader::IsMagicValid(dex_file_pointer);
861 if (UNLIKELY(!valid_magic)) {
862 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
863 "dex file magic",
864 GetLocation().c_str(),
865 i,
866 dex_file_location.c_str());
867 return false;
868 }
869 if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_pointer))) {
870 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
871 "dex file version",
872 GetLocation().c_str(),
873 i,
874 dex_file_location.c_str());
875 return false;
876 }
877 const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
878 if (dex_file_offset != 0 && (DexSize() - dex_file_offset < header->file_size_)) {
879 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
880 "offset %u and size %u truncated at %zu",
881 GetLocation().c_str(),
882 i,
883 dex_file_location.c_str(),
884 dex_file_offset,
885 header->file_size_,
886 DexSize());
887 return false;
888 }
889
890 uint32_t class_offsets_offset;
891 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {
892 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
893 "after class offsets offset",
894 GetLocation().c_str(),
895 i,
896 dex_file_location.c_str());
897 return false;
898 }
899 if (UNLIKELY(class_offsets_offset > Size()) ||
900 UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) {
901 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
902 "class offsets, offset %u of %zu, class defs %u",
903 GetLocation().c_str(),
904 i,
905 dex_file_location.c_str(),
906 class_offsets_offset,
907 Size(),
908 header->class_defs_size_);
909 return false;
910 }
911 if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) {
912 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned "
913 "class offsets, offset %u",
914 GetLocation().c_str(),
915 i,
916 dex_file_location.c_str(),
917 class_offsets_offset);
918 return false;
919 }
920 const uint32_t* class_offsets_pointer =
921 reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset);
922
923 uint32_t lookup_table_offset;
924 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {
925 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
926 "after lookup table offset",
927 GetLocation().c_str(),
928 i,
929 dex_file_location.c_str());
930 return false;
931 }
932 const uint8_t* lookup_table_data = lookup_table_offset != 0u
933 ? DexBegin() + lookup_table_offset
934 : nullptr;
935 if (lookup_table_offset != 0u &&
936 (UNLIKELY(lookup_table_offset > DexSize()) ||
937 UNLIKELY(DexSize() - lookup_table_offset <
938 TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
939 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
940 "type lookup table, offset %u of %zu, class defs %u",
941 GetLocation().c_str(),
942 i,
943 dex_file_location.c_str(),
944 lookup_table_offset,
945 Size(),
946 header->class_defs_size_);
947 return false;
948 }
949
950 uint32_t dex_layout_sections_offset;
951 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_layout_sections_offset))) {
952 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
953 "after dex layout sections offset",
954 GetLocation().c_str(),
955 i,
956 dex_file_location.c_str());
957 return false;
958 }
959 const DexLayoutSections* const dex_layout_sections = dex_layout_sections_offset != 0
960 ? reinterpret_cast<const DexLayoutSections*>(Begin() + dex_layout_sections_offset)
961 : nullptr;
962
963 const IndexBssMapping* method_bss_mapping;
964 const IndexBssMapping* type_bss_mapping;
965 const IndexBssMapping* public_type_bss_mapping;
966 const IndexBssMapping* package_type_bss_mapping;
967 const IndexBssMapping* string_bss_mapping;
968 if (!ReadIndexBssMapping(
969 this, &oat, i, dex_file_location, "method", &method_bss_mapping, error_msg) ||
970 !ReadIndexBssMapping(
971 this, &oat, i, dex_file_location, "type", &type_bss_mapping, error_msg) ||
972 !ReadIndexBssMapping(
973 this, &oat, i, dex_file_location, "type", &public_type_bss_mapping, error_msg) ||
974 !ReadIndexBssMapping(
975 this, &oat, i, dex_file_location, "type", &package_type_bss_mapping, error_msg) ||
976 !ReadIndexBssMapping(
977 this, &oat, i, dex_file_location, "string", &string_bss_mapping, error_msg)) {
978 return false;
979 }
980
981 // Create the OatDexFile and add it to the owning container.
982 OatDexFile* oat_dex_file = new OatDexFile(
983 this,
984 dex_file_location,
985 DexFileLoader::GetDexCanonicalLocation(dex_file_name.c_str()),
986 dex_file_checksum,
987 dex_file_pointer,
988 lookup_table_data,
989 method_bss_mapping,
990 type_bss_mapping,
991 public_type_bss_mapping,
992 package_type_bss_mapping,
993 string_bss_mapping,
994 class_offsets_pointer,
995 dex_layout_sections);
996 oat_dex_files_storage_.push_back(oat_dex_file);
997
998 // Add the location and canonical location (if different) to the oat_dex_files_ table.
999 // Note: We do not add the non-canonical `dex_file_name`. If it is different from both
1000 // the location and canonical location, GetOatDexFile() shall canonicalize it when
1001 // requested and match the canonical path.
1002 std::string_view key = oat_dex_file_location; // References oat file data.
1003 std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
1004 oat_dex_files_.Put(key, oat_dex_file);
1005 if (canonical_key != key) {
1006 oat_dex_files_.Put(canonical_key, oat_dex_file);
1007 }
1008 }
1009 if (!dex_filenames.empty() && dex_filenames_pos != dex_filenames.size()) {
1010 *error_msg = StringPrintf("Oat file '%s' contains only %zu primary dex locations, expected %zu",
1011 GetLocation().c_str(),
1012 dex_filenames_pos,
1013 dex_filenames.size());
1014 return false;
1015 }
1016
1017 if (DataBimgRelRoBegin() != nullptr) {
1018 // Make .data.bimg.rel.ro read only. ClassLinker shall temporarily make it writable for
1019 // relocation when we register a dex file from this oat file. We do not do the relocation
1020 // here to avoid dirtying the pages if the code is never actually ready to be executed.
1021 uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin());
1022 CheckedCall(mprotect, "protect relocations", reloc_begin, DataBimgRelRoSize(), PROT_READ);
1023 // Make sure the file lists a boot image dependency, otherwise the .data.bimg.rel.ro
1024 // section is bogus. The full dependency is checked before the code is executed.
1025 // We cannot do this check if we do not have a key-value store, i.e. for secondary
1026 // oat files for boot image extensions.
1027 if (GetOatHeader().GetKeyValueStoreSize() != 0u) {
1028 const char* boot_class_path_checksum =
1029 GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey);
1030 if (boot_class_path_checksum == nullptr ||
1031 boot_class_path_checksum[0] != gc::space::ImageSpace::kImageChecksumPrefix) {
1032 *error_msg = StringPrintf("Oat file '%s' contains .data.bimg.rel.ro section "
1033 "without boot image dependency.",
1034 GetLocation().c_str());
1035 return false;
1036 }
1037 }
1038 }
1039
1040 return true;
1041 }
1042
1043 ////////////////////////
1044 // OatFile via dlopen //
1045 ////////////////////////
1046
1047 class DlOpenOatFile final : public OatFileBase {
1048 public:
DlOpenOatFile(const std::string & filename,bool executable)1049 DlOpenOatFile(const std::string& filename, bool executable)
1050 : OatFileBase(filename, executable),
1051 dlopen_handle_(nullptr),
1052 shared_objects_before_(0) {
1053 }
1054
~DlOpenOatFile()1055 ~DlOpenOatFile() {
1056 if (dlopen_handle_ != nullptr) {
1057 if (!kIsTargetBuild) {
1058 MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
1059 host_dlopen_handles_.erase(dlopen_handle_);
1060 dlclose(dlopen_handle_);
1061 } else {
1062 dlclose(dlopen_handle_);
1063 }
1064 }
1065 }
1066
1067 protected:
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const1068 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
1069 std::string* error_msg) const override {
1070 const uint8_t* ptr =
1071 reinterpret_cast<const uint8_t*>(dlsym(dlopen_handle_, symbol_name.c_str()));
1072 if (ptr == nullptr) {
1073 *error_msg = dlerror();
1074 }
1075 return ptr;
1076 }
1077
1078 void PreLoad() override;
1079
1080 bool Load(const std::string& elf_filename,
1081 bool writable,
1082 bool executable,
1083 bool low_4gb,
1084 /*inout*/MemMap* reservation, // Where to load if not null.
1085 /*out*/std::string* error_msg) override;
1086
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)1087 bool Load(int oat_fd ATTRIBUTE_UNUSED,
1088 bool writable ATTRIBUTE_UNUSED,
1089 bool executable ATTRIBUTE_UNUSED,
1090 bool low_4gb ATTRIBUTE_UNUSED,
1091 /*inout*/MemMap* reservation ATTRIBUTE_UNUSED,
1092 /*out*/std::string* error_msg ATTRIBUTE_UNUSED) override {
1093 return false;
1094 }
1095
1096 // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
1097 void PreSetup(const std::string& elf_filename) override;
1098
1099 private:
1100 bool Dlopen(const std::string& elf_filename,
1101 /*inout*/MemMap* reservation, // Where to load if not null.
1102 /*out*/std::string* error_msg);
1103
1104 // On the host, if the same library is loaded again with dlopen the same
1105 // file handle is returned. This differs from the behavior of dlopen on the
1106 // target, where dlopen reloads the library at a different address every
1107 // time you load it. The runtime relies on the target behavior to ensure
1108 // each instance of the loaded library has a unique dex cache. To avoid
1109 // problems, we fall back to our own linker in the case when the same
1110 // library is opened multiple times on host. dlopen_handles_ is used to
1111 // detect that case.
1112 // Guarded by host_dlopen_handles_lock_;
1113 static std::unordered_set<void*> host_dlopen_handles_;
1114
1115 // Reservation and placeholder memory map objects corresponding to the regions mapped by dlopen.
1116 // Note: Must be destroyed after dlclose() as it can hold the owning reservation.
1117 std::vector<MemMap> dlopen_mmaps_;
1118
1119 // dlopen handle during runtime.
1120 void* dlopen_handle_; // TODO: Unique_ptr with custom deleter.
1121
1122 // The number of shared objects the linker told us about before loading. Used to
1123 // (optimistically) optimize the PreSetup stage (see comment there).
1124 size_t shared_objects_before_;
1125
1126 DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile);
1127 };
1128
1129 std::unordered_set<void*> DlOpenOatFile::host_dlopen_handles_;
1130
PreLoad()1131 void DlOpenOatFile::PreLoad() {
1132 #ifdef __APPLE__
1133 UNUSED(shared_objects_before_);
1134 LOG(FATAL) << "Should not reach here.";
1135 UNREACHABLE();
1136 #else
1137 // Count the entries in dl_iterate_phdr we get at this point in time.
1138 struct dl_iterate_context {
1139 static int callback(dl_phdr_info* info ATTRIBUTE_UNUSED,
1140 size_t size ATTRIBUTE_UNUSED,
1141 void* data) {
1142 reinterpret_cast<dl_iterate_context*>(data)->count++;
1143 return 0; // Continue iteration.
1144 }
1145 size_t count = 0;
1146 } context;
1147
1148 dl_iterate_phdr(dl_iterate_context::callback, &context);
1149 shared_objects_before_ = context.count;
1150 #endif
1151 }
1152
Load(const std::string & elf_filename,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1153 bool DlOpenOatFile::Load(const std::string& elf_filename,
1154 bool writable,
1155 bool executable,
1156 bool low_4gb,
1157 /*inout*/MemMap* reservation, // Where to load if not null.
1158 /*out*/std::string* error_msg) {
1159 // Use dlopen only when flagged to do so, and when it's OK to load things executable.
1160 // TODO: Also try when not executable? The issue here could be re-mapping as writable (as
1161 // !executable is a sign that we may want to patch), which may not be allowed for
1162 // various reasons.
1163 if (!kUseDlopen) {
1164 *error_msg = "DlOpen is disabled.";
1165 return false;
1166 }
1167 if (low_4gb) {
1168 *error_msg = "DlOpen does not support low 4gb loading.";
1169 return false;
1170 }
1171 if (writable) {
1172 *error_msg = "DlOpen does not support writable loading.";
1173 return false;
1174 }
1175 if (!executable) {
1176 *error_msg = "DlOpen does not support non-executable loading.";
1177 return false;
1178 }
1179
1180 // dlopen always returns the same library if it is already opened on the host. For this reason
1181 // we only use dlopen if we are the target or we do not already have the dex file opened. Having
1182 // the same library loaded multiple times at different addresses is required for class unloading
1183 // and for having dex caches arrays in the .bss section.
1184 if (!kIsTargetBuild) {
1185 if (!kUseDlopenOnHost) {
1186 *error_msg = "DlOpen disabled for host.";
1187 return false;
1188 }
1189 }
1190
1191 bool success = Dlopen(elf_filename, reservation, error_msg);
1192 DCHECK(dlopen_handle_ != nullptr || !success);
1193
1194 return success;
1195 }
1196
1197 #ifdef ART_TARGET_ANDROID
GetSystemLinkerNamespace()1198 static struct android_namespace_t* GetSystemLinkerNamespace() {
1199 static struct android_namespace_t* system_ns = []() {
1200 // The system namespace is called "default" for binaries in /system and
1201 // "system" for those in the ART APEX. Try "system" first since "default"
1202 // always exists.
1203 // TODO(b/185587109): Get rid of this error prone logic.
1204 struct android_namespace_t* ns = android_get_exported_namespace("system");
1205 if (ns == nullptr) {
1206 ns = android_get_exported_namespace("default");
1207 if (ns == nullptr) {
1208 LOG(FATAL) << "Failed to get system namespace for loading OAT files";
1209 }
1210 }
1211 return ns;
1212 }();
1213 return system_ns;
1214 }
1215 #endif // ART_TARGET_ANDROID
1216
Dlopen(const std::string & elf_filename,MemMap * reservation,std::string * error_msg)1217 bool DlOpenOatFile::Dlopen(const std::string& elf_filename,
1218 /*inout*/MemMap* reservation,
1219 /*out*/std::string* error_msg) {
1220 #ifdef __APPLE__
1221 // The dl_iterate_phdr syscall is missing. There is similar API on OSX,
1222 // but let's fallback to the custom loading code for the time being.
1223 UNUSED(elf_filename, reservation);
1224 *error_msg = "Dlopen unsupported on Mac.";
1225 return false;
1226 #else
1227 {
1228 UniqueCPtr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
1229 if (absolute_path == nullptr) {
1230 *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
1231 return false;
1232 }
1233 #ifdef ART_TARGET_ANDROID
1234 android_dlextinfo extinfo = {};
1235 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD; // Force-load, don't reuse handle
1236 // (open oat files multiple times).
1237 if (reservation != nullptr) {
1238 if (!reservation->IsValid()) {
1239 *error_msg = StringPrintf("Invalid reservation for %s", elf_filename.c_str());
1240 return false;
1241 }
1242 extinfo.flags |= ANDROID_DLEXT_RESERVED_ADDRESS; // Use the reserved memory range.
1243 extinfo.reserved_addr = reservation->Begin();
1244 extinfo.reserved_size = reservation->Size();
1245 }
1246
1247 if (strncmp(kAndroidArtApexDefaultPath,
1248 absolute_path.get(),
1249 sizeof(kAndroidArtApexDefaultPath) - 1) != 0 ||
1250 absolute_path.get()[sizeof(kAndroidArtApexDefaultPath) - 1] != '/') {
1251 // Use the system namespace for OAT files outside the ART APEX. Search
1252 // paths and links don't matter here, but permitted paths do, and the
1253 // system namespace is configured to allow loading from all appropriate
1254 // locations.
1255 extinfo.flags |= ANDROID_DLEXT_USE_NAMESPACE;
1256 extinfo.library_namespace = GetSystemLinkerNamespace();
1257 }
1258
1259 dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
1260 if (reservation != nullptr && dlopen_handle_ != nullptr) {
1261 // Find used pages from the reservation.
1262 struct dl_iterate_context {
1263 static int callback(dl_phdr_info* info, size_t size ATTRIBUTE_UNUSED, void* data) {
1264 auto* context = reinterpret_cast<dl_iterate_context*>(data);
1265 static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1266 using Elf_Half = Elf64_Half;
1267
1268 // See whether this callback corresponds to the file which we have just loaded.
1269 uint8_t* reservation_begin = context->reservation->Begin();
1270 bool contained_in_reservation = false;
1271 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1272 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1273 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1274 info->dlpi_phdr[i].p_vaddr);
1275 size_t memsz = info->dlpi_phdr[i].p_memsz;
1276 size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1277 if (offset < context->reservation->Size()) {
1278 contained_in_reservation = true;
1279 DCHECK_LE(memsz, context->reservation->Size() - offset);
1280 } else if (vaddr < reservation_begin) {
1281 // Check that there's no overlap with the reservation.
1282 DCHECK_LE(memsz, static_cast<size_t>(reservation_begin - vaddr));
1283 }
1284 break; // It is sufficient to check the first PT_LOAD header.
1285 }
1286 }
1287
1288 if (contained_in_reservation) {
1289 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1290 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1291 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1292 info->dlpi_phdr[i].p_vaddr);
1293 size_t memsz = info->dlpi_phdr[i].p_memsz;
1294 size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1295 DCHECK_LT(offset, context->reservation->Size());
1296 DCHECK_LE(memsz, context->reservation->Size() - offset);
1297 context->max_size = std::max(context->max_size, offset + memsz);
1298 }
1299 }
1300
1301 return 1; // Stop iteration and return 1 from dl_iterate_phdr.
1302 }
1303 return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished.
1304 }
1305
1306 const MemMap* const reservation;
1307 size_t max_size = 0u;
1308 };
1309 dl_iterate_context context = { reservation };
1310
1311 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1312 LOG(FATAL) << "Could not find the shared object mmapped to the reservation.";
1313 UNREACHABLE();
1314 }
1315
1316 // Take ownership of the memory used by the shared object. dlopen() does not assume
1317 // full ownership of this memory and dlclose() shall just remap it as zero pages with
1318 // PROT_NONE. We need to unmap the memory when destroying this oat file.
1319 dlopen_mmaps_.push_back(reservation->TakeReservedMemory(context.max_size));
1320 }
1321 #else
1322 static_assert(!kIsTargetBuild || kIsTargetLinux || kIsTargetFuchsia,
1323 "host_dlopen_handles_ will leak handles");
1324 if (reservation != nullptr) {
1325 *error_msg = StringPrintf("dlopen() into reserved memory is unsupported on host for '%s'.",
1326 elf_filename.c_str());
1327 return false;
1328 }
1329 MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
1330 dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
1331 if (dlopen_handle_ != nullptr) {
1332 if (!host_dlopen_handles_.insert(dlopen_handle_).second) {
1333 dlclose(dlopen_handle_);
1334 dlopen_handle_ = nullptr;
1335 *error_msg = StringPrintf("host dlopen re-opened '%s'", elf_filename.c_str());
1336 return false;
1337 }
1338 }
1339 #endif // ART_TARGET_ANDROID
1340 }
1341 if (dlopen_handle_ == nullptr) {
1342 *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
1343 return false;
1344 }
1345 return true;
1346 #endif
1347 }
1348
PreSetup(const std::string & elf_filename)1349 void DlOpenOatFile::PreSetup(const std::string& elf_filename) {
1350 #ifdef __APPLE__
1351 UNUSED(elf_filename);
1352 LOG(FATAL) << "Should not reach here.";
1353 UNREACHABLE();
1354 #else
1355 struct PlaceholderMapData {
1356 const char* name;
1357 uint8_t* vaddr;
1358 size_t memsz;
1359 };
1360 struct dl_iterate_context {
1361 static int callback(dl_phdr_info* info, size_t size ATTRIBUTE_UNUSED, void* data) {
1362 auto* context = reinterpret_cast<dl_iterate_context*>(data);
1363 static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1364 using Elf_Half = Elf64_Half;
1365
1366 context->shared_objects_seen++;
1367 if (context->shared_objects_seen < context->shared_objects_before) {
1368 // We haven't been called yet for anything we haven't seen before. Just continue.
1369 // Note: this is aggressively optimistic. If another thread was unloading a library,
1370 // we may miss out here. However, this does not happen often in practice.
1371 return 0;
1372 }
1373
1374 // See whether this callback corresponds to the file which we have just loaded.
1375 bool contains_begin = false;
1376 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1377 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1378 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1379 info->dlpi_phdr[i].p_vaddr);
1380 size_t memsz = info->dlpi_phdr[i].p_memsz;
1381 if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
1382 contains_begin = true;
1383 break;
1384 }
1385 }
1386 }
1387 // Add placeholder mmaps for this file.
1388 if (contains_begin) {
1389 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1390 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1391 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1392 info->dlpi_phdr[i].p_vaddr);
1393 size_t memsz = info->dlpi_phdr[i].p_memsz;
1394 size_t name_size = strlen(info->dlpi_name) + 1u;
1395 std::vector<char>* placeholder_maps_names = context->placeholder_maps_names_;
1396 // We must not allocate any memory in the callback, see b/156312036 .
1397 if (name_size < placeholder_maps_names->capacity() - placeholder_maps_names->size() &&
1398 context->placeholder_maps_data_->size() <
1399 context->placeholder_maps_data_->capacity()) {
1400 placeholder_maps_names->insert(
1401 placeholder_maps_names->end(), info->dlpi_name, info->dlpi_name + name_size);
1402 const char* name =
1403 &(*placeholder_maps_names)[placeholder_maps_names->size() - name_size];
1404 context->placeholder_maps_data_->push_back({ name, vaddr, memsz });
1405 }
1406 context->num_placeholder_maps_ += 1u;
1407 context->placeholder_maps_names_size_ += name_size;
1408 }
1409 }
1410 return 1; // Stop iteration and return 1 from dl_iterate_phdr.
1411 }
1412 return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished.
1413 }
1414 const uint8_t* const begin_;
1415 std::vector<PlaceholderMapData>* placeholder_maps_data_;
1416 size_t num_placeholder_maps_;
1417 std::vector<char>* placeholder_maps_names_;
1418 size_t placeholder_maps_names_size_;
1419 size_t shared_objects_before;
1420 size_t shared_objects_seen;
1421 };
1422
1423 // We must not allocate any memory in the callback, see b/156312036 .
1424 // Therefore we pre-allocate storage for the data we need for creating the placeholder maps.
1425 std::vector<PlaceholderMapData> placeholder_maps_data;
1426 placeholder_maps_data.reserve(32); // 32 should be enough. If not, we'll retry.
1427 std::vector<char> placeholder_maps_names;
1428 placeholder_maps_names.reserve(4 * KB); // 4KiB should be enough. If not, we'll retry.
1429
1430 dl_iterate_context context = {
1431 Begin(),
1432 &placeholder_maps_data,
1433 /*num_placeholder_maps_*/ 0u,
1434 &placeholder_maps_names,
1435 /*placeholder_maps_names_size_*/ 0u,
1436 shared_objects_before_,
1437 /*shared_objects_seen*/ 0u
1438 };
1439
1440 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1441 // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0
1442 // before giving up. This should be unusual.
1443 VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before="
1444 << shared_objects_before_;
1445 DCHECK(placeholder_maps_data.empty());
1446 DCHECK_EQ(context.num_placeholder_maps_, 0u);
1447 DCHECK(placeholder_maps_names.empty());
1448 DCHECK_EQ(context.placeholder_maps_names_size_, 0u);
1449 context.shared_objects_before = 0u;
1450 context.shared_objects_seen = 0u;
1451 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1452 // OK, give up and print an error.
1453 PrintFileToLog("/proc/self/maps", android::base::LogSeverity::WARNING);
1454 LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps.";
1455 }
1456 }
1457
1458 if (placeholder_maps_data.size() < context.num_placeholder_maps_) {
1459 // Insufficient capacity. Reserve more space and retry.
1460 placeholder_maps_data.clear();
1461 placeholder_maps_data.reserve(context.num_placeholder_maps_);
1462 context.num_placeholder_maps_ = 0u;
1463 placeholder_maps_names.clear();
1464 placeholder_maps_names.reserve(context.placeholder_maps_names_size_);
1465 context.placeholder_maps_names_size_ = 0u;
1466 context.shared_objects_before = 0u;
1467 context.shared_objects_seen = 0u;
1468 bool success = (dl_iterate_phdr(dl_iterate_context::callback, &context) != 0);
1469 CHECK(success);
1470 }
1471
1472 CHECK_EQ(placeholder_maps_data.size(), context.num_placeholder_maps_);
1473 CHECK_EQ(placeholder_maps_names.size(), context.placeholder_maps_names_size_);
1474 DCHECK_EQ(static_cast<size_t>(std::count(placeholder_maps_names.begin(),
1475 placeholder_maps_names.end(), '\0')),
1476 context.num_placeholder_maps_);
1477 for (const PlaceholderMapData& data : placeholder_maps_data) {
1478 MemMap mmap = MemMap::MapPlaceholder(data.name, data.vaddr, data.memsz);
1479 dlopen_mmaps_.push_back(std::move(mmap));
1480 }
1481 #endif
1482 }
1483
1484 ////////////////////////////////////////////////
1485 // OatFile via our own ElfFile implementation //
1486 ////////////////////////////////////////////////
1487
1488 class ElfOatFile final : public OatFileBase {
1489 public:
ElfOatFile(const std::string & filename,bool executable)1490 ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {}
1491
1492 bool InitializeFromElfFile(int zip_fd,
1493 ElfFile* elf_file,
1494 VdexFile* vdex_file,
1495 ArrayRef<const std::string> dex_filenames,
1496 std::string* error_msg);
1497
1498 protected:
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const1499 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
1500 std::string* error_msg) const override {
1501 const uint8_t* ptr = elf_file_->FindDynamicSymbolAddress(symbol_name);
1502 if (ptr == nullptr) {
1503 *error_msg = "(Internal implementation could not find symbol)";
1504 }
1505 return ptr;
1506 }
1507
PreLoad()1508 void PreLoad() override {
1509 }
1510
1511 bool Load(const std::string& elf_filename,
1512 bool writable,
1513 bool executable,
1514 bool low_4gb,
1515 /*inout*/MemMap* reservation, // Where to load if not null.
1516 /*out*/std::string* error_msg) override;
1517
1518 bool Load(int oat_fd,
1519 bool writable,
1520 bool executable,
1521 bool low_4gb,
1522 /*inout*/MemMap* reservation, // Where to load if not null.
1523 /*out*/std::string* error_msg) override;
1524
PreSetup(const std::string & elf_filename ATTRIBUTE_UNUSED)1525 void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) override {
1526 }
1527
1528 private:
1529 bool ElfFileOpen(File* file,
1530 bool writable,
1531 bool executable,
1532 bool low_4gb,
1533 /*inout*/MemMap* reservation, // Where to load if not null.
1534 /*out*/std::string* error_msg);
1535
1536 private:
1537 // Backing memory map for oat file during cross compilation.
1538 std::unique_ptr<ElfFile> elf_file_;
1539
1540 DISALLOW_COPY_AND_ASSIGN(ElfOatFile);
1541 };
1542
InitializeFromElfFile(int zip_fd,ElfFile * elf_file,VdexFile * vdex_file,ArrayRef<const std::string> dex_filenames,std::string * error_msg)1543 bool ElfOatFile::InitializeFromElfFile(int zip_fd,
1544 ElfFile* elf_file,
1545 VdexFile* vdex_file,
1546 ArrayRef<const std::string> dex_filenames,
1547 std::string* error_msg) {
1548 ScopedTrace trace(__PRETTY_FUNCTION__);
1549 if (IsExecutable()) {
1550 *error_msg = "Cannot initialize from elf file in executable mode.";
1551 return false;
1552 }
1553 elf_file_.reset(elf_file);
1554 SetVdex(vdex_file);
1555 uint64_t offset, size;
1556 bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
1557 CHECK(has_section);
1558 SetBegin(elf_file->Begin() + offset);
1559 SetEnd(elf_file->Begin() + size + offset);
1560 // Ignore the optional .bss section when opening non-executable.
1561 return Setup(zip_fd, dex_filenames, error_msg);
1562 }
1563
Load(const std::string & elf_filename,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1564 bool ElfOatFile::Load(const std::string& elf_filename,
1565 bool writable,
1566 bool executable,
1567 bool low_4gb,
1568 /*inout*/MemMap* reservation,
1569 /*out*/std::string* error_msg) {
1570 ScopedTrace trace(__PRETTY_FUNCTION__);
1571 std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
1572 if (file == nullptr) {
1573 *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
1574 return false;
1575 }
1576 return ElfOatFile::ElfFileOpen(file.get(),
1577 writable,
1578 executable,
1579 low_4gb,
1580 reservation,
1581 error_msg);
1582 }
1583
Load(int oat_fd,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1584 bool ElfOatFile::Load(int oat_fd,
1585 bool writable,
1586 bool executable,
1587 bool low_4gb,
1588 /*inout*/MemMap* reservation,
1589 /*out*/std::string* error_msg) {
1590 ScopedTrace trace(__PRETTY_FUNCTION__);
1591 if (oat_fd != -1) {
1592 int duped_fd = DupCloexec(oat_fd);
1593 std::unique_ptr<File> file = std::make_unique<File>(duped_fd, false);
1594 if (file == nullptr) {
1595 *error_msg = StringPrintf("Failed to open oat filename for reading: %s",
1596 strerror(errno));
1597 return false;
1598 }
1599 return ElfOatFile::ElfFileOpen(file.get(),
1600 writable,
1601 executable,
1602 low_4gb,
1603 reservation,
1604 error_msg);
1605 }
1606 return false;
1607 }
1608
ElfFileOpen(File * file,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1609 bool ElfOatFile::ElfFileOpen(File* file,
1610 bool writable,
1611 bool executable,
1612 bool low_4gb,
1613 /*inout*/MemMap* reservation,
1614 /*out*/std::string* error_msg) {
1615 ScopedTrace trace(__PRETTY_FUNCTION__);
1616 elf_file_.reset(ElfFile::Open(file,
1617 writable,
1618 /*program_header_only=*/ true,
1619 low_4gb,
1620 error_msg));
1621 if (elf_file_ == nullptr) {
1622 DCHECK(!error_msg->empty());
1623 return false;
1624 }
1625 bool loaded = elf_file_->Load(file, executable, low_4gb, reservation, error_msg);
1626 DCHECK(loaded || !error_msg->empty());
1627 return loaded;
1628 }
1629
1630 class OatFileBackedByVdex final : public OatFileBase {
1631 public:
OatFileBackedByVdex(const std::string & filename)1632 explicit OatFileBackedByVdex(const std::string& filename)
1633 : OatFileBase(filename, /*executable=*/ false) {}
1634
Open(const std::vector<const DexFile * > & dex_files,std::unique_ptr<VdexFile> && vdex_file,const std::string & location)1635 static OatFileBackedByVdex* Open(const std::vector<const DexFile*>& dex_files,
1636 std::unique_ptr<VdexFile>&& vdex_file,
1637 const std::string& location) {
1638 std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(location));
1639 // SetVdex will take ownership of the VdexFile.
1640 oat_file->SetVdex(vdex_file.release());
1641 oat_file->SetupHeader(dex_files.size());
1642 // Initialize OatDexFiles.
1643 std::string error_msg;
1644 if (!oat_file->Setup(dex_files, &error_msg)) {
1645 LOG(WARNING) << "Could not create in-memory vdex file: " << error_msg;
1646 return nullptr;
1647 }
1648 return oat_file.release();
1649 }
1650
Open(int zip_fd,std::unique_ptr<VdexFile> && unique_vdex_file,const std::string & dex_location,std::string * error_msg)1651 static OatFileBackedByVdex* Open(int zip_fd,
1652 std::unique_ptr<VdexFile>&& unique_vdex_file,
1653 const std::string& dex_location,
1654 std::string* error_msg) {
1655 VdexFile* vdex_file = unique_vdex_file.get();
1656 std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(vdex_file->GetName()));
1657 // SetVdex will take ownership of the VdexFile.
1658 oat_file->SetVdex(unique_vdex_file.release());
1659 if (vdex_file->HasDexSection()) {
1660 uint32_t i = 0;
1661 const uint8_t* type_lookup_table_start = nullptr;
1662 for (const uint8_t* dex_file_start = vdex_file->GetNextDexFileData(nullptr, i);
1663 dex_file_start != nullptr;
1664 dex_file_start = vdex_file->GetNextDexFileData(dex_file_start, ++i)) {
1665 const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_start);
1666 if (UNLIKELY(!vdex_file->Contains(dex_file_start))) {
1667 *error_msg =
1668 StringPrintf("In vdex file '%s' found invalid dex file pointer %p not in [%p, %p]",
1669 dex_location.c_str(),
1670 dex_file_start,
1671 vdex_file->Begin(),
1672 vdex_file->End());
1673 return nullptr;
1674 }
1675 if (UNLIKELY(!vdex_file->Contains(dex_file_start + header->file_size_ - 1))) {
1676 *error_msg =
1677 StringPrintf("In vdex file '%s' found overflowing dex file %p not in [%p, %p]",
1678 dex_location.c_str(),
1679 dex_file_start + header->file_size_,
1680 vdex_file->Begin(),
1681 vdex_file->End());
1682 return nullptr;
1683 }
1684 if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_start))) {
1685 *error_msg =
1686 StringPrintf("In vdex file '%s' found dex file with invalid dex file version",
1687 dex_location.c_str());
1688 return nullptr;
1689 }
1690 // Create the OatDexFile and add it to the owning container.
1691 std::string location = DexFileLoader::GetMultiDexLocation(i, dex_location.c_str());
1692 std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(location.c_str());
1693 type_lookup_table_start = vdex_file->GetNextTypeLookupTableData(type_lookup_table_start, i);
1694 const uint8_t* type_lookup_table_data = nullptr;
1695 if (!ComputeAndCheckTypeLookupTableData(*header,
1696 type_lookup_table_start,
1697 vdex_file,
1698 &type_lookup_table_data,
1699 error_msg)) {
1700 return nullptr;
1701 }
1702
1703 OatDexFile* oat_dex_file = new OatDexFile(oat_file.get(),
1704 dex_file_start,
1705 vdex_file->GetLocationChecksum(i),
1706 location,
1707 canonical_location,
1708 type_lookup_table_data);
1709 oat_file->oat_dex_files_storage_.push_back(oat_dex_file);
1710
1711 std::string_view key(oat_dex_file->GetDexFileLocation());
1712 oat_file->oat_dex_files_.Put(key, oat_dex_file);
1713 if (canonical_location != location) {
1714 std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
1715 oat_file->oat_dex_files_.Put(canonical_key, oat_dex_file);
1716 }
1717 }
1718 oat_file->SetupHeader(oat_file->oat_dex_files_storage_.size());
1719 } else {
1720 // No need for any verification when loading dex files as we already have
1721 // a vdex file.
1722 const ArtDexFileLoader dex_file_loader;
1723 bool loaded = false;
1724 if (zip_fd != -1) {
1725 loaded = dex_file_loader.OpenZip(zip_fd,
1726 dex_location,
1727 /*verify=*/ false,
1728 /*verify_checksum=*/ false,
1729 error_msg,
1730 &oat_file->external_dex_files_);
1731 } else {
1732 loaded = dex_file_loader.Open(dex_location.c_str(),
1733 dex_location,
1734 /*verify=*/ false,
1735 /*verify_checksum=*/ false,
1736 error_msg,
1737 &oat_file->external_dex_files_);
1738 }
1739 if (!loaded) {
1740 return nullptr;
1741 }
1742 oat_file->SetupHeader(oat_file->external_dex_files_.size());
1743 if (!oat_file->Setup(MakeNonOwningPointerVector(oat_file->external_dex_files_), error_msg)) {
1744 return nullptr;
1745 }
1746 }
1747
1748 return oat_file.release();
1749 }
1750
SetupHeader(size_t number_of_dex_files)1751 void SetupHeader(size_t number_of_dex_files) {
1752 DCHECK(!IsExecutable());
1753
1754 // Create a fake OatHeader with a key store to help debugging.
1755 std::unique_ptr<const InstructionSetFeatures> isa_features =
1756 InstructionSetFeatures::FromCppDefines();
1757 SafeMap<std::string, std::string> store;
1758 store.Put(OatHeader::kCompilerFilter, CompilerFilter::NameOfFilter(CompilerFilter::kVerify));
1759 store.Put(OatHeader::kCompilationReasonKey, "vdex");
1760 store.Put(OatHeader::kConcurrentCopying,
1761 kUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
1762 oat_header_.reset(OatHeader::Create(kRuntimeISA,
1763 isa_features.get(),
1764 number_of_dex_files,
1765 &store));
1766 const uint8_t* begin = reinterpret_cast<const uint8_t*>(oat_header_.get());
1767 SetBegin(begin);
1768 SetEnd(begin + oat_header_->GetHeaderSize());
1769 }
1770
1771 protected:
PreLoad()1772 void PreLoad() override {}
1773
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)1774 bool Load(const std::string& elf_filename ATTRIBUTE_UNUSED,
1775 bool writable ATTRIBUTE_UNUSED,
1776 bool executable ATTRIBUTE_UNUSED,
1777 bool low_4gb ATTRIBUTE_UNUSED,
1778 MemMap* reservation ATTRIBUTE_UNUSED,
1779 std::string* error_msg ATTRIBUTE_UNUSED) override {
1780 LOG(FATAL) << "Unsupported";
1781 UNREACHABLE();
1782 }
1783
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)1784 bool Load(int oat_fd ATTRIBUTE_UNUSED,
1785 bool writable ATTRIBUTE_UNUSED,
1786 bool executable ATTRIBUTE_UNUSED,
1787 bool low_4gb ATTRIBUTE_UNUSED,
1788 MemMap* reservation ATTRIBUTE_UNUSED,
1789 std::string* error_msg ATTRIBUTE_UNUSED) override {
1790 LOG(FATAL) << "Unsupported";
1791 UNREACHABLE();
1792 }
1793
PreSetup(const std::string & elf_filename ATTRIBUTE_UNUSED)1794 void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) override {}
1795
FindDynamicSymbolAddress(const std::string & symbol_name ATTRIBUTE_UNUSED,std::string * error_msg) const1796 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name ATTRIBUTE_UNUSED,
1797 std::string* error_msg) const override {
1798 *error_msg = "Unsupported";
1799 return nullptr;
1800 }
1801
1802 private:
1803 std::unique_ptr<OatHeader> oat_header_;
1804
1805 DISALLOW_COPY_AND_ASSIGN(OatFileBackedByVdex);
1806 };
1807
1808 //////////////////////////
1809 // General OatFile code //
1810 //////////////////////////
1811
CheckLocation(const std::string & location)1812 static void CheckLocation(const std::string& location) {
1813 CHECK(!location.empty());
1814 }
1815
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)1816 OatFile* OatFile::Open(int zip_fd,
1817 const std::string& oat_filename,
1818 const std::string& oat_location,
1819 bool executable,
1820 bool low_4gb,
1821 ArrayRef<const std::string> dex_filenames,
1822 /*inout*/MemMap* reservation,
1823 /*out*/std::string* error_msg) {
1824 ScopedTrace trace("Open oat file " + oat_location);
1825 CHECK(!oat_filename.empty()) << oat_location;
1826 CheckLocation(oat_location);
1827
1828 std::string vdex_filename = GetVdexFilename(oat_filename);
1829
1830 // Check that the vdex file even exists, fast-fail. We don't check the odex
1831 // file as we use the absence of an odex file for test the functionality of
1832 // vdex-only.
1833 if (!OS::FileExists(vdex_filename.c_str())) {
1834 *error_msg = StringPrintf("File %s does not exist.", vdex_filename.c_str());
1835 return nullptr;
1836 }
1837
1838 // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
1839 // disabled.
1840 OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(zip_fd,
1841 vdex_filename,
1842 oat_filename,
1843 oat_location,
1844 /*writable=*/ false,
1845 executable,
1846 low_4gb,
1847 dex_filenames,
1848 reservation,
1849 error_msg);
1850 if (with_dlopen != nullptr) {
1851 Runtime* runtime = Runtime::Current();
1852 // The runtime might not be available at this point if we're running
1853 // dex2oat or oatdump.
1854 if (runtime != nullptr) {
1855 size_t madvise_size_limit = runtime->GetMadviseWillNeedSizeOdex();
1856 Runtime::MadviseFileForRange(madvise_size_limit,
1857 with_dlopen->Size(),
1858 with_dlopen->Begin(),
1859 with_dlopen->End(),
1860 oat_location);
1861 }
1862 return with_dlopen;
1863 }
1864 if (kPrintDlOpenErrorMessage) {
1865 LOG(ERROR) << "Failed to dlopen: " << oat_filename << " with error " << *error_msg;
1866 }
1867 // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
1868 //
1869 // On target, dlopen may fail when compiling due to selinux restrictions on installd.
1870 //
1871 // We use our own ELF loader for Quick to deal with legacy apps that
1872 // open a generated dex file by name, remove the file, then open
1873 // another generated dex file with the same name. http://b/10614658
1874 //
1875 // On host, dlopen is expected to fail when cross compiling, so fall back to ElfOatFile.
1876 //
1877 //
1878 // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
1879 // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN.
1880 OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1881 vdex_filename,
1882 oat_filename,
1883 oat_location,
1884 /*writable=*/ false,
1885 executable,
1886 low_4gb,
1887 dex_filenames,
1888 reservation,
1889 error_msg);
1890 return with_internal;
1891 }
1892
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)1893 OatFile* OatFile::Open(int zip_fd,
1894 int vdex_fd,
1895 int oat_fd,
1896 const std::string& oat_location,
1897 bool executable,
1898 bool low_4gb,
1899 ArrayRef<const std::string> dex_filenames,
1900 /*inout*/MemMap* reservation,
1901 /*out*/std::string* error_msg) {
1902 CHECK(!oat_location.empty()) << oat_location;
1903
1904 std::string vdex_location = GetVdexFilename(oat_location);
1905
1906 OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1907 vdex_fd,
1908 oat_fd,
1909 vdex_location,
1910 oat_location,
1911 /*writable=*/ false,
1912 executable,
1913 low_4gb,
1914 dex_filenames,
1915 reservation,
1916 error_msg);
1917 return with_internal;
1918 }
1919
OpenFromVdex(const std::vector<const DexFile * > & dex_files,std::unique_ptr<VdexFile> && vdex_file,const std::string & location)1920 OatFile* OatFile::OpenFromVdex(const std::vector<const DexFile*>& dex_files,
1921 std::unique_ptr<VdexFile>&& vdex_file,
1922 const std::string& location) {
1923 CheckLocation(location);
1924 return OatFileBackedByVdex::Open(dex_files, std::move(vdex_file), location);
1925 }
1926
OpenFromVdex(int zip_fd,std::unique_ptr<VdexFile> && vdex_file,const std::string & location,std::string * error_msg)1927 OatFile* OatFile::OpenFromVdex(int zip_fd,
1928 std::unique_ptr<VdexFile>&& vdex_file,
1929 const std::string& location,
1930 std::string* error_msg) {
1931 CheckLocation(location);
1932 return OatFileBackedByVdex::Open(zip_fd, std::move(vdex_file), location, error_msg);
1933 }
1934
OatFile(const std::string & location,bool is_executable)1935 OatFile::OatFile(const std::string& location, bool is_executable)
1936 : location_(location),
1937 vdex_(nullptr),
1938 begin_(nullptr),
1939 end_(nullptr),
1940 data_bimg_rel_ro_begin_(nullptr),
1941 data_bimg_rel_ro_end_(nullptr),
1942 bss_begin_(nullptr),
1943 bss_end_(nullptr),
1944 bss_methods_(nullptr),
1945 bss_roots_(nullptr),
1946 is_executable_(is_executable),
1947 vdex_begin_(nullptr),
1948 vdex_end_(nullptr),
1949 secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
1950 CHECK(!location_.empty());
1951 }
1952
~OatFile()1953 OatFile::~OatFile() {
1954 STLDeleteElements(&oat_dex_files_storage_);
1955 }
1956
GetOatHeader() const1957 const OatHeader& OatFile::GetOatHeader() const {
1958 return *reinterpret_cast<const OatHeader*>(Begin());
1959 }
1960
Begin() const1961 const uint8_t* OatFile::Begin() const {
1962 CHECK(begin_ != nullptr);
1963 return begin_;
1964 }
1965
End() const1966 const uint8_t* OatFile::End() const {
1967 CHECK(end_ != nullptr);
1968 return end_;
1969 }
1970
DexBegin() const1971 const uint8_t* OatFile::DexBegin() const {
1972 return vdex_->Begin();
1973 }
1974
DexEnd() const1975 const uint8_t* OatFile::DexEnd() const {
1976 return vdex_->End();
1977 }
1978
GetBootImageRelocations() const1979 ArrayRef<const uint32_t> OatFile::GetBootImageRelocations() const {
1980 if (data_bimg_rel_ro_begin_ != nullptr) {
1981 const uint32_t* relocations = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_begin_);
1982 const uint32_t* relocations_end = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_end_);
1983 return ArrayRef<const uint32_t>(relocations, relocations_end - relocations);
1984 } else {
1985 return ArrayRef<const uint32_t>();
1986 }
1987 }
1988
GetBssMethods() const1989 ArrayRef<ArtMethod*> OatFile::GetBssMethods() const {
1990 if (bss_methods_ != nullptr) {
1991 ArtMethod** methods = reinterpret_cast<ArtMethod**>(bss_methods_);
1992 ArtMethod** methods_end =
1993 reinterpret_cast<ArtMethod**>(bss_roots_ != nullptr ? bss_roots_ : bss_end_);
1994 return ArrayRef<ArtMethod*>(methods, methods_end - methods);
1995 } else {
1996 return ArrayRef<ArtMethod*>();
1997 }
1998 }
1999
GetBssGcRoots() const2000 ArrayRef<GcRoot<mirror::Object>> OatFile::GetBssGcRoots() const {
2001 if (bss_roots_ != nullptr) {
2002 auto* roots = reinterpret_cast<GcRoot<mirror::Object>*>(bss_roots_);
2003 auto* roots_end = reinterpret_cast<GcRoot<mirror::Object>*>(bss_end_);
2004 return ArrayRef<GcRoot<mirror::Object>>(roots, roots_end - roots);
2005 } else {
2006 return ArrayRef<GcRoot<mirror::Object>>();
2007 }
2008 }
2009
GetOatDexFile(const char * dex_location,const uint32_t * dex_location_checksum,std::string * error_msg) const2010 const OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
2011 const uint32_t* dex_location_checksum,
2012 std::string* error_msg) const {
2013 // NOTE: We assume here that the canonical location for a given dex_location never
2014 // changes. If it does (i.e. some symlink used by the filename changes) we may return
2015 // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
2016 // an identical file or fail; otherwise we may see some unpredictable failures.
2017
2018 // TODO: Additional analysis of usage patterns to see if this can be simplified
2019 // without any performance loss, for example by not doing the first lock-free lookup.
2020
2021 const OatDexFile* oat_dex_file = nullptr;
2022 std::string_view key(dex_location);
2023 // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
2024 // directly mentioned in the oat file and doesn't require locking.
2025 auto primary_it = oat_dex_files_.find(key);
2026 if (primary_it != oat_dex_files_.end()) {
2027 oat_dex_file = primary_it->second;
2028 DCHECK(oat_dex_file != nullptr);
2029 } else {
2030 // This dex_location is not one of the dex locations directly mentioned in the
2031 // oat file. The correct lookup is via the canonical location but first see in
2032 // the secondary_oat_dex_files_ whether we've looked up this location before.
2033 MutexLock mu(Thread::Current(), secondary_lookup_lock_);
2034 auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
2035 if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
2036 oat_dex_file = secondary_lb->second; // May be null.
2037 } else {
2038 // We haven't seen this dex_location before, we must check the canonical location.
2039 std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
2040 if (dex_canonical_location != dex_location) {
2041 std::string_view canonical_key(dex_canonical_location);
2042 auto canonical_it = oat_dex_files_.find(canonical_key);
2043 if (canonical_it != oat_dex_files_.end()) {
2044 oat_dex_file = canonical_it->second;
2045 } // else keep null.
2046 } // else keep null.
2047
2048 // Copy the key to the string_cache_ and store the result in secondary map.
2049 string_cache_.emplace_back(key.data(), key.length());
2050 std::string_view key_copy(string_cache_.back());
2051 secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
2052 }
2053 }
2054
2055 if (oat_dex_file == nullptr) {
2056 if (error_msg != nullptr) {
2057 std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
2058 *error_msg = "Failed to find OatDexFile for DexFile " + std::string(dex_location)
2059 + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation();
2060 }
2061 return nullptr;
2062 }
2063
2064 if (dex_location_checksum != nullptr &&
2065 oat_dex_file->GetDexFileLocationChecksum() != *dex_location_checksum) {
2066 if (error_msg != nullptr) {
2067 std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
2068 std::string checksum = StringPrintf("0x%08x", oat_dex_file->GetDexFileLocationChecksum());
2069 std::string required_checksum = StringPrintf("0x%08x", *dex_location_checksum);
2070 *error_msg = "OatDexFile for DexFile " + std::string(dex_location)
2071 + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation()
2072 + " has checksum " + checksum + " but " + required_checksum + " was required";
2073 }
2074 return nullptr;
2075 }
2076 return oat_dex_file;
2077 }
2078
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)2079 OatDexFile::OatDexFile(const OatFile* oat_file,
2080 const std::string& dex_file_location,
2081 const std::string& canonical_dex_file_location,
2082 uint32_t dex_file_location_checksum,
2083 const uint8_t* dex_file_pointer,
2084 const uint8_t* lookup_table_data,
2085 const IndexBssMapping* method_bss_mapping_data,
2086 const IndexBssMapping* type_bss_mapping_data,
2087 const IndexBssMapping* public_type_bss_mapping_data,
2088 const IndexBssMapping* package_type_bss_mapping_data,
2089 const IndexBssMapping* string_bss_mapping_data,
2090 const uint32_t* oat_class_offsets_pointer,
2091 const DexLayoutSections* dex_layout_sections)
2092 : oat_file_(oat_file),
2093 dex_file_location_(dex_file_location),
2094 canonical_dex_file_location_(canonical_dex_file_location),
2095 dex_file_location_checksum_(dex_file_location_checksum),
2096 dex_file_pointer_(dex_file_pointer),
2097 lookup_table_data_(lookup_table_data),
2098 method_bss_mapping_(method_bss_mapping_data),
2099 type_bss_mapping_(type_bss_mapping_data),
2100 public_type_bss_mapping_(public_type_bss_mapping_data),
2101 package_type_bss_mapping_(package_type_bss_mapping_data),
2102 string_bss_mapping_(string_bss_mapping_data),
2103 oat_class_offsets_pointer_(oat_class_offsets_pointer),
2104 lookup_table_(),
2105 dex_layout_sections_(dex_layout_sections) {
2106 InitializeTypeLookupTable();
2107 DCHECK(!IsBackedByVdexOnly());
2108 }
2109
InitializeTypeLookupTable()2110 void OatDexFile::InitializeTypeLookupTable() {
2111 // Initialize TypeLookupTable.
2112 if (lookup_table_data_ != nullptr) {
2113 // Peek the number of classes from the DexFile.
2114 const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_);
2115 const uint32_t num_class_defs = dex_header->class_defs_size_;
2116 if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) >
2117 GetOatFile()->DexEnd()) {
2118 LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
2119 } else {
2120 const uint8_t* dex_data = dex_file_pointer_;
2121 // TODO: Clean this up to create the type lookup table after the dex file has been created?
2122 if (CompactDexFile::IsMagicValid(dex_header->magic_)) {
2123 dex_data += dex_header->data_off_;
2124 }
2125 lookup_table_ = TypeLookupTable::Open(dex_data, lookup_table_data_, num_class_defs);
2126 }
2127 }
2128 }
2129
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)2130 OatDexFile::OatDexFile(const OatFile* oat_file,
2131 const uint8_t* dex_file_pointer,
2132 uint32_t dex_file_location_checksum,
2133 const std::string& dex_file_location,
2134 const std::string& canonical_dex_file_location,
2135 const uint8_t* lookup_table_data)
2136 : oat_file_(oat_file),
2137 dex_file_location_(dex_file_location),
2138 canonical_dex_file_location_(canonical_dex_file_location),
2139 dex_file_location_checksum_(dex_file_location_checksum),
2140 dex_file_pointer_(dex_file_pointer),
2141 lookup_table_data_(lookup_table_data) {
2142 InitializeTypeLookupTable();
2143 DCHECK(IsBackedByVdexOnly());
2144 }
2145
OatDexFile(TypeLookupTable && lookup_table)2146 OatDexFile::OatDexFile(TypeLookupTable&& lookup_table) : lookup_table_(std::move(lookup_table)) {
2147 // Stripped-down OatDexFile only allowed in the compiler, the zygote, or the system server.
2148 CHECK(Runtime::Current() == nullptr ||
2149 Runtime::Current()->IsAotCompiler() ||
2150 Runtime::Current()->IsZygote() ||
2151 Runtime::Current()->IsSystemServer());
2152 }
2153
~OatDexFile()2154 OatDexFile::~OatDexFile() {}
2155
FileSize() const2156 size_t OatDexFile::FileSize() const {
2157 DCHECK(dex_file_pointer_ != nullptr);
2158 return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
2159 }
2160
OpenDexFile(std::string * error_msg) const2161 std::unique_ptr<const DexFile> OatDexFile::OpenDexFile(std::string* error_msg) const {
2162 ScopedTrace trace(__PRETTY_FUNCTION__);
2163 static constexpr bool kVerify = false;
2164 static constexpr bool kVerifyChecksum = false;
2165 const ArtDexFileLoader dex_file_loader;
2166 return dex_file_loader.Open(dex_file_pointer_,
2167 FileSize(),
2168 dex_file_location_,
2169 dex_file_location_checksum_,
2170 this,
2171 kVerify,
2172 kVerifyChecksum,
2173 error_msg);
2174 }
2175
GetOatClassOffset(uint16_t class_def_index) const2176 uint32_t OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
2177 DCHECK(oat_class_offsets_pointer_ != nullptr);
2178 return oat_class_offsets_pointer_[class_def_index];
2179 }
2180
IsBackedByVdexOnly() const2181 bool OatDexFile::IsBackedByVdexOnly() const {
2182 return oat_class_offsets_pointer_ == nullptr;
2183 }
2184
GetOatClass(uint16_t class_def_index) const2185 OatFile::OatClass OatDexFile::GetOatClass(uint16_t class_def_index) const {
2186 if (IsBackedByVdexOnly()) {
2187 // If there is only a vdex file, return that the class is not ready. The
2188 // caller will have to call `VdexFile::ComputeClassStatus` to compute the
2189 // actual class status, because we need to do the assignability type checks.
2190 return OatFile::OatClass(oat_file_,
2191 ClassStatus::kNotReady,
2192 /* type= */ OatClassType::kNoneCompiled,
2193 /* bitmap_size= */ 0u,
2194 /* bitmap_pointer= */ nullptr,
2195 /* methods_pointer= */ nullptr);
2196 }
2197
2198 uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
2199 CHECK_GE(oat_class_offset, sizeof(OatHeader)) << oat_file_->GetLocation();
2200 CHECK_LT(oat_class_offset, oat_file_->Size()) << oat_file_->GetLocation();
2201 CHECK_LE(/* status */ sizeof(uint16_t) + /* type */ sizeof(uint16_t),
2202 oat_file_->Size() - oat_class_offset) << oat_file_->GetLocation();
2203 const uint8_t* current_pointer = oat_file_->Begin() + oat_class_offset;
2204
2205 uint16_t status_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2206 current_pointer += sizeof(uint16_t);
2207 uint16_t type_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2208 current_pointer += sizeof(uint16_t);
2209 CHECK_LE(status_value, enum_cast<uint8_t>(ClassStatus::kLast))
2210 << static_cast<uint32_t>(status_value) << " at " << oat_file_->GetLocation();
2211 CHECK_LT(type_value, enum_cast<uint8_t>(OatClassType::kOatClassMax)) << oat_file_->GetLocation();
2212 ClassStatus status = enum_cast<ClassStatus>(status_value);
2213 OatClassType type = enum_cast<OatClassType>(type_value);
2214
2215 uint32_t num_methods = 0;
2216 const uint32_t* bitmap_pointer = nullptr;
2217 const OatMethodOffsets* methods_pointer = nullptr;
2218 if (type != OatClassType::kNoneCompiled) {
2219 CHECK_LE(sizeof(uint32_t), static_cast<size_t>(oat_file_->End() - current_pointer))
2220 << oat_file_->GetLocation();
2221 num_methods = *reinterpret_cast<const uint32_t*>(current_pointer);
2222 current_pointer += sizeof(uint32_t);
2223 CHECK_NE(num_methods, 0u) << oat_file_->GetLocation();
2224 uint32_t num_method_offsets;
2225 if (type == OatClassType::kSomeCompiled) {
2226 uint32_t bitmap_size = BitVector::BitsToWords(num_methods) * BitVector::kWordBytes;
2227 CHECK_LE(bitmap_size, static_cast<size_t>(oat_file_->End() - current_pointer))
2228 << oat_file_->GetLocation();
2229 bitmap_pointer = reinterpret_cast<const uint32_t*>(current_pointer);
2230 current_pointer += bitmap_size;
2231 // Note: The bits in range [num_methods, bitmap_size * kBitsPerByte)
2232 // should be zero but we're not verifying that.
2233 num_method_offsets = BitVector::NumSetBits(bitmap_pointer, num_methods);
2234 } else {
2235 num_method_offsets = num_methods;
2236 }
2237 CHECK_LE(num_method_offsets,
2238 static_cast<size_t>(oat_file_->End() - current_pointer) / sizeof(OatMethodOffsets))
2239 << oat_file_->GetLocation();
2240 methods_pointer = reinterpret_cast<const OatMethodOffsets*>(current_pointer);
2241 }
2242
2243 return OatFile::OatClass(oat_file_, status, type, num_methods, bitmap_pointer, methods_pointer);
2244 }
2245
FindClassDef(const DexFile & dex_file,const char * descriptor,size_t hash)2246 const dex::ClassDef* OatDexFile::FindClassDef(const DexFile& dex_file,
2247 const char* descriptor,
2248 size_t hash) {
2249 const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2250 DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash);
2251 bool used_lookup_table = false;
2252 const dex::ClassDef* lookup_table_classdef = nullptr;
2253 if (LIKELY((oat_dex_file != nullptr) && oat_dex_file->GetTypeLookupTable().Valid())) {
2254 used_lookup_table = true;
2255 const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable().Lookup(descriptor, hash);
2256 if (class_def_idx != dex::kDexNoIndex) {
2257 CHECK_LT(class_def_idx, dex_file.NumClassDefs()) << oat_dex_file->GetOatFile()->GetLocation();
2258 lookup_table_classdef = &dex_file.GetClassDef(class_def_idx);
2259 }
2260 if (!kIsDebugBuild) {
2261 return lookup_table_classdef;
2262 }
2263 }
2264 // Fast path for rare no class defs case.
2265 const uint32_t num_class_defs = dex_file.NumClassDefs();
2266 if (num_class_defs == 0) {
2267 DCHECK(!used_lookup_table);
2268 return nullptr;
2269 }
2270 const dex::TypeId* type_id = dex_file.FindTypeId(descriptor);
2271 if (type_id != nullptr) {
2272 dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id);
2273 const dex::ClassDef* found_class_def = dex_file.FindClassDef(type_idx);
2274 if (kIsDebugBuild && used_lookup_table) {
2275 DCHECK_EQ(found_class_def, lookup_table_classdef);
2276 }
2277 return found_class_def;
2278 }
2279 return nullptr;
2280 }
2281
2282 // Madvise the dex file based on the state we are moving to.
MadviseDexFile(const DexFile & dex_file,MadviseState state)2283 void OatDexFile::MadviseDexFile(const DexFile& dex_file, MadviseState state) {
2284 Runtime* const runtime = Runtime::Current();
2285 const bool low_ram = runtime->GetHeap()->IsLowMemoryMode();
2286 // TODO: Also do madvise hints for non low ram devices.
2287 if (!low_ram) {
2288 return;
2289 }
2290 if (state == MadviseState::kMadviseStateAtLoad && runtime->MAdviseRandomAccess()) {
2291 // Default every dex file to MADV_RANDOM when its loaded by default for low ram devices.
2292 // Other devices have enough page cache to get performance benefits from loading more pages
2293 // into the page cache.
2294 DexLayoutSection::MadviseLargestPageAlignedRegion(dex_file.Begin(),
2295 dex_file.Begin() + dex_file.Size(),
2296 MADV_RANDOM);
2297 }
2298 const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2299 if (oat_dex_file != nullptr) {
2300 // Should always be there.
2301 const DexLayoutSections* const sections = oat_dex_file->GetDexLayoutSections();
2302 if (sections != nullptr) {
2303 sections->Madvise(&dex_file, state);
2304 } else {
2305 DCHECK(oat_dex_file->IsBackedByVdexOnly());
2306 }
2307 }
2308 }
2309
OatClass(const OatFile * oat_file,ClassStatus status,OatClassType type,uint32_t num_methods,const uint32_t * bitmap_pointer,const OatMethodOffsets * methods_pointer)2310 OatFile::OatClass::OatClass(const OatFile* oat_file,
2311 ClassStatus status,
2312 OatClassType type,
2313 uint32_t num_methods,
2314 const uint32_t* bitmap_pointer,
2315 const OatMethodOffsets* methods_pointer)
2316 : oat_file_(oat_file),
2317 status_(status),
2318 type_(type),
2319 num_methods_(num_methods),
2320 bitmap_(bitmap_pointer),
2321 methods_pointer_(methods_pointer) {
2322 DCHECK_EQ(num_methods != 0u, type != OatClassType::kNoneCompiled);
2323 DCHECK_EQ(bitmap_pointer != nullptr, type == OatClassType::kSomeCompiled);
2324 DCHECK_EQ(methods_pointer != nullptr, type != OatClassType::kNoneCompiled);
2325 }
2326
GetOatMethodOffsetsOffset(uint32_t method_index) const2327 uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
2328 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2329 if (oat_method_offsets == nullptr) {
2330 return 0u;
2331 }
2332 return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
2333 }
2334
GetOatMethodOffsets(uint32_t method_index) const2335 const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
2336 // NOTE: We don't keep the number of methods for `kNoneCompiled` and cannot do
2337 // a bounds check for `method_index` in that case.
2338 if (methods_pointer_ == nullptr) {
2339 CHECK_EQ(OatClassType::kNoneCompiled, type_);
2340 return nullptr;
2341 }
2342 CHECK_LT(method_index, num_methods_) << oat_file_->GetLocation();
2343 size_t methods_pointer_index;
2344 if (bitmap_ == nullptr) {
2345 CHECK_EQ(OatClassType::kAllCompiled, type_);
2346 methods_pointer_index = method_index;
2347 } else {
2348 CHECK_EQ(OatClassType::kSomeCompiled, type_);
2349 if (!BitVector::IsBitSet(bitmap_, method_index)) {
2350 return nullptr;
2351 }
2352 size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
2353 methods_pointer_index = num_set_bits;
2354 }
2355 if (kIsDebugBuild) {
2356 size_t size_until_end = dchecked_integral_cast<size_t>(
2357 oat_file_->End() - reinterpret_cast<const uint8_t*>(methods_pointer_));
2358 CHECK_LE(methods_pointer_index, size_until_end / sizeof(OatMethodOffsets))
2359 << oat_file_->GetLocation();
2360 }
2361 const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
2362 return &oat_method_offsets;
2363 }
2364
GetOatMethod(uint32_t method_index) const2365 const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
2366 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2367 if (oat_method_offsets == nullptr) {
2368 return OatMethod(nullptr, 0);
2369 }
2370 if (oat_file_->IsExecutable() ||
2371 Runtime::Current() == nullptr || // This case applies for oatdump.
2372 Runtime::Current()->IsAotCompiler()) {
2373 return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
2374 }
2375 // We aren't allowed to use the compiled code. We just force it down the interpreted / jit
2376 // version.
2377 return OatMethod(oat_file_->Begin(), 0);
2378 }
2379
IsDebuggable() const2380 bool OatFile::IsDebuggable() const {
2381 return GetOatHeader().IsDebuggable();
2382 }
2383
GetCompilerFilter() const2384 CompilerFilter::Filter OatFile::GetCompilerFilter() const {
2385 return GetOatHeader().GetCompilerFilter();
2386 }
2387
GetClassLoaderContext() const2388 std::string OatFile::GetClassLoaderContext() const {
2389 return GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
2390 }
2391
GetCompilationReason() const2392 const char* OatFile::GetCompilationReason() const {
2393 return GetOatHeader().GetStoreValueByKey(OatHeader::kCompilationReasonKey);
2394 }
2395
FindOatClass(const DexFile & dex_file,uint16_t class_def_idx,bool * found)2396 OatFile::OatClass OatFile::FindOatClass(const DexFile& dex_file,
2397 uint16_t class_def_idx,
2398 bool* found) {
2399 DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
2400 const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2401 if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
2402 *found = false;
2403 return OatFile::OatClass::Invalid();
2404 }
2405 *found = true;
2406 return oat_dex_file->GetOatClass(class_def_idx);
2407 }
2408
RequiresImage() const2409 bool OatFile::RequiresImage() const { return GetOatHeader().RequiresImage(); }
2410
DCheckIndexToBssMapping(const OatFile * oat_file,uint32_t number_of_indexes,size_t slot_size,const IndexBssMapping * index_bss_mapping)2411 static void DCheckIndexToBssMapping(const OatFile* oat_file,
2412 uint32_t number_of_indexes,
2413 size_t slot_size,
2414 const IndexBssMapping* index_bss_mapping) {
2415 if (kIsDebugBuild && index_bss_mapping != nullptr) {
2416 size_t index_bits = IndexBssMappingEntry::IndexBits(number_of_indexes);
2417 const IndexBssMappingEntry* prev_entry = nullptr;
2418 for (const IndexBssMappingEntry& entry : *index_bss_mapping) {
2419 CHECK_ALIGNED_PARAM(entry.bss_offset, slot_size);
2420 CHECK_LT(entry.bss_offset, oat_file->BssSize());
2421 uint32_t mask = entry.GetMask(index_bits);
2422 CHECK_LE(POPCOUNT(mask) * slot_size, entry.bss_offset);
2423 size_t index_mask_span = (mask != 0u) ? 32u - index_bits - CTZ(mask) : 0u;
2424 CHECK_LE(index_mask_span, entry.GetIndex(index_bits));
2425 if (prev_entry != nullptr) {
2426 CHECK_LT(prev_entry->GetIndex(index_bits), entry.GetIndex(index_bits) - index_mask_span);
2427 }
2428 prev_entry = &entry;
2429 }
2430 CHECK(prev_entry != nullptr);
2431 CHECK_LT(prev_entry->GetIndex(index_bits), number_of_indexes);
2432 }
2433 }
2434
InitializeRelocations() const2435 void OatFile::InitializeRelocations() const {
2436 DCHECK(IsExecutable());
2437
2438 // Initialize the .data.bimg.rel.ro section.
2439 if (!GetBootImageRelocations().empty()) {
2440 uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin());
2441 CheckedCall(mprotect,
2442 "un-protect boot image relocations",
2443 reloc_begin,
2444 DataBimgRelRoSize(),
2445 PROT_READ | PROT_WRITE);
2446 uint32_t boot_image_begin = Runtime::Current()->GetHeap()->GetBootImagesStartAddress();
2447 for (const uint32_t& relocation : GetBootImageRelocations()) {
2448 const_cast<uint32_t&>(relocation) += boot_image_begin;
2449 }
2450 CheckedCall(mprotect,
2451 "protect boot image relocations",
2452 reloc_begin,
2453 DataBimgRelRoSize(),
2454 PROT_READ);
2455 }
2456
2457 // Before initializing .bss, check the .bss mappings in debug mode.
2458 if (kIsDebugBuild) {
2459 PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
2460 for (const OatDexFile* odf : GetOatDexFiles()) {
2461 const DexFile::Header* header =
2462 reinterpret_cast<const DexFile::Header*>(odf->GetDexFilePointer());
2463 DCheckIndexToBssMapping(this,
2464 header->method_ids_size_,
2465 static_cast<size_t>(pointer_size),
2466 odf->GetMethodBssMapping());
2467 DCheckIndexToBssMapping(this,
2468 header->type_ids_size_,
2469 sizeof(GcRoot<mirror::Class>),
2470 odf->GetTypeBssMapping());
2471 DCheckIndexToBssMapping(this,
2472 header->string_ids_size_,
2473 sizeof(GcRoot<mirror::String>),
2474 odf->GetStringBssMapping());
2475 }
2476 }
2477
2478 // Initialize the .bss section.
2479 // TODO: Pre-initialize from boot/app image?
2480 ArtMethod* resolution_method = Runtime::Current()->GetResolutionMethod();
2481 for (ArtMethod*& entry : GetBssMethods()) {
2482 entry = resolution_method;
2483 }
2484 }
2485
AssertAotCompiler()2486 void OatDexFile::AssertAotCompiler() {
2487 CHECK(Runtime::Current()->IsAotCompiler());
2488 }
2489
IsBackedByVdexOnly() const2490 bool OatFile::IsBackedByVdexOnly() const {
2491 return oat_dex_files_storage_.size() >= 1 && oat_dex_files_storage_[0]->IsBackedByVdexOnly();
2492 }
2493
2494 } // namespace art
2495