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