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