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