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