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