• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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