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   bool Setup(const std::vector<const DexFile*>& dex_files, std::string* error_msg);
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 
ComputeAndCheckTypeLookupTableData(const DexFile::Header & header,const uint8_t * type_lookup_table_start,const VdexFile * vdex_file,const uint8_t ** type_lookup_table_data,std::string * error_msg)479 static bool ComputeAndCheckTypeLookupTableData(const DexFile::Header& header,
480                                                const uint8_t* type_lookup_table_start,
481                                                const VdexFile* vdex_file,
482                                                const uint8_t** type_lookup_table_data,
483                                                std::string* error_msg) {
484   if (type_lookup_table_start == nullptr ||
485       reinterpret_cast<const uint32_t*>(type_lookup_table_start)[0] == 0) {
486     *type_lookup_table_data = nullptr;
487     return true;
488   }
489 
490   *type_lookup_table_data = type_lookup_table_start + sizeof(uint32_t);
491   size_t expected_table_size = TypeLookupTable::RawDataLength(header.class_defs_size_);
492   size_t found_size = reinterpret_cast<const uint32_t*>(type_lookup_table_start)[0];
493   if (UNLIKELY(found_size != expected_table_size)) {
494     *error_msg =
495         StringPrintf("In vdex file '%s' unexpected type lookup table size: found %zu, expected %zu",
496                      vdex_file->GetName().c_str(),
497                      found_size,
498                      expected_table_size);
499     return false;
500   }
501   if (UNLIKELY(!vdex_file->Contains(*type_lookup_table_data))) {
502     *error_msg =
503         StringPrintf("In vdex file '%s' found invalid type lookup table pointer %p not in [%p, %p]",
504                      vdex_file->GetName().c_str(),
505                      type_lookup_table_data,
506                      vdex_file->Begin(),
507                      vdex_file->End());
508     return false;
509   }
510   if (UNLIKELY(!vdex_file->Contains(*type_lookup_table_data + expected_table_size - 1))) {
511     *error_msg =
512         StringPrintf("In vdex file '%s' found overflowing type lookup table %p not in [%p, %p]",
513                      vdex_file->GetName().c_str(),
514                      type_lookup_table_data + expected_table_size,
515                      vdex_file->Begin(),
516                      vdex_file->End());
517     return false;
518   }
519   if (UNLIKELY(!IsAligned<4>(type_lookup_table_start))) {
520     *error_msg =
521         StringPrintf("In vdex file '%s' found invalid type lookup table alignment %p",
522                      vdex_file->GetName().c_str(),
523                      type_lookup_table_start);
524     return false;
525   }
526   return true;
527 }
528 
Setup(const std::vector<const DexFile * > & dex_files,std::string * error_msg)529 bool OatFileBase::Setup(const std::vector<const DexFile*>& dex_files, std::string* error_msg) {
530   uint32_t i = 0;
531   const uint8_t* type_lookup_table_start = nullptr;
532   for (const DexFile* dex_file : dex_files) {
533     std::string dex_location = dex_file->GetLocation();
534     std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location.c_str());
535 
536     type_lookup_table_start = vdex_->GetNextTypeLookupTableData(type_lookup_table_start, i++);
537     const uint8_t* type_lookup_table_data = nullptr;
538     if (!ComputeAndCheckTypeLookupTableData(dex_file->GetHeader(),
539                                             type_lookup_table_start,
540                                             vdex_.get(),
541                                             &type_lookup_table_data,
542                                             error_msg)) {
543       return false;
544     }
545     // Create an OatDexFile and add it to the owning container.
546     OatDexFile* oat_dex_file = new OatDexFile(
547         this,
548         dex_file->Begin(),
549         dex_file->GetLocationChecksum(),
550         dex_location,
551         canonical_location,
552         type_lookup_table_data);
553     oat_dex_files_storage_.push_back(oat_dex_file);
554 
555     // Add the location and canonical location (if different) to the oat_dex_files_ table.
556     std::string_view key(oat_dex_file->GetDexFileLocation());
557     oat_dex_files_.Put(key, oat_dex_file);
558     if (canonical_location != dex_location) {
559       std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
560       oat_dex_files_.Put(canonical_key, oat_dex_file);
561     }
562   }
563   // Now that we've created all the OatDexFile, update the dex files.
564   for (i = 0; i < dex_files.size(); ++i) {
565     dex_files[i]->SetOatDexFile(oat_dex_files_storage_[i]);
566   }
567   return true;
568 }
569 
Setup(int zip_fd,ArrayRef<const std::string> dex_filenames,std::string * error_msg)570 bool OatFileBase::Setup(int zip_fd,
571                         ArrayRef<const std::string> dex_filenames,
572                         std::string* error_msg) {
573   if (!GetOatHeader().IsValid()) {
574     std::string cause = GetOatHeader().GetValidationErrorMessage();
575     *error_msg = StringPrintf("Invalid oat header for '%s': %s",
576                               GetLocation().c_str(),
577                               cause.c_str());
578     return false;
579   }
580   PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
581   size_t key_value_store_size =
582       (Size() >= sizeof(OatHeader)) ? GetOatHeader().GetKeyValueStoreSize() : 0u;
583   if (Size() < sizeof(OatHeader) + key_value_store_size) {
584     *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader, "
585                                   "size = %zu < %zu + %zu",
586                               GetLocation().c_str(),
587                               Size(),
588                               sizeof(OatHeader),
589                               key_value_store_size);
590     return false;
591   }
592 
593   size_t oat_dex_files_offset = GetOatHeader().GetOatDexFilesOffset();
594   if (oat_dex_files_offset < GetOatHeader().GetHeaderSize() || oat_dex_files_offset > Size()) {
595     *error_msg = StringPrintf("In oat file '%s' found invalid oat dex files offset: "
596                                   "%zu is not in [%zu, %zu]",
597                               GetLocation().c_str(),
598                               oat_dex_files_offset,
599                               GetOatHeader().GetHeaderSize(),
600                               Size());
601     return false;
602   }
603   const uint8_t* oat = Begin() + oat_dex_files_offset;  // Jump to the OatDexFile records.
604 
605   if (!IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_begin_) ||
606       !IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_end_) ||
607       data_bimg_rel_ro_begin_ > data_bimg_rel_ro_end_) {
608     *error_msg = StringPrintf("In oat file '%s' found unaligned or unordered databimgrelro "
609                                   "symbol(s): begin = %p, end = %p",
610                               GetLocation().c_str(),
611                               data_bimg_rel_ro_begin_,
612                               data_bimg_rel_ro_end_);
613     return false;
614   }
615 
616   DCHECK_GE(static_cast<size_t>(pointer_size), alignof(GcRoot<mirror::Object>));
617   if (!IsAligned<kPageSize>(bss_begin_) ||
618       !IsAlignedParam(bss_methods_, static_cast<size_t>(pointer_size)) ||
619       !IsAlignedParam(bss_roots_, static_cast<size_t>(pointer_size)) ||
620       !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_end_)) {
621     *error_msg = StringPrintf("In oat file '%s' found unaligned bss symbol(s): "
622                                   "begin = %p, methods_ = %p, roots = %p, end = %p",
623                               GetLocation().c_str(),
624                               bss_begin_,
625                               bss_methods_,
626                               bss_roots_,
627                               bss_end_);
628     return false;
629   }
630 
631   if ((bss_methods_ != nullptr && (bss_methods_ < bss_begin_ || bss_methods_ > bss_end_)) ||
632       (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) ||
633       (bss_methods_ != nullptr && bss_roots_ != nullptr && bss_methods_ > bss_roots_)) {
634     *error_msg = StringPrintf("In oat file '%s' found bss symbol(s) outside .bss or unordered: "
635                                   "begin = %p, methods = %p, roots = %p, end = %p",
636                               GetLocation().c_str(),
637                               bss_begin_,
638                               bss_methods_,
639                               bss_roots_,
640                               bss_end_);
641     return false;
642   }
643 
644   if (bss_methods_ != nullptr && bss_methods_ != bss_begin_) {
645     *error_msg = StringPrintf("In oat file '%s' found unexpected .bss gap before 'oatbssmethods': "
646                                   "begin = %p, methods = %p",
647                               GetLocation().c_str(),
648                               bss_begin_,
649                               bss_methods_);
650     return false;
651   }
652 
653   std::string_view primary_location;
654   std::string_view primary_location_replacement;
655   size_t dex_filenames_pos = 0u;
656   uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
657   oat_dex_files_storage_.reserve(dex_file_count);
658   for (size_t i = 0; i < dex_file_count; i++) {
659     uint32_t dex_file_location_size;
660     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
661       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file "
662                                     "location size",
663                                 GetLocation().c_str(),
664                                 i);
665       return false;
666     }
667     if (UNLIKELY(dex_file_location_size == 0U)) {
668       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name",
669                                 GetLocation().c_str(),
670                                 i);
671       return false;
672     }
673     if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) {
674       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file "
675                                     "location",
676                                 GetLocation().c_str(),
677                                 i);
678       return false;
679     }
680     const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
681     oat += dex_file_location_size;
682 
683     // Location encoded in the oat file. We will use this for multidex naming.
684     std::string_view oat_dex_file_location(dex_file_location_data, dex_file_location_size);
685     std::string dex_file_location(oat_dex_file_location);
686     bool is_multidex = DexFileLoader::IsMultiDexLocation(dex_file_location.c_str());
687     // Check that `is_multidex` does not clash with other indicators. The first dex location
688     // must be primary location and, if we're opening external dex files, the location must
689     // be multi-dex if and only if we already have a dex file opened for it.
690     if ((i == 0 && is_multidex) ||
691         (!external_dex_files_.empty() && (is_multidex != (i < external_dex_files_.size())))) {
692       *error_msg = StringPrintf("In oat file '%s' found unexpected %s location '%s'",
693                                 GetLocation().c_str(),
694                                 is_multidex ? "multi-dex" : "primary",
695                                 dex_file_location.c_str());
696       return false;
697     }
698     // Remember the primary location and, if provided, the replacement from `dex_filenames`.
699     if (!is_multidex) {
700       primary_location = oat_dex_file_location;
701       if (!dex_filenames.empty()) {
702         if (dex_filenames_pos == dex_filenames.size()) {
703           *error_msg = StringPrintf("In oat file '%s' found excessive primary location '%s'"
704                                         ", expected only %zu primary locations",
705                                     GetLocation().c_str(),
706                                     dex_file_location.c_str(),
707                                     dex_filenames.size());
708           return false;
709         }
710         primary_location_replacement = dex_filenames[dex_filenames_pos];
711         ++dex_filenames_pos;
712       }
713     }
714     // Check that the base location of a multidex location matches the last seen primary location.
715     if (is_multidex &&
716         (!StartsWith(dex_file_location, primary_location) ||
717              dex_file_location[primary_location.size()] != DexFileLoader::kMultiDexSeparator)) {
718       *error_msg = StringPrintf("In oat file '%s' found unexpected multidex location '%s',"
719                                     " unrelated to '%s'",
720                                 GetLocation().c_str(),
721                                 dex_file_location.c_str(),
722                                 std::string(primary_location).c_str());
723       return false;
724     }
725     std::string dex_file_name = dex_file_location;
726     if (!dex_filenames.empty()) {
727       dex_file_name.replace(/*pos*/ 0u, primary_location.size(), primary_location_replacement);
728       // If the location does not contain path and matches the file name component,
729       // use the provided file name also as the location.
730       // TODO: Do we need this for anything other than tests?
731       if (dex_file_location.find('/') == std::string::npos &&
732           dex_file_name.size() > dex_file_location.size() &&
733           dex_file_name[dex_file_name.size() - dex_file_location.size() - 1u] == '/' &&
734           EndsWith(dex_file_name, dex_file_location)) {
735         dex_file_location = dex_file_name;
736       }
737     }
738 
739     uint32_t dex_file_checksum;
740     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
741       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after "
742                                     "dex file checksum",
743                                 GetLocation().c_str(),
744                                 i,
745                                 dex_file_location.c_str());
746       return false;
747     }
748 
749     uint32_t dex_file_offset;
750     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
751       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
752                                     "after dex file offsets",
753                                 GetLocation().c_str(),
754                                 i,
755                                 dex_file_location.c_str());
756       return false;
757     }
758     if (UNLIKELY(dex_file_offset > DexSize())) {
759       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
760                                     "offset %u > %zu",
761                                 GetLocation().c_str(),
762                                 i,
763                                 dex_file_location.c_str(),
764                                 dex_file_offset,
765                                 DexSize());
766       return false;
767     }
768     const uint8_t* dex_file_pointer = nullptr;
769     if (UNLIKELY(dex_file_offset == 0U)) {
770       // Do not support mixed-mode oat files.
771       if (i != 0u && external_dex_files_.empty()) {
772         *error_msg = StringPrintf("In oat file '%s', unsupported uncompressed-dex-file for dex "
773                                       "file %zu (%s)",
774                                   GetLocation().c_str(),
775                                   i,
776                                   dex_file_location.c_str());
777         return false;
778       }
779       DCHECK_LE(i, external_dex_files_.size());
780       if (i == external_dex_files_.size()) {
781         std::vector<std::unique_ptr<const DexFile>> new_dex_files;
782         // No dex files, load it from location.
783         const ArtDexFileLoader dex_file_loader;
784         bool loaded = false;
785         if (zip_fd != -1) {
786           loaded = dex_file_loader.OpenZip(zip_fd,
787                                            dex_file_location,
788                                            /*verify=*/ false,
789                                            /*verify_checksum=*/ false,
790                                            error_msg,
791                                            &new_dex_files);
792         } else {
793           loaded = dex_file_loader.Open(dex_file_name.c_str(),
794                                         dex_file_location,
795                                         /*verify=*/ false,
796                                         /*verify_checksum=*/ false,
797                                         error_msg,
798                                         &new_dex_files);
799         }
800         if (!loaded) {
801           if (Runtime::Current() == nullptr) {
802             // If there's no runtime, we're running oatdump, so return
803             // a half constructed oat file that oatdump knows how to deal with.
804             LOG(WARNING) << "Could not find associated dex files of oat file. "
805                          << "Oatdump will only dump the header.";
806             return true;
807           } else {
808             return false;
809           }
810         }
811         // The oat file may be out of date wrt/ the dex-file location. We need to be defensive
812         // here and ensure that at least the number of dex files still matches.
813         // If we have a zip_fd, or reached the end of provided `dex_filenames`, we must
814         // load all dex files from that file, otherwise we may open multiple files.
815         // Note: actual checksum comparisons are the duty of the OatFileAssistant and will be
816         //       done after loading the OatFile.
817         size_t max_dex_files = dex_file_count - external_dex_files_.size();
818         bool expect_all =
819             (zip_fd != -1) || (!dex_filenames.empty() && dex_filenames_pos == dex_filenames.size());
820         if (expect_all ? new_dex_files.size() != max_dex_files
821                        : new_dex_files.size() > max_dex_files) {
822           *error_msg = StringPrintf("In oat file '%s', expected %s%zu uncompressed dex files, but "
823                                         "found %zu in '%s'",
824                                     GetLocation().c_str(),
825                                     (expect_all ? "" : "<="),
826                                     max_dex_files,
827                                     new_dex_files.size(),
828                                     dex_file_location.c_str());
829           return false;
830         }
831         for (std::unique_ptr<const DexFile>& dex_file : new_dex_files) {
832           external_dex_files_.push_back(std::move(dex_file));
833         }
834       }
835       dex_file_pointer = external_dex_files_[i]->Begin();
836     } else {
837       // Do not support mixed-mode oat files.
838       if (!external_dex_files_.empty()) {
839         *error_msg = StringPrintf("In oat file '%s', unsupported embedded dex-file for dex file "
840                                       "%zu (%s)",
841                                   GetLocation().c_str(),
842                                   i,
843                                   dex_file_location.c_str());
844         return false;
845       }
846       if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
847         *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
848                                       "offset %u of %zu but the size of dex file header is %zu",
849                                   GetLocation().c_str(),
850                                   i,
851                                   dex_file_location.c_str(),
852                                   dex_file_offset,
853                                   DexSize(),
854                                   sizeof(DexFile::Header));
855         return false;
856       }
857       dex_file_pointer = DexBegin() + dex_file_offset;
858     }
859 
860     const bool valid_magic = DexFileLoader::IsMagicValid(dex_file_pointer);
861     if (UNLIKELY(!valid_magic)) {
862       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
863                                     "dex file magic",
864                                 GetLocation().c_str(),
865                                 i,
866                                 dex_file_location.c_str());
867       return false;
868     }
869     if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_pointer))) {
870       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
871                                     "dex file version",
872                                 GetLocation().c_str(),
873                                 i,
874                                 dex_file_location.c_str());
875       return false;
876     }
877     const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
878     if (dex_file_offset != 0 && (DexSize() - dex_file_offset < header->file_size_)) {
879       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
880                                     "offset %u and size %u truncated at %zu",
881                                 GetLocation().c_str(),
882                                 i,
883                                 dex_file_location.c_str(),
884                                 dex_file_offset,
885                                 header->file_size_,
886                                 DexSize());
887       return false;
888     }
889 
890     uint32_t class_offsets_offset;
891     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {
892       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
893                                     "after class offsets offset",
894                                 GetLocation().c_str(),
895                                 i,
896                                 dex_file_location.c_str());
897       return false;
898     }
899     if (UNLIKELY(class_offsets_offset > Size()) ||
900         UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) {
901       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
902                                     "class offsets, offset %u of %zu, class defs %u",
903                                 GetLocation().c_str(),
904                                 i,
905                                 dex_file_location.c_str(),
906                                 class_offsets_offset,
907                                 Size(),
908                                 header->class_defs_size_);
909       return false;
910     }
911     if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) {
912       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned "
913                                     "class offsets, offset %u",
914                                 GetLocation().c_str(),
915                                 i,
916                                 dex_file_location.c_str(),
917                                 class_offsets_offset);
918       return false;
919     }
920     const uint32_t* class_offsets_pointer =
921         reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset);
922 
923     uint32_t lookup_table_offset;
924     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {
925       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
926                                     "after lookup table offset",
927                                 GetLocation().c_str(),
928                                 i,
929                                 dex_file_location.c_str());
930       return false;
931     }
932     const uint8_t* lookup_table_data = lookup_table_offset != 0u
933         ? DexBegin() + lookup_table_offset
934         : nullptr;
935     if (lookup_table_offset != 0u &&
936         (UNLIKELY(lookup_table_offset > DexSize()) ||
937             UNLIKELY(DexSize() - lookup_table_offset <
938                      TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
939       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
940                                     "type lookup table, offset %u of %zu, class defs %u",
941                                 GetLocation().c_str(),
942                                 i,
943                                 dex_file_location.c_str(),
944                                 lookup_table_offset,
945                                 Size(),
946                                 header->class_defs_size_);
947       return false;
948     }
949 
950     uint32_t dex_layout_sections_offset;
951     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_layout_sections_offset))) {
952       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
953                                     "after dex layout sections offset",
954                                 GetLocation().c_str(),
955                                 i,
956                                 dex_file_location.c_str());
957       return false;
958     }
959     const DexLayoutSections* const dex_layout_sections = dex_layout_sections_offset != 0
960         ? reinterpret_cast<const DexLayoutSections*>(Begin() + dex_layout_sections_offset)
961         : nullptr;
962 
963     const IndexBssMapping* method_bss_mapping;
964     const IndexBssMapping* type_bss_mapping;
965     const IndexBssMapping* public_type_bss_mapping;
966     const IndexBssMapping* package_type_bss_mapping;
967     const IndexBssMapping* string_bss_mapping;
968     if (!ReadIndexBssMapping(
969             this, &oat, i, dex_file_location, "method", &method_bss_mapping, error_msg) ||
970         !ReadIndexBssMapping(
971             this, &oat, i, dex_file_location, "type", &type_bss_mapping, error_msg) ||
972         !ReadIndexBssMapping(
973             this, &oat, i, dex_file_location, "type", &public_type_bss_mapping, error_msg) ||
974         !ReadIndexBssMapping(
975             this, &oat, i, dex_file_location, "type", &package_type_bss_mapping, error_msg) ||
976         !ReadIndexBssMapping(
977             this, &oat, i, dex_file_location, "string", &string_bss_mapping, error_msg)) {
978       return false;
979     }
980 
981     // Create the OatDexFile and add it to the owning container.
982     OatDexFile* oat_dex_file = new OatDexFile(
983         this,
984         dex_file_location,
985         DexFileLoader::GetDexCanonicalLocation(dex_file_name.c_str()),
986         dex_file_checksum,
987         dex_file_pointer,
988         lookup_table_data,
989         method_bss_mapping,
990         type_bss_mapping,
991         public_type_bss_mapping,
992         package_type_bss_mapping,
993         string_bss_mapping,
994         class_offsets_pointer,
995         dex_layout_sections);
996     oat_dex_files_storage_.push_back(oat_dex_file);
997 
998     // Add the location and canonical location (if different) to the oat_dex_files_ table.
999     // Note: We do not add the non-canonical `dex_file_name`. If it is different from both
1000     // the location and canonical location, GetOatDexFile() shall canonicalize it when
1001     // requested and match the canonical path.
1002     std::string_view key = oat_dex_file_location;  // References oat file data.
1003     std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
1004     oat_dex_files_.Put(key, oat_dex_file);
1005     if (canonical_key != key) {
1006       oat_dex_files_.Put(canonical_key, oat_dex_file);
1007     }
1008   }
1009   if (!dex_filenames.empty() && dex_filenames_pos != dex_filenames.size()) {
1010     *error_msg = StringPrintf("Oat file '%s' contains only %zu primary dex locations, expected %zu",
1011                               GetLocation().c_str(),
1012                               dex_filenames_pos,
1013                               dex_filenames.size());
1014     return false;
1015   }
1016 
1017   if (DataBimgRelRoBegin() != nullptr) {
1018     // Make .data.bimg.rel.ro read only. ClassLinker shall temporarily make it writable for
1019     // relocation when we register a dex file from this oat file. We do not do the relocation
1020     // here to avoid dirtying the pages if the code is never actually ready to be executed.
1021     uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin());
1022     CheckedCall(mprotect, "protect relocations", reloc_begin, DataBimgRelRoSize(), PROT_READ);
1023     // Make sure the file lists a boot image dependency, otherwise the .data.bimg.rel.ro
1024     // section is bogus. The full dependency is checked before the code is executed.
1025     // We cannot do this check if we do not have a key-value store, i.e. for secondary
1026     // oat files for boot image extensions.
1027     if (GetOatHeader().GetKeyValueStoreSize() != 0u) {
1028       const char* boot_class_path_checksum =
1029           GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey);
1030       if (boot_class_path_checksum == nullptr ||
1031           boot_class_path_checksum[0] != gc::space::ImageSpace::kImageChecksumPrefix) {
1032         *error_msg = StringPrintf("Oat file '%s' contains .data.bimg.rel.ro section "
1033                                       "without boot image dependency.",
1034                                   GetLocation().c_str());
1035         return false;
1036       }
1037     }
1038   }
1039 
1040   return true;
1041 }
1042 
1043 ////////////////////////
1044 // OatFile via dlopen //
1045 ////////////////////////
1046 
1047 class DlOpenOatFile final : public OatFileBase {
1048  public:
DlOpenOatFile(const std::string & filename,bool executable)1049   DlOpenOatFile(const std::string& filename, bool executable)
1050       : OatFileBase(filename, executable),
1051         dlopen_handle_(nullptr),
1052         shared_objects_before_(0) {
1053   }
1054 
~DlOpenOatFile()1055   ~DlOpenOatFile() {
1056     if (dlopen_handle_ != nullptr) {
1057       if (!kIsTargetBuild) {
1058         MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
1059         host_dlopen_handles_.erase(dlopen_handle_);
1060         dlclose(dlopen_handle_);
1061       } else {
1062         dlclose(dlopen_handle_);
1063       }
1064     }
1065   }
1066 
1067  protected:
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const1068   const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
1069                                           std::string* error_msg) const override {
1070     const uint8_t* ptr =
1071         reinterpret_cast<const uint8_t*>(dlsym(dlopen_handle_, symbol_name.c_str()));
1072     if (ptr == nullptr) {
1073       *error_msg = dlerror();
1074     }
1075     return ptr;
1076   }
1077 
1078   void PreLoad() override;
1079 
1080   bool Load(const std::string& elf_filename,
1081             bool writable,
1082             bool executable,
1083             bool low_4gb,
1084             /*inout*/MemMap* reservation,  // Where to load if not null.
1085             /*out*/std::string* error_msg) override;
1086 
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)1087   bool Load(int oat_fd ATTRIBUTE_UNUSED,
1088             bool writable ATTRIBUTE_UNUSED,
1089             bool executable ATTRIBUTE_UNUSED,
1090             bool low_4gb ATTRIBUTE_UNUSED,
1091             /*inout*/MemMap* reservation ATTRIBUTE_UNUSED,
1092             /*out*/std::string* error_msg ATTRIBUTE_UNUSED) override {
1093     return false;
1094   }
1095 
1096   // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
1097   void PreSetup(const std::string& elf_filename) override;
1098 
1099  private:
1100   bool Dlopen(const std::string& elf_filename,
1101               /*inout*/MemMap* reservation,  // Where to load if not null.
1102               /*out*/std::string* error_msg);
1103 
1104   // On the host, if the same library is loaded again with dlopen the same
1105   // file handle is returned. This differs from the behavior of dlopen on the
1106   // target, where dlopen reloads the library at a different address every
1107   // time you load it. The runtime relies on the target behavior to ensure
1108   // each instance of the loaded library has a unique dex cache. To avoid
1109   // problems, we fall back to our own linker in the case when the same
1110   // library is opened multiple times on host. dlopen_handles_ is used to
1111   // detect that case.
1112   // Guarded by host_dlopen_handles_lock_;
1113   static std::unordered_set<void*> host_dlopen_handles_;
1114 
1115   // Reservation and placeholder memory map objects corresponding to the regions mapped by dlopen.
1116   // Note: Must be destroyed after dlclose() as it can hold the owning reservation.
1117   std::vector<MemMap> dlopen_mmaps_;
1118 
1119   // dlopen handle during runtime.
1120   void* dlopen_handle_;  // TODO: Unique_ptr with custom deleter.
1121 
1122   // The number of shared objects the linker told us about before loading. Used to
1123   // (optimistically) optimize the PreSetup stage (see comment there).
1124   size_t shared_objects_before_;
1125 
1126   DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile);
1127 };
1128 
1129 std::unordered_set<void*> DlOpenOatFile::host_dlopen_handles_;
1130 
PreLoad()1131 void DlOpenOatFile::PreLoad() {
1132 #ifdef __APPLE__
1133   UNUSED(shared_objects_before_);
1134   LOG(FATAL) << "Should not reach here.";
1135   UNREACHABLE();
1136 #else
1137   // Count the entries in dl_iterate_phdr we get at this point in time.
1138   struct dl_iterate_context {
1139     static int callback(dl_phdr_info* info ATTRIBUTE_UNUSED,
1140                         size_t size ATTRIBUTE_UNUSED,
1141                         void* data) {
1142       reinterpret_cast<dl_iterate_context*>(data)->count++;
1143       return 0;  // Continue iteration.
1144     }
1145     size_t count = 0;
1146   } context;
1147 
1148   dl_iterate_phdr(dl_iterate_context::callback, &context);
1149   shared_objects_before_ = context.count;
1150 #endif
1151 }
1152 
Load(const std::string & elf_filename,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1153 bool DlOpenOatFile::Load(const std::string& elf_filename,
1154                          bool writable,
1155                          bool executable,
1156                          bool low_4gb,
1157                          /*inout*/MemMap* reservation,  // Where to load if not null.
1158                          /*out*/std::string* error_msg) {
1159   // Use dlopen only when flagged to do so, and when it's OK to load things executable.
1160   // TODO: Also try when not executable? The issue here could be re-mapping as writable (as
1161   //       !executable is a sign that we may want to patch), which may not be allowed for
1162   //       various reasons.
1163   if (!kUseDlopen) {
1164     *error_msg = "DlOpen is disabled.";
1165     return false;
1166   }
1167   if (low_4gb) {
1168     *error_msg = "DlOpen does not support low 4gb loading.";
1169     return false;
1170   }
1171   if (writable) {
1172     *error_msg = "DlOpen does not support writable loading.";
1173     return false;
1174   }
1175   if (!executable) {
1176     *error_msg = "DlOpen does not support non-executable loading.";
1177     return false;
1178   }
1179 
1180   // dlopen always returns the same library if it is already opened on the host. For this reason
1181   // we only use dlopen if we are the target or we do not already have the dex file opened. Having
1182   // the same library loaded multiple times at different addresses is required for class unloading
1183   // and for having dex caches arrays in the .bss section.
1184   if (!kIsTargetBuild) {
1185     if (!kUseDlopenOnHost) {
1186       *error_msg = "DlOpen disabled for host.";
1187       return false;
1188     }
1189   }
1190 
1191   bool success = Dlopen(elf_filename, reservation, error_msg);
1192   DCHECK(dlopen_handle_ != nullptr || !success);
1193 
1194   return success;
1195 }
1196 
1197 #ifdef ART_TARGET_ANDROID
GetSystemLinkerNamespace()1198 static struct android_namespace_t* GetSystemLinkerNamespace() {
1199   static struct android_namespace_t* system_ns = []() {
1200     // The system namespace is called "default" for binaries in /system and
1201     // "system" for those in the ART APEX. Try "system" first since "default"
1202     // always exists.
1203     // TODO(b/185587109): Get rid of this error prone logic.
1204     struct android_namespace_t* ns = android_get_exported_namespace("system");
1205     if (ns == nullptr) {
1206       ns = android_get_exported_namespace("default");
1207       if (ns == nullptr) {
1208         LOG(FATAL) << "Failed to get system namespace for loading OAT files";
1209       }
1210     }
1211     return ns;
1212   }();
1213   return system_ns;
1214 }
1215 #endif  // ART_TARGET_ANDROID
1216 
Dlopen(const std::string & elf_filename,MemMap * reservation,std::string * error_msg)1217 bool DlOpenOatFile::Dlopen(const std::string& elf_filename,
1218                            /*inout*/MemMap* reservation,
1219                            /*out*/std::string* error_msg) {
1220 #ifdef __APPLE__
1221   // The dl_iterate_phdr syscall is missing.  There is similar API on OSX,
1222   // but let's fallback to the custom loading code for the time being.
1223   UNUSED(elf_filename, reservation);
1224   *error_msg = "Dlopen unsupported on Mac.";
1225   return false;
1226 #else
1227   {
1228     UniqueCPtr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
1229     if (absolute_path == nullptr) {
1230       *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
1231       return false;
1232     }
1233 #ifdef ART_TARGET_ANDROID
1234     android_dlextinfo extinfo = {};
1235     extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;   // Force-load, don't reuse handle
1236                                                 //   (open oat files multiple times).
1237     if (reservation != nullptr) {
1238       if (!reservation->IsValid()) {
1239         *error_msg = StringPrintf("Invalid reservation for %s", elf_filename.c_str());
1240         return false;
1241       }
1242       extinfo.flags |= ANDROID_DLEXT_RESERVED_ADDRESS;          // Use the reserved memory range.
1243       extinfo.reserved_addr = reservation->Begin();
1244       extinfo.reserved_size = reservation->Size();
1245     }
1246 
1247     if (strncmp(kAndroidArtApexDefaultPath,
1248                 absolute_path.get(),
1249                 sizeof(kAndroidArtApexDefaultPath) - 1) != 0 ||
1250         absolute_path.get()[sizeof(kAndroidArtApexDefaultPath) - 1] != '/') {
1251       // Use the system namespace for OAT files outside the ART APEX. Search
1252       // paths and links don't matter here, but permitted paths do, and the
1253       // system namespace is configured to allow loading from all appropriate
1254       // locations.
1255       extinfo.flags |= ANDROID_DLEXT_USE_NAMESPACE;
1256       extinfo.library_namespace = GetSystemLinkerNamespace();
1257     }
1258 
1259     dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
1260     if (reservation != nullptr && dlopen_handle_ != nullptr) {
1261       // Find used pages from the reservation.
1262       struct dl_iterate_context {
1263         static int callback(dl_phdr_info* info, size_t size ATTRIBUTE_UNUSED, void* data) {
1264           auto* context = reinterpret_cast<dl_iterate_context*>(data);
1265           static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1266           using Elf_Half = Elf64_Half;
1267 
1268           // See whether this callback corresponds to the file which we have just loaded.
1269           uint8_t* reservation_begin = context->reservation->Begin();
1270           bool contained_in_reservation = false;
1271           for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1272             if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1273               uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1274                   info->dlpi_phdr[i].p_vaddr);
1275               size_t memsz = info->dlpi_phdr[i].p_memsz;
1276               size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1277               if (offset < context->reservation->Size()) {
1278                 contained_in_reservation = true;
1279                 DCHECK_LE(memsz, context->reservation->Size() - offset);
1280               } else if (vaddr < reservation_begin) {
1281                 // Check that there's no overlap with the reservation.
1282                 DCHECK_LE(memsz, static_cast<size_t>(reservation_begin - vaddr));
1283               }
1284               break;  // It is sufficient to check the first PT_LOAD header.
1285             }
1286           }
1287 
1288           if (contained_in_reservation) {
1289             for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1290               if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1291                 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1292                     info->dlpi_phdr[i].p_vaddr);
1293                 size_t memsz = info->dlpi_phdr[i].p_memsz;
1294                 size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1295                 DCHECK_LT(offset, context->reservation->Size());
1296                 DCHECK_LE(memsz, context->reservation->Size() - offset);
1297                 context->max_size = std::max(context->max_size, offset + memsz);
1298               }
1299             }
1300 
1301             return 1;  // Stop iteration and return 1 from dl_iterate_phdr.
1302           }
1303           return 0;  // Continue iteration and return 0 from dl_iterate_phdr when finished.
1304         }
1305 
1306         const MemMap* const reservation;
1307         size_t max_size = 0u;
1308       };
1309       dl_iterate_context context = { reservation };
1310 
1311       if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1312         LOG(FATAL) << "Could not find the shared object mmapped to the reservation.";
1313         UNREACHABLE();
1314       }
1315 
1316       // Take ownership of the memory used by the shared object. dlopen() does not assume
1317       // full ownership of this memory and dlclose() shall just remap it as zero pages with
1318       // PROT_NONE. We need to unmap the memory when destroying this oat file.
1319       dlopen_mmaps_.push_back(reservation->TakeReservedMemory(context.max_size));
1320     }
1321 #else
1322     static_assert(!kIsTargetBuild || kIsTargetLinux || kIsTargetFuchsia,
1323                   "host_dlopen_handles_ will leak handles");
1324     if (reservation != nullptr) {
1325       *error_msg = StringPrintf("dlopen() into reserved memory is unsupported on host for '%s'.",
1326                                 elf_filename.c_str());
1327       return false;
1328     }
1329     MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
1330     dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
1331     if (dlopen_handle_ != nullptr) {
1332       if (!host_dlopen_handles_.insert(dlopen_handle_).second) {
1333         dlclose(dlopen_handle_);
1334         dlopen_handle_ = nullptr;
1335         *error_msg = StringPrintf("host dlopen re-opened '%s'", elf_filename.c_str());
1336         return false;
1337       }
1338     }
1339 #endif  // ART_TARGET_ANDROID
1340   }
1341   if (dlopen_handle_ == nullptr) {
1342     *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
1343     return false;
1344   }
1345   return true;
1346 #endif
1347 }
1348 
PreSetup(const std::string & elf_filename)1349 void DlOpenOatFile::PreSetup(const std::string& elf_filename) {
1350 #ifdef __APPLE__
1351   UNUSED(elf_filename);
1352   LOG(FATAL) << "Should not reach here.";
1353   UNREACHABLE();
1354 #else
1355   struct PlaceholderMapData {
1356     const char* name;
1357     uint8_t* vaddr;
1358     size_t memsz;
1359   };
1360   struct dl_iterate_context {
1361     static int callback(dl_phdr_info* info, size_t size ATTRIBUTE_UNUSED, void* data) {
1362       auto* context = reinterpret_cast<dl_iterate_context*>(data);
1363       static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1364       using Elf_Half = Elf64_Half;
1365 
1366       context->shared_objects_seen++;
1367       if (context->shared_objects_seen < context->shared_objects_before) {
1368         // We haven't been called yet for anything we haven't seen before. Just continue.
1369         // Note: this is aggressively optimistic. If another thread was unloading a library,
1370         //       we may miss out here. However, this does not happen often in practice.
1371         return 0;
1372       }
1373 
1374       // See whether this callback corresponds to the file which we have just loaded.
1375       bool contains_begin = false;
1376       for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1377         if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1378           uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1379               info->dlpi_phdr[i].p_vaddr);
1380           size_t memsz = info->dlpi_phdr[i].p_memsz;
1381           if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
1382             contains_begin = true;
1383             break;
1384           }
1385         }
1386       }
1387       // Add placeholder mmaps for this file.
1388       if (contains_begin) {
1389         for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1390           if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1391             uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1392                 info->dlpi_phdr[i].p_vaddr);
1393             size_t memsz = info->dlpi_phdr[i].p_memsz;
1394             size_t name_size = strlen(info->dlpi_name) + 1u;
1395             std::vector<char>* placeholder_maps_names = context->placeholder_maps_names_;
1396             // We must not allocate any memory in the callback, see b/156312036 .
1397             if (name_size < placeholder_maps_names->capacity() - placeholder_maps_names->size() &&
1398                 context->placeholder_maps_data_->size() <
1399                     context->placeholder_maps_data_->capacity()) {
1400               placeholder_maps_names->insert(
1401                   placeholder_maps_names->end(), info->dlpi_name, info->dlpi_name + name_size);
1402               const char* name =
1403                   &(*placeholder_maps_names)[placeholder_maps_names->size() - name_size];
1404               context->placeholder_maps_data_->push_back({ name, vaddr, memsz });
1405             }
1406             context->num_placeholder_maps_ += 1u;
1407             context->placeholder_maps_names_size_ += name_size;
1408           }
1409         }
1410         return 1;  // Stop iteration and return 1 from dl_iterate_phdr.
1411       }
1412       return 0;  // Continue iteration and return 0 from dl_iterate_phdr when finished.
1413     }
1414     const uint8_t* const begin_;
1415     std::vector<PlaceholderMapData>* placeholder_maps_data_;
1416     size_t num_placeholder_maps_;
1417     std::vector<char>* placeholder_maps_names_;
1418     size_t placeholder_maps_names_size_;
1419     size_t shared_objects_before;
1420     size_t shared_objects_seen;
1421   };
1422 
1423   // We must not allocate any memory in the callback, see b/156312036 .
1424   // Therefore we pre-allocate storage for the data we need for creating the placeholder maps.
1425   std::vector<PlaceholderMapData> placeholder_maps_data;
1426   placeholder_maps_data.reserve(32);  // 32 should be enough. If not, we'll retry.
1427   std::vector<char> placeholder_maps_names;
1428   placeholder_maps_names.reserve(4 * KB);  // 4KiB should be enough. If not, we'll retry.
1429 
1430   dl_iterate_context context = {
1431       Begin(),
1432       &placeholder_maps_data,
1433       /*num_placeholder_maps_*/ 0u,
1434       &placeholder_maps_names,
1435       /*placeholder_maps_names_size_*/ 0u,
1436       shared_objects_before_,
1437       /*shared_objects_seen*/ 0u
1438   };
1439 
1440   if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1441     // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0
1442     // before giving up. This should be unusual.
1443     VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before="
1444               << shared_objects_before_;
1445     DCHECK(placeholder_maps_data.empty());
1446     DCHECK_EQ(context.num_placeholder_maps_, 0u);
1447     DCHECK(placeholder_maps_names.empty());
1448     DCHECK_EQ(context.placeholder_maps_names_size_, 0u);
1449     context.shared_objects_before = 0u;
1450     context.shared_objects_seen = 0u;
1451     if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1452       // OK, give up and print an error.
1453       PrintFileToLog("/proc/self/maps", android::base::LogSeverity::WARNING);
1454       LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps.";
1455     }
1456   }
1457 
1458   if (placeholder_maps_data.size() < context.num_placeholder_maps_) {
1459     // Insufficient capacity. Reserve more space and retry.
1460     placeholder_maps_data.clear();
1461     placeholder_maps_data.reserve(context.num_placeholder_maps_);
1462     context.num_placeholder_maps_ = 0u;
1463     placeholder_maps_names.clear();
1464     placeholder_maps_names.reserve(context.placeholder_maps_names_size_);
1465     context.placeholder_maps_names_size_ = 0u;
1466     context.shared_objects_before = 0u;
1467     context.shared_objects_seen = 0u;
1468     bool success = (dl_iterate_phdr(dl_iterate_context::callback, &context) != 0);
1469     CHECK(success);
1470   }
1471 
1472   CHECK_EQ(placeholder_maps_data.size(), context.num_placeholder_maps_);
1473   CHECK_EQ(placeholder_maps_names.size(), context.placeholder_maps_names_size_);
1474   DCHECK_EQ(static_cast<size_t>(std::count(placeholder_maps_names.begin(),
1475                                            placeholder_maps_names.end(), '\0')),
1476             context.num_placeholder_maps_);
1477   for (const PlaceholderMapData& data : placeholder_maps_data) {
1478     MemMap mmap = MemMap::MapPlaceholder(data.name, data.vaddr, data.memsz);
1479     dlopen_mmaps_.push_back(std::move(mmap));
1480   }
1481 #endif
1482 }
1483 
1484 ////////////////////////////////////////////////
1485 // OatFile via our own ElfFile implementation //
1486 ////////////////////////////////////////////////
1487 
1488 class ElfOatFile final : public OatFileBase {
1489  public:
ElfOatFile(const std::string & filename,bool executable)1490   ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {}
1491 
1492   bool InitializeFromElfFile(int zip_fd,
1493                              ElfFile* elf_file,
1494                              VdexFile* vdex_file,
1495                              ArrayRef<const std::string> dex_filenames,
1496                              std::string* error_msg);
1497 
1498  protected:
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const1499   const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
1500                                           std::string* error_msg) const override {
1501     const uint8_t* ptr = elf_file_->FindDynamicSymbolAddress(symbol_name);
1502     if (ptr == nullptr) {
1503       *error_msg = "(Internal implementation could not find symbol)";
1504     }
1505     return ptr;
1506   }
1507 
PreLoad()1508   void PreLoad() override {
1509   }
1510 
1511   bool Load(const std::string& elf_filename,
1512             bool writable,
1513             bool executable,
1514             bool low_4gb,
1515             /*inout*/MemMap* reservation,  // Where to load if not null.
1516             /*out*/std::string* error_msg) override;
1517 
1518   bool Load(int oat_fd,
1519             bool writable,
1520             bool executable,
1521             bool low_4gb,
1522             /*inout*/MemMap* reservation,  // Where to load if not null.
1523             /*out*/std::string* error_msg) override;
1524 
PreSetup(const std::string & elf_filename ATTRIBUTE_UNUSED)1525   void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) override {
1526   }
1527 
1528  private:
1529   bool ElfFileOpen(File* file,
1530                    bool writable,
1531                    bool executable,
1532                    bool low_4gb,
1533                    /*inout*/MemMap* reservation,  // Where to load if not null.
1534                    /*out*/std::string* error_msg);
1535 
1536  private:
1537   // Backing memory map for oat file during cross compilation.
1538   std::unique_ptr<ElfFile> elf_file_;
1539 
1540   DISALLOW_COPY_AND_ASSIGN(ElfOatFile);
1541 };
1542 
InitializeFromElfFile(int zip_fd,ElfFile * elf_file,VdexFile * vdex_file,ArrayRef<const std::string> dex_filenames,std::string * error_msg)1543 bool ElfOatFile::InitializeFromElfFile(int zip_fd,
1544                                        ElfFile* elf_file,
1545                                        VdexFile* vdex_file,
1546                                        ArrayRef<const std::string> dex_filenames,
1547                                        std::string* error_msg) {
1548   ScopedTrace trace(__PRETTY_FUNCTION__);
1549   if (IsExecutable()) {
1550     *error_msg = "Cannot initialize from elf file in executable mode.";
1551     return false;
1552   }
1553   elf_file_.reset(elf_file);
1554   SetVdex(vdex_file);
1555   uint64_t offset, size;
1556   bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
1557   CHECK(has_section);
1558   SetBegin(elf_file->Begin() + offset);
1559   SetEnd(elf_file->Begin() + size + offset);
1560   // Ignore the optional .bss section when opening non-executable.
1561   return Setup(zip_fd, dex_filenames, error_msg);
1562 }
1563 
Load(const std::string & elf_filename,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1564 bool ElfOatFile::Load(const std::string& elf_filename,
1565                       bool writable,
1566                       bool executable,
1567                       bool low_4gb,
1568                       /*inout*/MemMap* reservation,
1569                       /*out*/std::string* error_msg) {
1570   ScopedTrace trace(__PRETTY_FUNCTION__);
1571   std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
1572   if (file == nullptr) {
1573     *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
1574     return false;
1575   }
1576   return ElfOatFile::ElfFileOpen(file.get(),
1577                                  writable,
1578                                  executable,
1579                                  low_4gb,
1580                                  reservation,
1581                                  error_msg);
1582 }
1583 
Load(int oat_fd,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1584 bool ElfOatFile::Load(int oat_fd,
1585                       bool writable,
1586                       bool executable,
1587                       bool low_4gb,
1588                       /*inout*/MemMap* reservation,
1589                       /*out*/std::string* error_msg) {
1590   ScopedTrace trace(__PRETTY_FUNCTION__);
1591   if (oat_fd != -1) {
1592     int duped_fd = DupCloexec(oat_fd);
1593     std::unique_ptr<File> file = std::make_unique<File>(duped_fd, false);
1594     if (file == nullptr) {
1595       *error_msg = StringPrintf("Failed to open oat filename for reading: %s",
1596                                 strerror(errno));
1597       return false;
1598     }
1599     return ElfOatFile::ElfFileOpen(file.get(),
1600                                    writable,
1601                                    executable,
1602                                    low_4gb,
1603                                    reservation,
1604                                    error_msg);
1605   }
1606   return false;
1607 }
1608 
ElfFileOpen(File * file,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1609 bool ElfOatFile::ElfFileOpen(File* file,
1610                              bool writable,
1611                              bool executable,
1612                              bool low_4gb,
1613                              /*inout*/MemMap* reservation,
1614                              /*out*/std::string* error_msg) {
1615   ScopedTrace trace(__PRETTY_FUNCTION__);
1616   elf_file_.reset(ElfFile::Open(file,
1617                                 writable,
1618                                 /*program_header_only=*/ true,
1619                                 low_4gb,
1620                                 error_msg));
1621   if (elf_file_ == nullptr) {
1622     DCHECK(!error_msg->empty());
1623     return false;
1624   }
1625   bool loaded = elf_file_->Load(file, executable, low_4gb, reservation, error_msg);
1626   DCHECK(loaded || !error_msg->empty());
1627   return loaded;
1628 }
1629 
1630 class OatFileBackedByVdex final : public OatFileBase {
1631  public:
OatFileBackedByVdex(const std::string & filename)1632   explicit OatFileBackedByVdex(const std::string& filename)
1633       : OatFileBase(filename, /*executable=*/ false) {}
1634 
Open(const std::vector<const DexFile * > & dex_files,std::unique_ptr<VdexFile> && vdex_file,const std::string & location)1635   static OatFileBackedByVdex* Open(const std::vector<const DexFile*>& dex_files,
1636                                    std::unique_ptr<VdexFile>&& vdex_file,
1637                                    const std::string& location) {
1638     std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(location));
1639     // SetVdex will take ownership of the VdexFile.
1640     oat_file->SetVdex(vdex_file.release());
1641     oat_file->SetupHeader(dex_files.size());
1642     // Initialize OatDexFiles.
1643     std::string error_msg;
1644     if (!oat_file->Setup(dex_files, &error_msg)) {
1645       LOG(WARNING) << "Could not create in-memory vdex file: " << error_msg;
1646       return nullptr;
1647     }
1648     return oat_file.release();
1649   }
1650 
Open(int zip_fd,std::unique_ptr<VdexFile> && unique_vdex_file,const std::string & dex_location,std::string * error_msg)1651   static OatFileBackedByVdex* Open(int zip_fd,
1652                                    std::unique_ptr<VdexFile>&& unique_vdex_file,
1653                                    const std::string& dex_location,
1654                                    std::string* error_msg) {
1655     VdexFile* vdex_file = unique_vdex_file.get();
1656     std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(vdex_file->GetName()));
1657     // SetVdex will take ownership of the VdexFile.
1658     oat_file->SetVdex(unique_vdex_file.release());
1659     if (vdex_file->HasDexSection()) {
1660       uint32_t i = 0;
1661       const uint8_t* type_lookup_table_start = nullptr;
1662       for (const uint8_t* dex_file_start = vdex_file->GetNextDexFileData(nullptr, i);
1663            dex_file_start != nullptr;
1664            dex_file_start = vdex_file->GetNextDexFileData(dex_file_start, ++i)) {
1665         const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_start);
1666         if (UNLIKELY(!vdex_file->Contains(dex_file_start))) {
1667           *error_msg =
1668               StringPrintf("In vdex file '%s' found invalid dex file pointer %p not in [%p, %p]",
1669                            dex_location.c_str(),
1670                            dex_file_start,
1671                            vdex_file->Begin(),
1672                            vdex_file->End());
1673           return nullptr;
1674         }
1675         if (UNLIKELY(!vdex_file->Contains(dex_file_start + header->file_size_ - 1))) {
1676           *error_msg =
1677               StringPrintf("In vdex file '%s' found overflowing dex file %p not in [%p, %p]",
1678                            dex_location.c_str(),
1679                            dex_file_start + header->file_size_,
1680                            vdex_file->Begin(),
1681                            vdex_file->End());
1682           return nullptr;
1683         }
1684         if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_start))) {
1685           *error_msg =
1686               StringPrintf("In vdex file '%s' found dex file with invalid dex file version",
1687                            dex_location.c_str());
1688           return nullptr;
1689         }
1690         // Create the OatDexFile and add it to the owning container.
1691         std::string location = DexFileLoader::GetMultiDexLocation(i, dex_location.c_str());
1692         std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(location.c_str());
1693         type_lookup_table_start = vdex_file->GetNextTypeLookupTableData(type_lookup_table_start, i);
1694         const uint8_t* type_lookup_table_data = nullptr;
1695         if (!ComputeAndCheckTypeLookupTableData(*header,
1696                                                 type_lookup_table_start,
1697                                                 vdex_file,
1698                                                 &type_lookup_table_data,
1699                                                 error_msg)) {
1700           return nullptr;
1701         }
1702 
1703         OatDexFile* oat_dex_file = new OatDexFile(oat_file.get(),
1704                                                   dex_file_start,
1705                                                   vdex_file->GetLocationChecksum(i),
1706                                                   location,
1707                                                   canonical_location,
1708                                                   type_lookup_table_data);
1709         oat_file->oat_dex_files_storage_.push_back(oat_dex_file);
1710 
1711         std::string_view key(oat_dex_file->GetDexFileLocation());
1712         oat_file->oat_dex_files_.Put(key, oat_dex_file);
1713         if (canonical_location != location) {
1714           std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
1715           oat_file->oat_dex_files_.Put(canonical_key, oat_dex_file);
1716         }
1717       }
1718       oat_file->SetupHeader(oat_file->oat_dex_files_storage_.size());
1719     } else {
1720       // No need for any verification when loading dex files as we already have
1721       // a vdex file.
1722       const ArtDexFileLoader dex_file_loader;
1723       bool loaded = false;
1724       if (zip_fd != -1) {
1725         loaded = dex_file_loader.OpenZip(zip_fd,
1726                                          dex_location,
1727                                          /*verify=*/ false,
1728                                          /*verify_checksum=*/ false,
1729                                          error_msg,
1730                                          &oat_file->external_dex_files_);
1731       } else {
1732         loaded = dex_file_loader.Open(dex_location.c_str(),
1733                                       dex_location,
1734                                       /*verify=*/ false,
1735                                       /*verify_checksum=*/ false,
1736                                       error_msg,
1737                                       &oat_file->external_dex_files_);
1738       }
1739       if (!loaded) {
1740         return nullptr;
1741       }
1742       oat_file->SetupHeader(oat_file->external_dex_files_.size());
1743       if (!oat_file->Setup(MakeNonOwningPointerVector(oat_file->external_dex_files_), error_msg)) {
1744         return nullptr;
1745       }
1746     }
1747 
1748     return oat_file.release();
1749   }
1750 
SetupHeader(size_t number_of_dex_files)1751   void SetupHeader(size_t number_of_dex_files) {
1752     DCHECK(!IsExecutable());
1753 
1754     // Create a fake OatHeader with a key store to help debugging.
1755     std::unique_ptr<const InstructionSetFeatures> isa_features =
1756         InstructionSetFeatures::FromCppDefines();
1757     SafeMap<std::string, std::string> store;
1758     store.Put(OatHeader::kCompilerFilter, CompilerFilter::NameOfFilter(CompilerFilter::kVerify));
1759     store.Put(OatHeader::kCompilationReasonKey, "vdex");
1760     store.Put(OatHeader::kConcurrentCopying,
1761               kUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
1762     oat_header_.reset(OatHeader::Create(kRuntimeISA,
1763                                         isa_features.get(),
1764                                         number_of_dex_files,
1765                                         &store));
1766     const uint8_t* begin = reinterpret_cast<const uint8_t*>(oat_header_.get());
1767     SetBegin(begin);
1768     SetEnd(begin + oat_header_->GetHeaderSize());
1769   }
1770 
1771  protected:
PreLoad()1772   void PreLoad() override {}
1773 
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)1774   bool Load(const std::string& elf_filename ATTRIBUTE_UNUSED,
1775             bool writable ATTRIBUTE_UNUSED,
1776             bool executable ATTRIBUTE_UNUSED,
1777             bool low_4gb ATTRIBUTE_UNUSED,
1778             MemMap* reservation ATTRIBUTE_UNUSED,
1779             std::string* error_msg ATTRIBUTE_UNUSED) override {
1780     LOG(FATAL) << "Unsupported";
1781     UNREACHABLE();
1782   }
1783 
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)1784   bool Load(int oat_fd ATTRIBUTE_UNUSED,
1785             bool writable ATTRIBUTE_UNUSED,
1786             bool executable ATTRIBUTE_UNUSED,
1787             bool low_4gb ATTRIBUTE_UNUSED,
1788             MemMap* reservation ATTRIBUTE_UNUSED,
1789             std::string* error_msg ATTRIBUTE_UNUSED) override {
1790     LOG(FATAL) << "Unsupported";
1791     UNREACHABLE();
1792   }
1793 
PreSetup(const std::string & elf_filename ATTRIBUTE_UNUSED)1794   void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) override {}
1795 
FindDynamicSymbolAddress(const std::string & symbol_name ATTRIBUTE_UNUSED,std::string * error_msg) const1796   const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name ATTRIBUTE_UNUSED,
1797                                           std::string* error_msg) const override {
1798     *error_msg = "Unsupported";
1799     return nullptr;
1800   }
1801 
1802  private:
1803   std::unique_ptr<OatHeader> oat_header_;
1804 
1805   DISALLOW_COPY_AND_ASSIGN(OatFileBackedByVdex);
1806 };
1807 
1808 //////////////////////////
1809 // General OatFile code //
1810 //////////////////////////
1811 
CheckLocation(const std::string & location)1812 static void CheckLocation(const std::string& location) {
1813   CHECK(!location.empty());
1814 }
1815 
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)1816 OatFile* OatFile::Open(int zip_fd,
1817                        const std::string& oat_filename,
1818                        const std::string& oat_location,
1819                        bool executable,
1820                        bool low_4gb,
1821                        ArrayRef<const std::string> dex_filenames,
1822                        /*inout*/MemMap* reservation,
1823                        /*out*/std::string* error_msg) {
1824   ScopedTrace trace("Open oat file " + oat_location);
1825   CHECK(!oat_filename.empty()) << oat_location;
1826   CheckLocation(oat_location);
1827 
1828   std::string vdex_filename = GetVdexFilename(oat_filename);
1829 
1830   // Check that the vdex file even exists, fast-fail. We don't check the odex
1831   // file as we use the absence of an odex file for test the functionality of
1832   // vdex-only.
1833   if (!OS::FileExists(vdex_filename.c_str())) {
1834     *error_msg = StringPrintf("File %s does not exist.", vdex_filename.c_str());
1835     return nullptr;
1836   }
1837 
1838   // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
1839   // disabled.
1840   OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(zip_fd,
1841                                                                  vdex_filename,
1842                                                                  oat_filename,
1843                                                                  oat_location,
1844                                                                  /*writable=*/ false,
1845                                                                  executable,
1846                                                                  low_4gb,
1847                                                                  dex_filenames,
1848                                                                  reservation,
1849                                                                  error_msg);
1850   if (with_dlopen != nullptr) {
1851     Runtime* runtime = Runtime::Current();
1852     // The runtime might not be available at this point if we're running
1853     // dex2oat or oatdump.
1854     if (runtime != nullptr) {
1855       size_t madvise_size_limit = runtime->GetMadviseWillNeedSizeOdex();
1856       Runtime::MadviseFileForRange(madvise_size_limit,
1857                                    with_dlopen->Size(),
1858                                    with_dlopen->Begin(),
1859                                    with_dlopen->End(),
1860                                    oat_location);
1861     }
1862     return with_dlopen;
1863   }
1864   if (kPrintDlOpenErrorMessage) {
1865     LOG(ERROR) << "Failed to dlopen: " << oat_filename << " with error " << *error_msg;
1866   }
1867   // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
1868   //
1869   // On target, dlopen may fail when compiling due to selinux restrictions on installd.
1870   //
1871   // We use our own ELF loader for Quick to deal with legacy apps that
1872   // open a generated dex file by name, remove the file, then open
1873   // another generated dex file with the same name. http://b/10614658
1874   //
1875   // On host, dlopen is expected to fail when cross compiling, so fall back to ElfOatFile.
1876   //
1877   //
1878   // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
1879   // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN.
1880   OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1881                                                                 vdex_filename,
1882                                                                 oat_filename,
1883                                                                 oat_location,
1884                                                                 /*writable=*/ false,
1885                                                                 executable,
1886                                                                 low_4gb,
1887                                                                 dex_filenames,
1888                                                                 reservation,
1889                                                                 error_msg);
1890   return with_internal;
1891 }
1892 
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)1893 OatFile* OatFile::Open(int zip_fd,
1894                        int vdex_fd,
1895                        int oat_fd,
1896                        const std::string& oat_location,
1897                        bool executable,
1898                        bool low_4gb,
1899                        ArrayRef<const std::string> dex_filenames,
1900                        /*inout*/MemMap* reservation,
1901                        /*out*/std::string* error_msg) {
1902   CHECK(!oat_location.empty()) << oat_location;
1903 
1904   std::string vdex_location = GetVdexFilename(oat_location);
1905 
1906   OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1907                                                                 vdex_fd,
1908                                                                 oat_fd,
1909                                                                 vdex_location,
1910                                                                 oat_location,
1911                                                                 /*writable=*/ false,
1912                                                                 executable,
1913                                                                 low_4gb,
1914                                                                 dex_filenames,
1915                                                                 reservation,
1916                                                                 error_msg);
1917   return with_internal;
1918 }
1919 
OpenFromVdex(const std::vector<const DexFile * > & dex_files,std::unique_ptr<VdexFile> && vdex_file,const std::string & location)1920 OatFile* OatFile::OpenFromVdex(const std::vector<const DexFile*>& dex_files,
1921                                std::unique_ptr<VdexFile>&& vdex_file,
1922                                const std::string& location) {
1923   CheckLocation(location);
1924   return OatFileBackedByVdex::Open(dex_files, std::move(vdex_file), location);
1925 }
1926 
OpenFromVdex(int zip_fd,std::unique_ptr<VdexFile> && vdex_file,const std::string & location,std::string * error_msg)1927 OatFile* OatFile::OpenFromVdex(int zip_fd,
1928                                std::unique_ptr<VdexFile>&& vdex_file,
1929                                const std::string& location,
1930                                std::string* error_msg) {
1931   CheckLocation(location);
1932   return OatFileBackedByVdex::Open(zip_fd, std::move(vdex_file), location, error_msg);
1933 }
1934 
OatFile(const std::string & location,bool is_executable)1935 OatFile::OatFile(const std::string& location, bool is_executable)
1936     : location_(location),
1937       vdex_(nullptr),
1938       begin_(nullptr),
1939       end_(nullptr),
1940       data_bimg_rel_ro_begin_(nullptr),
1941       data_bimg_rel_ro_end_(nullptr),
1942       bss_begin_(nullptr),
1943       bss_end_(nullptr),
1944       bss_methods_(nullptr),
1945       bss_roots_(nullptr),
1946       is_executable_(is_executable),
1947       vdex_begin_(nullptr),
1948       vdex_end_(nullptr),
1949       secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
1950   CHECK(!location_.empty());
1951 }
1952 
~OatFile()1953 OatFile::~OatFile() {
1954   STLDeleteElements(&oat_dex_files_storage_);
1955 }
1956 
GetOatHeader() const1957 const OatHeader& OatFile::GetOatHeader() const {
1958   return *reinterpret_cast<const OatHeader*>(Begin());
1959 }
1960 
Begin() const1961 const uint8_t* OatFile::Begin() const {
1962   CHECK(begin_ != nullptr);
1963   return begin_;
1964 }
1965 
End() const1966 const uint8_t* OatFile::End() const {
1967   CHECK(end_ != nullptr);
1968   return end_;
1969 }
1970 
DexBegin() const1971 const uint8_t* OatFile::DexBegin() const {
1972   return vdex_->Begin();
1973 }
1974 
DexEnd() const1975 const uint8_t* OatFile::DexEnd() const {
1976   return vdex_->End();
1977 }
1978 
GetBootImageRelocations() const1979 ArrayRef<const uint32_t> OatFile::GetBootImageRelocations() const {
1980   if (data_bimg_rel_ro_begin_ != nullptr) {
1981     const uint32_t* relocations = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_begin_);
1982     const uint32_t* relocations_end = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_end_);
1983     return ArrayRef<const uint32_t>(relocations, relocations_end - relocations);
1984   } else {
1985     return ArrayRef<const uint32_t>();
1986   }
1987 }
1988 
GetBssMethods() const1989 ArrayRef<ArtMethod*> OatFile::GetBssMethods() const {
1990   if (bss_methods_ != nullptr) {
1991     ArtMethod** methods = reinterpret_cast<ArtMethod**>(bss_methods_);
1992     ArtMethod** methods_end =
1993         reinterpret_cast<ArtMethod**>(bss_roots_ != nullptr ? bss_roots_ : bss_end_);
1994     return ArrayRef<ArtMethod*>(methods, methods_end - methods);
1995   } else {
1996     return ArrayRef<ArtMethod*>();
1997   }
1998 }
1999 
GetBssGcRoots() const2000 ArrayRef<GcRoot<mirror::Object>> OatFile::GetBssGcRoots() const {
2001   if (bss_roots_ != nullptr) {
2002     auto* roots = reinterpret_cast<GcRoot<mirror::Object>*>(bss_roots_);
2003     auto* roots_end = reinterpret_cast<GcRoot<mirror::Object>*>(bss_end_);
2004     return ArrayRef<GcRoot<mirror::Object>>(roots, roots_end - roots);
2005   } else {
2006     return ArrayRef<GcRoot<mirror::Object>>();
2007   }
2008 }
2009 
GetOatDexFile(const char * dex_location,const uint32_t * dex_location_checksum,std::string * error_msg) const2010 const OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
2011                                          const uint32_t* dex_location_checksum,
2012                                          std::string* error_msg) const {
2013   // NOTE: We assume here that the canonical location for a given dex_location never
2014   // changes. If it does (i.e. some symlink used by the filename changes) we may return
2015   // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
2016   // an identical file or fail; otherwise we may see some unpredictable failures.
2017 
2018   // TODO: Additional analysis of usage patterns to see if this can be simplified
2019   // without any performance loss, for example by not doing the first lock-free lookup.
2020 
2021   const OatDexFile* oat_dex_file = nullptr;
2022   std::string_view key(dex_location);
2023   // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
2024   // directly mentioned in the oat file and doesn't require locking.
2025   auto primary_it = oat_dex_files_.find(key);
2026   if (primary_it != oat_dex_files_.end()) {
2027     oat_dex_file = primary_it->second;
2028     DCHECK(oat_dex_file != nullptr);
2029   } else {
2030     // This dex_location is not one of the dex locations directly mentioned in the
2031     // oat file. The correct lookup is via the canonical location but first see in
2032     // the secondary_oat_dex_files_ whether we've looked up this location before.
2033     MutexLock mu(Thread::Current(), secondary_lookup_lock_);
2034     auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
2035     if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
2036       oat_dex_file = secondary_lb->second;  // May be null.
2037     } else {
2038       // We haven't seen this dex_location before, we must check the canonical location.
2039       std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
2040       if (dex_canonical_location != dex_location) {
2041         std::string_view canonical_key(dex_canonical_location);
2042         auto canonical_it = oat_dex_files_.find(canonical_key);
2043         if (canonical_it != oat_dex_files_.end()) {
2044           oat_dex_file = canonical_it->second;
2045         }  // else keep null.
2046       }  // else keep null.
2047 
2048       // Copy the key to the string_cache_ and store the result in secondary map.
2049       string_cache_.emplace_back(key.data(), key.length());
2050       std::string_view key_copy(string_cache_.back());
2051       secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
2052     }
2053   }
2054 
2055   if (oat_dex_file == nullptr) {
2056     if (error_msg != nullptr) {
2057       std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
2058       *error_msg = "Failed to find OatDexFile for DexFile " + std::string(dex_location)
2059           + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation();
2060     }
2061     return nullptr;
2062   }
2063 
2064   if (dex_location_checksum != nullptr &&
2065       oat_dex_file->GetDexFileLocationChecksum() != *dex_location_checksum) {
2066     if (error_msg != nullptr) {
2067       std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
2068       std::string checksum = StringPrintf("0x%08x", oat_dex_file->GetDexFileLocationChecksum());
2069       std::string required_checksum = StringPrintf("0x%08x", *dex_location_checksum);
2070       *error_msg = "OatDexFile for DexFile " + std::string(dex_location)
2071           + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation()
2072           + " has checksum " + checksum + " but " + required_checksum + " was required";
2073     }
2074     return nullptr;
2075   }
2076   return oat_dex_file;
2077 }
2078 
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)2079 OatDexFile::OatDexFile(const OatFile* oat_file,
2080                        const std::string& dex_file_location,
2081                        const std::string& canonical_dex_file_location,
2082                        uint32_t dex_file_location_checksum,
2083                        const uint8_t* dex_file_pointer,
2084                        const uint8_t* lookup_table_data,
2085                        const IndexBssMapping* method_bss_mapping_data,
2086                        const IndexBssMapping* type_bss_mapping_data,
2087                        const IndexBssMapping* public_type_bss_mapping_data,
2088                        const IndexBssMapping* package_type_bss_mapping_data,
2089                        const IndexBssMapping* string_bss_mapping_data,
2090                        const uint32_t* oat_class_offsets_pointer,
2091                        const DexLayoutSections* dex_layout_sections)
2092     : oat_file_(oat_file),
2093       dex_file_location_(dex_file_location),
2094       canonical_dex_file_location_(canonical_dex_file_location),
2095       dex_file_location_checksum_(dex_file_location_checksum),
2096       dex_file_pointer_(dex_file_pointer),
2097       lookup_table_data_(lookup_table_data),
2098       method_bss_mapping_(method_bss_mapping_data),
2099       type_bss_mapping_(type_bss_mapping_data),
2100       public_type_bss_mapping_(public_type_bss_mapping_data),
2101       package_type_bss_mapping_(package_type_bss_mapping_data),
2102       string_bss_mapping_(string_bss_mapping_data),
2103       oat_class_offsets_pointer_(oat_class_offsets_pointer),
2104       lookup_table_(),
2105       dex_layout_sections_(dex_layout_sections) {
2106   InitializeTypeLookupTable();
2107   DCHECK(!IsBackedByVdexOnly());
2108 }
2109 
InitializeTypeLookupTable()2110 void OatDexFile::InitializeTypeLookupTable() {
2111   // Initialize TypeLookupTable.
2112   if (lookup_table_data_ != nullptr) {
2113     // Peek the number of classes from the DexFile.
2114     const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_);
2115     const uint32_t num_class_defs = dex_header->class_defs_size_;
2116     if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) >
2117             GetOatFile()->DexEnd()) {
2118       LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
2119     } else {
2120       const uint8_t* dex_data = dex_file_pointer_;
2121       // TODO: Clean this up to create the type lookup table after the dex file has been created?
2122       if (CompactDexFile::IsMagicValid(dex_header->magic_)) {
2123         dex_data += dex_header->data_off_;
2124       }
2125       lookup_table_ = TypeLookupTable::Open(dex_data, lookup_table_data_, num_class_defs);
2126     }
2127   }
2128 }
2129 
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)2130 OatDexFile::OatDexFile(const OatFile* oat_file,
2131                        const uint8_t* dex_file_pointer,
2132                        uint32_t dex_file_location_checksum,
2133                        const std::string& dex_file_location,
2134                        const std::string& canonical_dex_file_location,
2135                        const uint8_t* lookup_table_data)
2136     : oat_file_(oat_file),
2137       dex_file_location_(dex_file_location),
2138       canonical_dex_file_location_(canonical_dex_file_location),
2139       dex_file_location_checksum_(dex_file_location_checksum),
2140       dex_file_pointer_(dex_file_pointer),
2141       lookup_table_data_(lookup_table_data) {
2142   InitializeTypeLookupTable();
2143   DCHECK(IsBackedByVdexOnly());
2144 }
2145 
OatDexFile(TypeLookupTable && lookup_table)2146 OatDexFile::OatDexFile(TypeLookupTable&& lookup_table) : lookup_table_(std::move(lookup_table)) {
2147   // Stripped-down OatDexFile only allowed in the compiler, the zygote, or the system server.
2148   CHECK(Runtime::Current() == nullptr ||
2149         Runtime::Current()->IsAotCompiler() ||
2150         Runtime::Current()->IsZygote() ||
2151         Runtime::Current()->IsSystemServer());
2152 }
2153 
~OatDexFile()2154 OatDexFile::~OatDexFile() {}
2155 
FileSize() const2156 size_t OatDexFile::FileSize() const {
2157   DCHECK(dex_file_pointer_ != nullptr);
2158   return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
2159 }
2160 
OpenDexFile(std::string * error_msg) const2161 std::unique_ptr<const DexFile> OatDexFile::OpenDexFile(std::string* error_msg) const {
2162   ScopedTrace trace(__PRETTY_FUNCTION__);
2163   static constexpr bool kVerify = false;
2164   static constexpr bool kVerifyChecksum = false;
2165   const ArtDexFileLoader dex_file_loader;
2166   return dex_file_loader.Open(dex_file_pointer_,
2167                               FileSize(),
2168                               dex_file_location_,
2169                               dex_file_location_checksum_,
2170                               this,
2171                               kVerify,
2172                               kVerifyChecksum,
2173                               error_msg);
2174 }
2175 
GetOatClassOffset(uint16_t class_def_index) const2176 uint32_t OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
2177   DCHECK(oat_class_offsets_pointer_ != nullptr);
2178   return oat_class_offsets_pointer_[class_def_index];
2179 }
2180 
IsBackedByVdexOnly() const2181 bool OatDexFile::IsBackedByVdexOnly() const {
2182   return oat_class_offsets_pointer_ == nullptr;
2183 }
2184 
GetOatClass(uint16_t class_def_index) const2185 OatFile::OatClass OatDexFile::GetOatClass(uint16_t class_def_index) const {
2186   if (IsBackedByVdexOnly()) {
2187     // If there is only a vdex file, return that the class is not ready. The
2188     // caller will have to call `VdexFile::ComputeClassStatus` to compute the
2189     // actual class status, because we need to do the assignability type checks.
2190     return OatFile::OatClass(oat_file_,
2191                              ClassStatus::kNotReady,
2192                              /* type= */ OatClassType::kNoneCompiled,
2193                              /* bitmap_size= */ 0u,
2194                              /* bitmap_pointer= */ nullptr,
2195                              /* methods_pointer= */ nullptr);
2196   }
2197 
2198   uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
2199   CHECK_GE(oat_class_offset, sizeof(OatHeader)) << oat_file_->GetLocation();
2200   CHECK_LT(oat_class_offset, oat_file_->Size()) << oat_file_->GetLocation();
2201   CHECK_LE(/* status */ sizeof(uint16_t) + /* type */ sizeof(uint16_t),
2202            oat_file_->Size() - oat_class_offset) << oat_file_->GetLocation();
2203   const uint8_t* current_pointer = oat_file_->Begin() + oat_class_offset;
2204 
2205   uint16_t status_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2206   current_pointer += sizeof(uint16_t);
2207   uint16_t type_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2208   current_pointer += sizeof(uint16_t);
2209   CHECK_LE(status_value, enum_cast<uint8_t>(ClassStatus::kLast))
2210       << static_cast<uint32_t>(status_value) << " at " << oat_file_->GetLocation();
2211   CHECK_LT(type_value, enum_cast<uint8_t>(OatClassType::kOatClassMax)) << oat_file_->GetLocation();
2212   ClassStatus status = enum_cast<ClassStatus>(status_value);
2213   OatClassType type = enum_cast<OatClassType>(type_value);
2214 
2215   uint32_t num_methods = 0;
2216   const uint32_t* bitmap_pointer = nullptr;
2217   const OatMethodOffsets* methods_pointer = nullptr;
2218   if (type != OatClassType::kNoneCompiled) {
2219     CHECK_LE(sizeof(uint32_t), static_cast<size_t>(oat_file_->End() - current_pointer))
2220         << oat_file_->GetLocation();
2221     num_methods = *reinterpret_cast<const uint32_t*>(current_pointer);
2222     current_pointer += sizeof(uint32_t);
2223     CHECK_NE(num_methods, 0u) << oat_file_->GetLocation();
2224     uint32_t num_method_offsets;
2225     if (type == OatClassType::kSomeCompiled) {
2226       uint32_t bitmap_size = BitVector::BitsToWords(num_methods) * BitVector::kWordBytes;
2227       CHECK_LE(bitmap_size, static_cast<size_t>(oat_file_->End() - current_pointer))
2228           << oat_file_->GetLocation();
2229       bitmap_pointer = reinterpret_cast<const uint32_t*>(current_pointer);
2230       current_pointer += bitmap_size;
2231       // Note: The bits in range [num_methods, bitmap_size * kBitsPerByte)
2232       // should be zero but we're not verifying that.
2233       num_method_offsets = BitVector::NumSetBits(bitmap_pointer, num_methods);
2234     } else {
2235       num_method_offsets = num_methods;
2236     }
2237     CHECK_LE(num_method_offsets,
2238              static_cast<size_t>(oat_file_->End() - current_pointer) / sizeof(OatMethodOffsets))
2239         << oat_file_->GetLocation();
2240     methods_pointer = reinterpret_cast<const OatMethodOffsets*>(current_pointer);
2241   }
2242 
2243   return OatFile::OatClass(oat_file_, status, type, num_methods, bitmap_pointer, methods_pointer);
2244 }
2245 
FindClassDef(const DexFile & dex_file,const char * descriptor,size_t hash)2246 const dex::ClassDef* OatDexFile::FindClassDef(const DexFile& dex_file,
2247                                               const char* descriptor,
2248                                               size_t hash) {
2249   const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2250   DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash);
2251   bool used_lookup_table = false;
2252   const dex::ClassDef* lookup_table_classdef = nullptr;
2253   if (LIKELY((oat_dex_file != nullptr) && oat_dex_file->GetTypeLookupTable().Valid())) {
2254     used_lookup_table = true;
2255     const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable().Lookup(descriptor, hash);
2256     if (class_def_idx != dex::kDexNoIndex) {
2257       CHECK_LT(class_def_idx, dex_file.NumClassDefs()) << oat_dex_file->GetOatFile()->GetLocation();
2258       lookup_table_classdef = &dex_file.GetClassDef(class_def_idx);
2259     }
2260     if (!kIsDebugBuild) {
2261       return lookup_table_classdef;
2262     }
2263   }
2264   // Fast path for rare no class defs case.
2265   const uint32_t num_class_defs = dex_file.NumClassDefs();
2266   if (num_class_defs == 0) {
2267     DCHECK(!used_lookup_table);
2268     return nullptr;
2269   }
2270   const dex::TypeId* type_id = dex_file.FindTypeId(descriptor);
2271   if (type_id != nullptr) {
2272     dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id);
2273     const dex::ClassDef* found_class_def = dex_file.FindClassDef(type_idx);
2274     if (kIsDebugBuild && used_lookup_table) {
2275       DCHECK_EQ(found_class_def, lookup_table_classdef);
2276     }
2277     return found_class_def;
2278   }
2279   return nullptr;
2280 }
2281 
2282 // Madvise the dex file based on the state we are moving to.
MadviseDexFile(const DexFile & dex_file,MadviseState state)2283 void OatDexFile::MadviseDexFile(const DexFile& dex_file, MadviseState state) {
2284   Runtime* const runtime = Runtime::Current();
2285   const bool low_ram = runtime->GetHeap()->IsLowMemoryMode();
2286   // TODO: Also do madvise hints for non low ram devices.
2287   if (!low_ram) {
2288     return;
2289   }
2290   if (state == MadviseState::kMadviseStateAtLoad && runtime->MAdviseRandomAccess()) {
2291     // Default every dex file to MADV_RANDOM when its loaded by default for low ram devices.
2292     // Other devices have enough page cache to get performance benefits from loading more pages
2293     // into the page cache.
2294     DexLayoutSection::MadviseLargestPageAlignedRegion(dex_file.Begin(),
2295                                                       dex_file.Begin() + dex_file.Size(),
2296                                                       MADV_RANDOM);
2297   }
2298   const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2299   if (oat_dex_file != nullptr) {
2300     // Should always be there.
2301     const DexLayoutSections* const sections = oat_dex_file->GetDexLayoutSections();
2302     if (sections != nullptr) {
2303       sections->Madvise(&dex_file, state);
2304     } else {
2305       DCHECK(oat_dex_file->IsBackedByVdexOnly());
2306     }
2307   }
2308 }
2309 
OatClass(const OatFile * oat_file,ClassStatus status,OatClassType type,uint32_t num_methods,const uint32_t * bitmap_pointer,const OatMethodOffsets * methods_pointer)2310 OatFile::OatClass::OatClass(const OatFile* oat_file,
2311                             ClassStatus status,
2312                             OatClassType type,
2313                             uint32_t num_methods,
2314                             const uint32_t* bitmap_pointer,
2315                             const OatMethodOffsets* methods_pointer)
2316     : oat_file_(oat_file),
2317       status_(status),
2318       type_(type),
2319       num_methods_(num_methods),
2320       bitmap_(bitmap_pointer),
2321       methods_pointer_(methods_pointer) {
2322   DCHECK_EQ(num_methods != 0u, type != OatClassType::kNoneCompiled);
2323   DCHECK_EQ(bitmap_pointer != nullptr, type == OatClassType::kSomeCompiled);
2324   DCHECK_EQ(methods_pointer != nullptr, type != OatClassType::kNoneCompiled);
2325 }
2326 
GetOatMethodOffsetsOffset(uint32_t method_index) const2327 uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
2328   const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2329   if (oat_method_offsets == nullptr) {
2330     return 0u;
2331   }
2332   return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
2333 }
2334 
GetOatMethodOffsets(uint32_t method_index) const2335 const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
2336   // NOTE: We don't keep the number of methods for `kNoneCompiled` and cannot do
2337   // a bounds check for `method_index` in that case.
2338   if (methods_pointer_ == nullptr) {
2339     CHECK_EQ(OatClassType::kNoneCompiled, type_);
2340     return nullptr;
2341   }
2342   CHECK_LT(method_index, num_methods_) << oat_file_->GetLocation();
2343   size_t methods_pointer_index;
2344   if (bitmap_ == nullptr) {
2345     CHECK_EQ(OatClassType::kAllCompiled, type_);
2346     methods_pointer_index = method_index;
2347   } else {
2348     CHECK_EQ(OatClassType::kSomeCompiled, type_);
2349     if (!BitVector::IsBitSet(bitmap_, method_index)) {
2350       return nullptr;
2351     }
2352     size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
2353     methods_pointer_index = num_set_bits;
2354   }
2355   if (kIsDebugBuild) {
2356     size_t size_until_end = dchecked_integral_cast<size_t>(
2357         oat_file_->End() - reinterpret_cast<const uint8_t*>(methods_pointer_));
2358     CHECK_LE(methods_pointer_index, size_until_end / sizeof(OatMethodOffsets))
2359         << oat_file_->GetLocation();
2360   }
2361   const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
2362   return &oat_method_offsets;
2363 }
2364 
GetOatMethod(uint32_t method_index) const2365 const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
2366   const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2367   if (oat_method_offsets == nullptr) {
2368     return OatMethod(nullptr, 0);
2369   }
2370   if (oat_file_->IsExecutable() ||
2371       Runtime::Current() == nullptr ||        // This case applies for oatdump.
2372       Runtime::Current()->IsAotCompiler()) {
2373     return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
2374   }
2375   // We aren't allowed to use the compiled code. We just force it down the interpreted / jit
2376   // version.
2377   return OatMethod(oat_file_->Begin(), 0);
2378 }
2379 
IsDebuggable() const2380 bool OatFile::IsDebuggable() const {
2381   return GetOatHeader().IsDebuggable();
2382 }
2383 
GetCompilerFilter() const2384 CompilerFilter::Filter OatFile::GetCompilerFilter() const {
2385   return GetOatHeader().GetCompilerFilter();
2386 }
2387 
GetClassLoaderContext() const2388 std::string OatFile::GetClassLoaderContext() const {
2389   return GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
2390 }
2391 
GetCompilationReason() const2392 const char* OatFile::GetCompilationReason() const {
2393   return GetOatHeader().GetStoreValueByKey(OatHeader::kCompilationReasonKey);
2394 }
2395 
FindOatClass(const DexFile & dex_file,uint16_t class_def_idx,bool * found)2396 OatFile::OatClass OatFile::FindOatClass(const DexFile& dex_file,
2397                                         uint16_t class_def_idx,
2398                                         bool* found) {
2399   DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
2400   const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2401   if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
2402     *found = false;
2403     return OatFile::OatClass::Invalid();
2404   }
2405   *found = true;
2406   return oat_dex_file->GetOatClass(class_def_idx);
2407 }
2408 
RequiresImage() const2409 bool OatFile::RequiresImage() const { return GetOatHeader().RequiresImage(); }
2410 
DCheckIndexToBssMapping(const OatFile * oat_file,uint32_t number_of_indexes,size_t slot_size,const IndexBssMapping * index_bss_mapping)2411 static void DCheckIndexToBssMapping(const OatFile* oat_file,
2412                                     uint32_t number_of_indexes,
2413                                     size_t slot_size,
2414                                     const IndexBssMapping* index_bss_mapping) {
2415   if (kIsDebugBuild && index_bss_mapping != nullptr) {
2416     size_t index_bits = IndexBssMappingEntry::IndexBits(number_of_indexes);
2417     const IndexBssMappingEntry* prev_entry = nullptr;
2418     for (const IndexBssMappingEntry& entry : *index_bss_mapping) {
2419       CHECK_ALIGNED_PARAM(entry.bss_offset, slot_size);
2420       CHECK_LT(entry.bss_offset, oat_file->BssSize());
2421       uint32_t mask = entry.GetMask(index_bits);
2422       CHECK_LE(POPCOUNT(mask) * slot_size, entry.bss_offset);
2423       size_t index_mask_span = (mask != 0u) ? 32u - index_bits - CTZ(mask) : 0u;
2424       CHECK_LE(index_mask_span, entry.GetIndex(index_bits));
2425       if (prev_entry != nullptr) {
2426         CHECK_LT(prev_entry->GetIndex(index_bits), entry.GetIndex(index_bits) - index_mask_span);
2427       }
2428       prev_entry = &entry;
2429     }
2430     CHECK(prev_entry != nullptr);
2431     CHECK_LT(prev_entry->GetIndex(index_bits), number_of_indexes);
2432   }
2433 }
2434 
InitializeRelocations() const2435 void OatFile::InitializeRelocations() const {
2436   DCHECK(IsExecutable());
2437 
2438   // Initialize the .data.bimg.rel.ro section.
2439   if (!GetBootImageRelocations().empty()) {
2440     uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin());
2441     CheckedCall(mprotect,
2442                 "un-protect boot image relocations",
2443                 reloc_begin,
2444                 DataBimgRelRoSize(),
2445                 PROT_READ | PROT_WRITE);
2446     uint32_t boot_image_begin = Runtime::Current()->GetHeap()->GetBootImagesStartAddress();
2447     for (const uint32_t& relocation : GetBootImageRelocations()) {
2448       const_cast<uint32_t&>(relocation) += boot_image_begin;
2449     }
2450     CheckedCall(mprotect,
2451                 "protect boot image relocations",
2452                 reloc_begin,
2453                 DataBimgRelRoSize(),
2454                 PROT_READ);
2455   }
2456 
2457   // Before initializing .bss, check the .bss mappings in debug mode.
2458   if (kIsDebugBuild) {
2459     PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
2460     for (const OatDexFile* odf : GetOatDexFiles()) {
2461       const DexFile::Header* header =
2462           reinterpret_cast<const DexFile::Header*>(odf->GetDexFilePointer());
2463       DCheckIndexToBssMapping(this,
2464                               header->method_ids_size_,
2465                               static_cast<size_t>(pointer_size),
2466                               odf->GetMethodBssMapping());
2467       DCheckIndexToBssMapping(this,
2468                               header->type_ids_size_,
2469                               sizeof(GcRoot<mirror::Class>),
2470                               odf->GetTypeBssMapping());
2471       DCheckIndexToBssMapping(this,
2472                               header->string_ids_size_,
2473                               sizeof(GcRoot<mirror::String>),
2474                               odf->GetStringBssMapping());
2475     }
2476   }
2477 
2478   // Initialize the .bss section.
2479   // TODO: Pre-initialize from boot/app image?
2480   ArtMethod* resolution_method = Runtime::Current()->GetResolutionMethod();
2481   for (ArtMethod*& entry : GetBssMethods()) {
2482     entry = resolution_method;
2483   }
2484 }
2485 
AssertAotCompiler()2486 void OatDexFile::AssertAotCompiler() {
2487   CHECK(Runtime::Current()->IsAotCompiler());
2488 }
2489 
IsBackedByVdexOnly() const2490 bool OatFile::IsBackedByVdexOnly() const {
2491   return oat_dex_files_storage_.size() >= 1 && oat_dex_files_storage_[0]->IsBackedByVdexOnly();
2492 }
2493 
2494 }  // namespace art
2495