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