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