• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "oat_file.h"
18 
19 #include <dlfcn.h>
20 #include <string.h>
21 #include <type_traits>
22 #include <unistd.h>
23 
24 #include <cstdlib>
25 #ifndef __APPLE__
26 #include <link.h>  // for dl_iterate_phdr.
27 #endif
28 #include <sstream>
29 
30 // dlopen_ext support from bionic.
31 #ifdef ART_TARGET_ANDROID
32 #include "android/dlext.h"
33 #endif
34 
35 #include "android-base/stringprintf.h"
36 
37 #include "art_method.h"
38 #include "base/bit_vector.h"
39 #include "base/enums.h"
40 #include "base/stl_util.h"
41 #include "base/systrace.h"
42 #include "base/unix_file/fd_file.h"
43 #include "dex_file_types.h"
44 #include "elf_file.h"
45 #include "elf_utils.h"
46 #include "gc_root.h"
47 #include "oat.h"
48 #include "mem_map.h"
49 #include "mirror/class.h"
50 #include "mirror/object-inl.h"
51 #include "oat_file-inl.h"
52 #include "oat_file_manager.h"
53 #include "os.h"
54 #include "runtime.h"
55 #include "type_lookup_table.h"
56 #include "utf-inl.h"
57 #include "utils.h"
58 #include "utils/dex_cache_arrays_layout-inl.h"
59 #include "vdex_file.h"
60 
61 namespace art {
62 
63 using android::base::StringPrintf;
64 
65 // Whether OatFile::Open will try dlopen. Fallback is our own ELF loader.
66 static constexpr bool kUseDlopen = true;
67 
68 // Whether OatFile::Open will try dlopen on the host. On the host we're not linking against
69 // bionic, so cannot take advantage of the support for changed semantics (loading the same soname
70 // multiple times). However, if/when we switch the above, we likely want to switch this, too,
71 // to get test coverage of the code paths.
72 static constexpr bool kUseDlopenOnHost = true;
73 
74 // For debugging, Open will print DlOpen error message if set to true.
75 static constexpr bool kPrintDlOpenErrorMessage = false;
76 
77 // Note for OatFileBase and descendents:
78 //
79 // These are used in OatFile::Open to try all our loaders.
80 //
81 // The process is simple:
82 //
83 // 1) Allocate an instance through the standard constructor (location, executable)
84 // 2) Load() to try to open the file.
85 // 3) ComputeFields() to populate the OatFile fields like begin_, using FindDynamicSymbolAddress.
86 // 4) PreSetup() for any steps that should be done before the final setup.
87 // 5) Setup() to complete the procedure.
88 
89 class OatFileBase : public OatFile {
90  public:
~OatFileBase()91   virtual ~OatFileBase() {}
92 
93   template <typename kOatFileBaseSubType>
94   static OatFileBase* OpenOatFile(const std::string& vdex_filename,
95                                   const std::string& elf_filename,
96                                   const std::string& location,
97                                   uint8_t* requested_base,
98                                   uint8_t* oat_file_begin,
99                                   bool writable,
100                                   bool executable,
101                                   bool low_4gb,
102                                   const char* abs_dex_location,
103                                   std::string* error_msg);
104 
105  protected:
OatFileBase(const std::string & filename,bool executable)106   OatFileBase(const std::string& filename, bool executable) : OatFile(filename, executable) {}
107 
108   virtual const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
109                                                   std::string* error_msg) const = 0;
110 
111   virtual void PreLoad() = 0;
112 
113   bool LoadVdex(const std::string& vdex_filename,
114                 bool writable,
115                 bool low_4gb,
116                 std::string* error_msg);
117 
118   virtual bool Load(const std::string& elf_filename,
119                     uint8_t* oat_file_begin,
120                     bool writable,
121                     bool executable,
122                     bool low_4gb,
123                     std::string* error_msg) = 0;
124 
125   bool ComputeFields(uint8_t* requested_base,
126                      const std::string& file_path,
127                      std::string* error_msg);
128 
129   virtual void PreSetup(const std::string& elf_filename) = 0;
130 
131   bool Setup(const char* abs_dex_location, std::string* error_msg);
132 
133   // Setters exposed for ElfOatFile.
134 
SetBegin(const uint8_t * begin)135   void SetBegin(const uint8_t* begin) {
136     begin_ = begin;
137   }
138 
SetEnd(const uint8_t * end)139   void SetEnd(const uint8_t* end) {
140     end_ = end;
141   }
142 
SetVdex(VdexFile * vdex)143   void SetVdex(VdexFile* vdex) {
144     vdex_.reset(vdex);
145   }
146 
147  private:
148   DISALLOW_COPY_AND_ASSIGN(OatFileBase);
149 };
150 
151 template <typename kOatFileBaseSubType>
OpenOatFile(const std::string & vdex_filename,const std::string & elf_filename,const std::string & location,uint8_t * requested_base,uint8_t * oat_file_begin,bool writable,bool executable,bool low_4gb,const char * abs_dex_location,std::string * error_msg)152 OatFileBase* OatFileBase::OpenOatFile(const std::string& vdex_filename,
153                                       const std::string& elf_filename,
154                                       const std::string& location,
155                                       uint8_t* requested_base,
156                                       uint8_t* oat_file_begin,
157                                       bool writable,
158                                       bool executable,
159                                       bool low_4gb,
160                                       const char* abs_dex_location,
161                                       std::string* error_msg) {
162   std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable));
163 
164   ret->PreLoad();
165 
166   if (kIsVdexEnabled && !ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) {
167     return nullptr;
168   }
169 
170   if (!ret->Load(elf_filename,
171                  oat_file_begin,
172                  writable,
173                  executable,
174                  low_4gb,
175                  error_msg)) {
176     return nullptr;
177   }
178 
179   if (!ret->ComputeFields(requested_base, elf_filename, error_msg)) {
180     return nullptr;
181   }
182 
183   ret->PreSetup(elf_filename);
184 
185   if (!ret->Setup(abs_dex_location, error_msg)) {
186     return nullptr;
187   }
188 
189   return ret.release();
190 }
191 
LoadVdex(const std::string & vdex_filename,bool writable,bool low_4gb,std::string * error_msg)192 bool OatFileBase::LoadVdex(const std::string& vdex_filename,
193                            bool writable,
194                            bool low_4gb,
195                            std::string* error_msg) {
196   vdex_ = VdexFile::Open(vdex_filename, writable, low_4gb, /* unquicken*/ false, error_msg);
197   if (vdex_.get() == nullptr) {
198     *error_msg = StringPrintf("Failed to load vdex file '%s' %s",
199                               vdex_filename.c_str(),
200                               error_msg->c_str());
201     return false;
202   }
203   return true;
204 }
205 
ComputeFields(uint8_t * requested_base,const std::string & file_path,std::string * error_msg)206 bool OatFileBase::ComputeFields(uint8_t* requested_base,
207                                 const std::string& file_path,
208                                 std::string* error_msg) {
209   std::string symbol_error_msg;
210   begin_ = FindDynamicSymbolAddress("oatdata", &symbol_error_msg);
211   if (begin_ == nullptr) {
212     *error_msg = StringPrintf("Failed to find oatdata symbol in '%s' %s",
213                               file_path.c_str(),
214                               symbol_error_msg.c_str());
215     return false;
216   }
217   if (requested_base != nullptr && begin_ != requested_base) {
218     // Host can fail this check. Do not dump there to avoid polluting the output.
219     if (kIsTargetBuild && (kIsDebugBuild || VLOG_IS_ON(oat))) {
220       PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
221     }
222     *error_msg = StringPrintf("Failed to find oatdata symbol at expected address: "
223         "oatdata=%p != expected=%p. See process maps in the log.",
224         begin_, requested_base);
225     return false;
226   }
227   end_ = FindDynamicSymbolAddress("oatlastword", &symbol_error_msg);
228   if (end_ == nullptr) {
229     *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s' %s",
230                               file_path.c_str(),
231                               symbol_error_msg.c_str());
232     return false;
233   }
234   // Readjust to be non-inclusive upper bound.
235   end_ += sizeof(uint32_t);
236 
237   bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg));
238   if (bss_begin_ == nullptr) {
239     // No .bss section.
240     bss_end_ = nullptr;
241   } else {
242     bss_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbsslastword", &symbol_error_msg));
243     if (bss_end_ == nullptr) {
244       *error_msg = StringPrintf("Failed to find oatbasslastword symbol in '%s'", file_path.c_str());
245       return false;
246     }
247     // Readjust to be non-inclusive upper bound.
248     bss_end_ += sizeof(uint32_t);
249     // Find bss methods if present.
250     bss_methods_ =
251         const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssmethods", &symbol_error_msg));
252     // Find bss roots if present.
253     bss_roots_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssroots", &symbol_error_msg));
254   }
255 
256   return true;
257 }
258 
259 // Read an unaligned entry from the OatDexFile data in OatFile and advance the read
260 // position by the number of bytes read, i.e. sizeof(T).
261 // Return true on success, false if the read would go beyond the end of the OatFile.
262 template <typename T>
ReadOatDexFileData(const OatFile & oat_file,const uint8_t ** oat,T * value)263 inline static bool ReadOatDexFileData(const OatFile& oat_file,
264                                       /*inout*/const uint8_t** oat,
265                                       /*out*/T* value) {
266   DCHECK(oat != nullptr);
267   DCHECK(value != nullptr);
268   DCHECK_LE(*oat, oat_file.End());
269   if (UNLIKELY(static_cast<size_t>(oat_file.End() - *oat) < sizeof(T))) {
270     return false;
271   }
272   static_assert(std::is_trivial<T>::value, "T must be a trivial type");
273   typedef __attribute__((__aligned__(1))) T unaligned_type;
274   *value = *reinterpret_cast<const unaligned_type*>(*oat);
275   *oat += sizeof(T);
276   return true;
277 }
278 
FindDexFileMapItem(const uint8_t * dex_begin,const uint8_t * dex_end,DexFile::MapItemType map_item_type,const DexFile::MapItem ** result_item)279 static bool FindDexFileMapItem(const uint8_t* dex_begin,
280                                const uint8_t* dex_end,
281                                DexFile::MapItemType map_item_type,
282                                const DexFile::MapItem** result_item) {
283   *result_item = nullptr;
284 
285   const DexFile::Header* header =
286       BoundsCheckedCast<const DexFile::Header*>(dex_begin, dex_begin, dex_end);
287   if (nullptr == header) return false;
288 
289   if (!DexFile::IsMagicValid(header->magic_)) return true;  // Not a dex file, not an error.
290 
291   const DexFile::MapList* map_list =
292       BoundsCheckedCast<const DexFile::MapList*>(dex_begin + header->map_off_, dex_begin, dex_end);
293   if (nullptr == map_list) return false;
294 
295   const DexFile::MapItem* map_item = map_list->list_;
296   size_t count = map_list->size_;
297   while (count--) {
298     if (map_item->type_ == static_cast<uint16_t>(map_item_type)) {
299       *result_item = map_item;
300       break;
301     }
302     map_item = BoundsCheckedCast<const DexFile::MapItem*>(map_item + 1, dex_begin, dex_end);
303     if (nullptr == map_item) return false;
304   }
305 
306   return true;
307 }
308 
Setup(const char * abs_dex_location,std::string * error_msg)309 bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) {
310   if (!GetOatHeader().IsValid()) {
311     std::string cause = GetOatHeader().GetValidationErrorMessage();
312     *error_msg = StringPrintf("Invalid oat header for '%s': %s",
313                               GetLocation().c_str(),
314                               cause.c_str());
315     return false;
316   }
317   PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
318   size_t key_value_store_size =
319       (Size() >= sizeof(OatHeader)) ? GetOatHeader().GetKeyValueStoreSize() : 0u;
320   if (Size() < sizeof(OatHeader) + key_value_store_size) {
321     *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader, "
322                                   "size = %zu < %zu + %zu",
323                               GetLocation().c_str(),
324                               Size(),
325                               sizeof(OatHeader),
326                               key_value_store_size);
327     return false;
328   }
329 
330   size_t oat_dex_files_offset = GetOatHeader().GetOatDexFilesOffset();
331   if (oat_dex_files_offset < GetOatHeader().GetHeaderSize() || oat_dex_files_offset > Size()) {
332     *error_msg = StringPrintf("In oat file '%s' found invalid oat dex files offset: "
333                                   "%zu is not in [%zu, %zu]",
334                               GetLocation().c_str(),
335                               oat_dex_files_offset,
336                               GetOatHeader().GetHeaderSize(),
337                               Size());
338     return false;
339   }
340   const uint8_t* oat = Begin() + oat_dex_files_offset;  // Jump to the OatDexFile records.
341 
342   DCHECK_GE(static_cast<size_t>(pointer_size), alignof(GcRoot<mirror::Object>));
343   if (!IsAligned<kPageSize>(bss_begin_) ||
344       !IsAlignedParam(bss_methods_, static_cast<size_t>(pointer_size)) ||
345       !IsAlignedParam(bss_roots_, static_cast<size_t>(pointer_size)) ||
346       !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_end_)) {
347     *error_msg = StringPrintf("In oat file '%s' found unaligned bss symbol(s): "
348                                   "begin = %p, methods_ = %p, roots = %p, end = %p",
349                               GetLocation().c_str(),
350                               bss_begin_,
351                               bss_methods_,
352                               bss_roots_,
353                               bss_end_);
354     return false;
355   }
356 
357   if ((bss_methods_ != nullptr && (bss_methods_ < bss_begin_ || bss_methods_ > bss_end_)) ||
358       (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) ||
359       (bss_methods_ != nullptr && bss_roots_ != nullptr && bss_methods_ > bss_roots_)) {
360     *error_msg = StringPrintf("In oat file '%s' found bss symbol(s) outside .bss or unordered: "
361                                   "begin = %p, methods_ = %p, roots = %p, end = %p",
362                               GetLocation().c_str(),
363                               bss_begin_,
364                               bss_methods_,
365                               bss_roots_,
366                               bss_end_);
367     return false;
368   }
369 
370   uint8_t* after_arrays = (bss_methods_ != nullptr) ? bss_methods_ : bss_roots_;  // May be null.
371   uint8_t* dex_cache_arrays = (bss_begin_ == after_arrays) ? nullptr : bss_begin_;
372   uint8_t* dex_cache_arrays_end =
373       (bss_begin_ == after_arrays) ? nullptr : (after_arrays != nullptr) ? after_arrays : bss_end_;
374   DCHECK_EQ(dex_cache_arrays != nullptr, dex_cache_arrays_end != nullptr);
375   uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
376   oat_dex_files_storage_.reserve(dex_file_count);
377   for (size_t i = 0; i < dex_file_count; i++) {
378     uint32_t dex_file_location_size;
379     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
380       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file "
381                                     "location size",
382                                 GetLocation().c_str(),
383                                 i);
384       return false;
385     }
386     if (UNLIKELY(dex_file_location_size == 0U)) {
387       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name",
388                                 GetLocation().c_str(),
389                                 i);
390       return false;
391     }
392     if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) {
393       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file "
394                                     "location",
395                                 GetLocation().c_str(),
396                                 i);
397       return false;
398     }
399     const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
400     oat += dex_file_location_size;
401 
402     std::string dex_file_location = ResolveRelativeEncodedDexLocation(
403         abs_dex_location,
404         std::string(dex_file_location_data, dex_file_location_size));
405 
406     uint32_t dex_file_checksum;
407     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
408       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after "
409                                     "dex file checksum",
410                                 GetLocation().c_str(),
411                                 i,
412                                 dex_file_location.c_str());
413       return false;
414     }
415 
416     uint32_t dex_file_offset;
417     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
418       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
419                                     "after dex file offsets",
420                                 GetLocation().c_str(),
421                                 i,
422                                 dex_file_location.c_str());
423       return false;
424     }
425     if (UNLIKELY(dex_file_offset == 0U)) {
426       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with zero dex "
427                                     "file offset",
428                                 GetLocation().c_str(),
429                                 i,
430                                 dex_file_location.c_str());
431       return false;
432     }
433     if (UNLIKELY(dex_file_offset > DexSize())) {
434       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
435                                     "offset %u > %zu",
436                                 GetLocation().c_str(),
437                                 i,
438                                 dex_file_location.c_str(),
439                                 dex_file_offset,
440                                 DexSize());
441       return false;
442     }
443     if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
444       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
445                                     "offset %u of %zu but the size of dex file header is %zu",
446                                 GetLocation().c_str(),
447                                 i,
448                                 dex_file_location.c_str(),
449                                 dex_file_offset,
450                                 DexSize(),
451                                 sizeof(DexFile::Header));
452       return false;
453     }
454 
455     const uint8_t* dex_file_pointer = DexBegin() + dex_file_offset;
456     if (UNLIKELY(!DexFile::IsMagicValid(dex_file_pointer))) {
457       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
458                                     "dex file magic '%s'",
459                                 GetLocation().c_str(),
460                                 i,
461                                 dex_file_location.c_str(),
462                                 dex_file_pointer);
463       return false;
464     }
465     if (UNLIKELY(!DexFile::IsVersionValid(dex_file_pointer))) {
466       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
467                                     "dex file version '%s'",
468                                 GetLocation().c_str(),
469                                 i,
470                                 dex_file_location.c_str(),
471                                 dex_file_pointer);
472       return false;
473     }
474     const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
475     if (DexSize() - dex_file_offset < header->file_size_) {
476       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
477                                     "offset %u and size %u truncated at %zu",
478                                 GetLocation().c_str(),
479                                 i,
480                                 dex_file_location.c_str(),
481                                 dex_file_offset,
482                                 header->file_size_,
483                                 DexSize());
484       return false;
485     }
486 
487     uint32_t class_offsets_offset;
488     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {
489       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
490                                     "after class offsets offset",
491                                 GetLocation().c_str(),
492                                 i,
493                                 dex_file_location.c_str());
494       return false;
495     }
496     if (UNLIKELY(class_offsets_offset > Size()) ||
497         UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) {
498       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
499                                     "class offsets, offset %u of %zu, class defs %u",
500                                 GetLocation().c_str(),
501                                 i,
502                                 dex_file_location.c_str(),
503                                 class_offsets_offset,
504                                 Size(),
505                                 header->class_defs_size_);
506       return false;
507     }
508     if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) {
509       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned "
510                                     "class offsets, offset %u",
511                                 GetLocation().c_str(),
512                                 i,
513                                 dex_file_location.c_str(),
514                                 class_offsets_offset);
515       return false;
516     }
517     const uint32_t* class_offsets_pointer =
518         reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset);
519 
520     uint32_t lookup_table_offset;
521     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {
522       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
523                                     "after lookup table offset",
524                                 GetLocation().c_str(),
525                                 i,
526                                 dex_file_location.c_str());
527       return false;
528     }
529     const uint8_t* lookup_table_data = lookup_table_offset != 0u
530         ? Begin() + lookup_table_offset
531         : nullptr;
532     if (lookup_table_offset != 0u &&
533         (UNLIKELY(lookup_table_offset > Size()) ||
534             UNLIKELY(Size() - lookup_table_offset <
535                      TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
536       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
537                                     "type lookup table, offset %u of %zu, class defs %u",
538                                 GetLocation().c_str(),
539                                 i,
540                                 dex_file_location.c_str(),
541                                 lookup_table_offset,
542                                 Size(),
543                                 header->class_defs_size_);
544       return false;
545     }
546 
547     uint32_t dex_layout_sections_offset;
548     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_layout_sections_offset))) {
549       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
550                                     "after dex layout sections offset",
551                                 GetLocation().c_str(),
552                                 i,
553                                 dex_file_location.c_str());
554       return false;
555     }
556     const DexLayoutSections* const dex_layout_sections = dex_layout_sections_offset != 0
557         ? reinterpret_cast<const DexLayoutSections*>(Begin() + dex_layout_sections_offset)
558         : nullptr;
559 
560     uint32_t method_bss_mapping_offset;
561     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &method_bss_mapping_offset))) {
562       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
563                                     "after method bss mapping offset",
564                                 GetLocation().c_str(),
565                                 i,
566                                 dex_file_location.c_str());
567       return false;
568     }
569     const bool readable_method_bss_mapping_size =
570         method_bss_mapping_offset != 0u &&
571         method_bss_mapping_offset <= Size() &&
572         IsAligned<alignof(MethodBssMapping)>(method_bss_mapping_offset) &&
573         Size() - method_bss_mapping_offset >= MethodBssMapping::ComputeSize(0);
574     const MethodBssMapping* method_bss_mapping = readable_method_bss_mapping_size
575         ? reinterpret_cast<const MethodBssMapping*>(Begin() + method_bss_mapping_offset)
576         : nullptr;
577     if (method_bss_mapping_offset != 0u &&
578         (UNLIKELY(method_bss_mapping == nullptr) ||
579             UNLIKELY(method_bss_mapping->size() == 0u) ||
580             UNLIKELY(Size() - method_bss_mapping_offset <
581                      MethodBssMapping::ComputeSize(method_bss_mapping->size())))) {
582       *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned or "
583                                     " truncated method bss mapping, offset %u of %zu, length %zu",
584                                 GetLocation().c_str(),
585                                 i,
586                                 dex_file_location.c_str(),
587                                 method_bss_mapping_offset,
588                                 Size(),
589                                 method_bss_mapping != nullptr ? method_bss_mapping->size() : 0u);
590       return false;
591     }
592     if (kIsDebugBuild && method_bss_mapping != nullptr) {
593       const MethodBssMappingEntry* prev_entry = nullptr;
594       for (const MethodBssMappingEntry& entry : *method_bss_mapping) {
595         CHECK_ALIGNED_PARAM(entry.bss_offset, static_cast<size_t>(pointer_size));
596         CHECK_LT(entry.bss_offset, BssSize());
597         CHECK_LE(POPCOUNT(entry.index_mask) * static_cast<size_t>(pointer_size),  entry.bss_offset);
598         size_t index_mask_span = (entry.index_mask != 0u) ? 16u - CTZ(entry.index_mask) : 0u;
599         CHECK_LE(index_mask_span, entry.method_index);
600         if (prev_entry != nullptr) {
601           CHECK_LT(prev_entry->method_index, entry.method_index - index_mask_span);
602         }
603         prev_entry = &entry;
604       }
605       CHECK_LT(prev_entry->method_index,
606                reinterpret_cast<const DexFile::Header*>(dex_file_pointer)->method_ids_size_);
607     }
608 
609     uint8_t* current_dex_cache_arrays = nullptr;
610     if (dex_cache_arrays != nullptr) {
611       // All DexCache types except for CallSite have their instance counts in the
612       // DexFile header. For CallSites, we need to read the info from the MapList.
613       const DexFile::MapItem* call_sites_item = nullptr;
614       if (!FindDexFileMapItem(DexBegin(),
615                               DexEnd(),
616                               DexFile::MapItemType::kDexTypeCallSiteIdItem,
617                               &call_sites_item)) {
618         *error_msg = StringPrintf("In oat file '%s' could not read data from truncated DexFile map",
619                                   GetLocation().c_str());
620         return false;
621       }
622       size_t num_call_sites = call_sites_item == nullptr ? 0 : call_sites_item->size_;
623       DexCacheArraysLayout layout(pointer_size, *header, num_call_sites);
624       if (layout.Size() != 0u) {
625         if (static_cast<size_t>(dex_cache_arrays_end - dex_cache_arrays) < layout.Size()) {
626           *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with "
627                                         "truncated dex cache arrays, %zu < %zu.",
628                                     GetLocation().c_str(),
629                                     i,
630                                     dex_file_location.c_str(),
631                                     static_cast<size_t>(dex_cache_arrays_end - dex_cache_arrays),
632                                     layout.Size());
633           return false;
634         }
635         current_dex_cache_arrays = dex_cache_arrays;
636         dex_cache_arrays += layout.Size();
637       }
638     }
639 
640     std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str());
641 
642     // Create the OatDexFile and add it to the owning container.
643     OatDexFile* oat_dex_file = new OatDexFile(this,
644                                               dex_file_location,
645                                               canonical_location,
646                                               dex_file_checksum,
647                                               dex_file_pointer,
648                                               lookup_table_data,
649                                               method_bss_mapping,
650                                               class_offsets_pointer,
651                                               current_dex_cache_arrays,
652                                               dex_layout_sections);
653     oat_dex_files_storage_.push_back(oat_dex_file);
654 
655     // Add the location and canonical location (if different) to the oat_dex_files_ table.
656     StringPiece key(oat_dex_file->GetDexFileLocation());
657     oat_dex_files_.Put(key, oat_dex_file);
658     if (canonical_location != dex_file_location) {
659       StringPiece canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
660       oat_dex_files_.Put(canonical_key, oat_dex_file);
661     }
662   }
663 
664   if (dex_cache_arrays != dex_cache_arrays_end) {
665     // We expect the bss section to be either empty (dex_cache_arrays and bss_end_
666     // both null) or contain just the dex cache arrays and optionally some GC roots.
667     *error_msg = StringPrintf("In oat file '%s' found unexpected bss size bigger by %zu bytes.",
668                               GetLocation().c_str(),
669                               static_cast<size_t>(bss_end_ - dex_cache_arrays));
670     return false;
671   }
672   return true;
673 }
674 
675 ////////////////////////
676 // OatFile via dlopen //
677 ////////////////////////
678 
679 class DlOpenOatFile FINAL : public OatFileBase {
680  public:
DlOpenOatFile(const std::string & filename,bool executable)681   DlOpenOatFile(const std::string& filename, bool executable)
682       : OatFileBase(filename, executable),
683         dlopen_handle_(nullptr),
684         shared_objects_before_(0) {
685   }
686 
~DlOpenOatFile()687   ~DlOpenOatFile() {
688     if (dlopen_handle_ != nullptr) {
689       if (!kIsTargetBuild) {
690         MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
691         host_dlopen_handles_.erase(dlopen_handle_);
692         dlclose(dlopen_handle_);
693       } else {
694         dlclose(dlopen_handle_);
695       }
696     }
697   }
698 
699  protected:
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const700   const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
701                                           std::string* error_msg) const OVERRIDE {
702     const uint8_t* ptr =
703         reinterpret_cast<const uint8_t*>(dlsym(dlopen_handle_, symbol_name.c_str()));
704     if (ptr == nullptr) {
705       *error_msg = dlerror();
706     }
707     return ptr;
708   }
709 
710   void PreLoad() OVERRIDE;
711 
712   bool Load(const std::string& elf_filename,
713             uint8_t* oat_file_begin,
714             bool writable,
715             bool executable,
716             bool low_4gb,
717             std::string* error_msg) OVERRIDE;
718 
719   // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
720   void PreSetup(const std::string& elf_filename) OVERRIDE;
721 
722  private:
723   bool Dlopen(const std::string& elf_filename,
724               uint8_t* oat_file_begin,
725               std::string* error_msg);
726 
727   // On the host, if the same library is loaded again with dlopen the same
728   // file handle is returned. This differs from the behavior of dlopen on the
729   // target, where dlopen reloads the library at a different address every
730   // time you load it. The runtime relies on the target behavior to ensure
731   // each instance of the loaded library has a unique dex cache. To avoid
732   // problems, we fall back to our own linker in the case when the same
733   // library is opened multiple times on host. dlopen_handles_ is used to
734   // detect that case.
735   // Guarded by host_dlopen_handles_lock_;
736   static std::unordered_set<void*> host_dlopen_handles_;
737 
738   // dlopen handle during runtime.
739   void* dlopen_handle_;  // TODO: Unique_ptr with custom deleter.
740 
741   // Dummy memory map objects corresponding to the regions mapped by dlopen.
742   std::vector<std::unique_ptr<MemMap>> dlopen_mmaps_;
743 
744   // The number of shared objects the linker told us about before loading. Used to
745   // (optimistically) optimize the PreSetup stage (see comment there).
746   size_t shared_objects_before_;
747 
748   DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile);
749 };
750 
751 std::unordered_set<void*> DlOpenOatFile::host_dlopen_handles_;
752 
PreLoad()753 void DlOpenOatFile::PreLoad() {
754 #ifdef __APPLE__
755   UNUSED(shared_objects_before_);
756   LOG(FATAL) << "Should not reach here.";
757   UNREACHABLE();
758 #else
759   // Count the entries in dl_iterate_phdr we get at this point in time.
760   struct dl_iterate_context {
761     static int callback(struct dl_phdr_info *info ATTRIBUTE_UNUSED,
762                         size_t size ATTRIBUTE_UNUSED,
763                         void *data) {
764       reinterpret_cast<dl_iterate_context*>(data)->count++;
765       return 0;  // Continue iteration.
766     }
767     size_t count = 0;
768   } context;
769 
770   dl_iterate_phdr(dl_iterate_context::callback, &context);
771   shared_objects_before_ = context.count;
772 #endif
773 }
774 
Load(const std::string & elf_filename,uint8_t * oat_file_begin,bool writable,bool executable,bool low_4gb,std::string * error_msg)775 bool DlOpenOatFile::Load(const std::string& elf_filename,
776                          uint8_t* oat_file_begin,
777                          bool writable,
778                          bool executable,
779                          bool low_4gb,
780                          std::string* error_msg) {
781   // Use dlopen only when flagged to do so, and when it's OK to load things executable.
782   // TODO: Also try when not executable? The issue here could be re-mapping as writable (as
783   //       !executable is a sign that we may want to patch), which may not be allowed for
784   //       various reasons.
785   if (!kUseDlopen) {
786     *error_msg = "DlOpen is disabled.";
787     return false;
788   }
789   if (low_4gb) {
790     *error_msg = "DlOpen does not support low 4gb loading.";
791     return false;
792   }
793   if (writable) {
794     *error_msg = "DlOpen does not support writable loading.";
795     return false;
796   }
797   if (!executable) {
798     *error_msg = "DlOpen does not support non-executable loading.";
799     return false;
800   }
801 
802   // dlopen always returns the same library if it is already opened on the host. For this reason
803   // we only use dlopen if we are the target or we do not already have the dex file opened. Having
804   // the same library loaded multiple times at different addresses is required for class unloading
805   // and for having dex caches arrays in the .bss section.
806   if (!kIsTargetBuild) {
807     if (!kUseDlopenOnHost) {
808       *error_msg = "DlOpen disabled for host.";
809       return false;
810     }
811   }
812 
813   bool success = Dlopen(elf_filename, oat_file_begin, error_msg);
814   DCHECK(dlopen_handle_ != nullptr || !success);
815 
816   return success;
817 }
818 
Dlopen(const std::string & elf_filename,uint8_t * oat_file_begin,std::string * error_msg)819 bool DlOpenOatFile::Dlopen(const std::string& elf_filename,
820                            uint8_t* oat_file_begin,
821                            std::string* error_msg) {
822 #ifdef __APPLE__
823   // The dl_iterate_phdr syscall is missing.  There is similar API on OSX,
824   // but let's fallback to the custom loading code for the time being.
825   UNUSED(elf_filename, oat_file_begin);
826   *error_msg = "Dlopen unsupported on Mac.";
827   return false;
828 #else
829   {
830     UniqueCPtr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
831     if (absolute_path == nullptr) {
832       *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
833       return false;
834     }
835 #ifdef ART_TARGET_ANDROID
836     android_dlextinfo extinfo = {};
837     extinfo.flags = ANDROID_DLEXT_FORCE_LOAD |                  // Force-load, don't reuse handle
838                                                                 //   (open oat files multiple
839                                                                 //    times).
840                     ANDROID_DLEXT_FORCE_FIXED_VADDR;            // Take a non-zero vaddr as absolute
841                                                                 //   (non-pic boot image).
842     if (oat_file_begin != nullptr) {                            //
843       extinfo.flags |= ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS;     // Use the requested addr if
844       extinfo.reserved_addr = oat_file_begin;                   // vaddr = 0.
845     }                                                           //   (pic boot image).
846     dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
847 #else
848     UNUSED(oat_file_begin);
849     static_assert(!kIsTargetBuild || kIsTargetLinux, "host_dlopen_handles_ will leak handles");
850     MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
851     dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
852     if (dlopen_handle_ != nullptr) {
853       if (!host_dlopen_handles_.insert(dlopen_handle_).second) {
854         dlclose(dlopen_handle_);
855         dlopen_handle_ = nullptr;
856         *error_msg = StringPrintf("host dlopen re-opened '%s'", elf_filename.c_str());
857         return false;
858       }
859     }
860 #endif  // ART_TARGET_ANDROID
861   }
862   if (dlopen_handle_ == nullptr) {
863     *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
864     return false;
865   }
866   return true;
867 #endif
868 }
869 
PreSetup(const std::string & elf_filename)870 void DlOpenOatFile::PreSetup(const std::string& elf_filename) {
871 #ifdef __APPLE__
872   UNUSED(elf_filename);
873   LOG(FATAL) << "Should not reach here.";
874   UNREACHABLE();
875 #else
876   struct dl_iterate_context {
877     static int callback(struct dl_phdr_info *info, size_t /* size */, void *data) {
878       auto* context = reinterpret_cast<dl_iterate_context*>(data);
879       context->shared_objects_seen++;
880       if (context->shared_objects_seen < context->shared_objects_before) {
881         // We haven't been called yet for anything we haven't seen before. Just continue.
882         // Note: this is aggressively optimistic. If another thread was unloading a library,
883         //       we may miss out here. However, this does not happen often in practice.
884         return 0;
885       }
886 
887       // See whether this callback corresponds to the file which we have just loaded.
888       bool contains_begin = false;
889       for (int i = 0; i < info->dlpi_phnum; i++) {
890         if (info->dlpi_phdr[i].p_type == PT_LOAD) {
891           uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
892               info->dlpi_phdr[i].p_vaddr);
893           size_t memsz = info->dlpi_phdr[i].p_memsz;
894           if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
895             contains_begin = true;
896             break;
897           }
898         }
899       }
900       // Add dummy mmaps for this file.
901       if (contains_begin) {
902         for (int i = 0; i < info->dlpi_phnum; i++) {
903           if (info->dlpi_phdr[i].p_type == PT_LOAD) {
904             uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
905                 info->dlpi_phdr[i].p_vaddr);
906             size_t memsz = info->dlpi_phdr[i].p_memsz;
907             MemMap* mmap = MemMap::MapDummy(info->dlpi_name, vaddr, memsz);
908             context->dlopen_mmaps_->push_back(std::unique_ptr<MemMap>(mmap));
909           }
910         }
911         return 1;  // Stop iteration and return 1 from dl_iterate_phdr.
912       }
913       return 0;  // Continue iteration and return 0 from dl_iterate_phdr when finished.
914     }
915     const uint8_t* const begin_;
916     std::vector<std::unique_ptr<MemMap>>* const dlopen_mmaps_;
917     const size_t shared_objects_before;
918     size_t shared_objects_seen;
919   };
920   dl_iterate_context context = { Begin(), &dlopen_mmaps_, shared_objects_before_, 0};
921 
922   if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
923     // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0
924     // before giving up. This should be unusual.
925     VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before="
926               << shared_objects_before_;
927     dl_iterate_context context0 = { Begin(), &dlopen_mmaps_, 0, 0};
928     if (dl_iterate_phdr(dl_iterate_context::callback, &context0) == 0) {
929       // OK, give up and print an error.
930       PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
931       LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps.";
932     }
933   }
934 #endif
935 }
936 
937 ////////////////////////////////////////////////
938 // OatFile via our own ElfFile implementation //
939 ////////////////////////////////////////////////
940 
941 class ElfOatFile FINAL : public OatFileBase {
942  public:
ElfOatFile(const std::string & filename,bool executable)943   ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {}
944 
945   static ElfOatFile* OpenElfFile(File* file,
946                                  const std::string& location,
947                                  uint8_t* requested_base,
948                                  uint8_t* oat_file_begin,  // Override base if not null
949                                  bool writable,
950                                  bool executable,
951                                  bool low_4gb,
952                                  const char* abs_dex_location,
953                                  std::string* error_msg);
954 
955   bool InitializeFromElfFile(ElfFile* elf_file,
956                              VdexFile* vdex_file,
957                              const char* abs_dex_location,
958                              std::string* error_msg);
959 
960  protected:
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const961   const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
962                                           std::string* error_msg) const OVERRIDE {
963     const uint8_t* ptr = elf_file_->FindDynamicSymbolAddress(symbol_name);
964     if (ptr == nullptr) {
965       *error_msg = "(Internal implementation could not find symbol)";
966     }
967     return ptr;
968   }
969 
PreLoad()970   void PreLoad() OVERRIDE {
971   }
972 
973   bool Load(const std::string& elf_filename,
974             uint8_t* oat_file_begin,  // Override where the file is loaded to if not null
975             bool writable,
976             bool executable,
977             bool low_4gb,
978             std::string* error_msg) OVERRIDE;
979 
PreSetup(const std::string & elf_filename ATTRIBUTE_UNUSED)980   void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) OVERRIDE {
981   }
982 
983  private:
984   bool ElfFileOpen(File* file,
985                    uint8_t* oat_file_begin,  // Override where the file is loaded to if not null
986                    bool writable,
987                    bool executable,
988                    bool low_4gb,
989                    std::string* error_msg);
990 
991  private:
992   // Backing memory map for oat file during cross compilation.
993   std::unique_ptr<ElfFile> elf_file_;
994 
995   DISALLOW_COPY_AND_ASSIGN(ElfOatFile);
996 };
997 
OpenElfFile(File * file,const std::string & location,uint8_t * requested_base,uint8_t * oat_file_begin,bool writable,bool executable,bool low_4gb,const char * abs_dex_location,std::string * error_msg)998 ElfOatFile* ElfOatFile::OpenElfFile(File* file,
999                                     const std::string& location,
1000                                     uint8_t* requested_base,
1001                                     uint8_t* oat_file_begin,  // Override base if not null
1002                                     bool writable,
1003                                     bool executable,
1004                                     bool low_4gb,
1005                                     const char* abs_dex_location,
1006                                     std::string* error_msg) {
1007   ScopedTrace trace("Open elf file " + location);
1008   std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, executable));
1009   bool success = oat_file->ElfFileOpen(file,
1010                                        oat_file_begin,
1011                                        writable,
1012                                        low_4gb,
1013                                        executable,
1014                                        error_msg);
1015   if (!success) {
1016     CHECK(!error_msg->empty());
1017     return nullptr;
1018   }
1019 
1020   // Complete the setup.
1021   if (!oat_file->ComputeFields(requested_base, file->GetPath(), error_msg)) {
1022     return nullptr;
1023   }
1024 
1025   if (!oat_file->Setup(abs_dex_location, error_msg)) {
1026     return nullptr;
1027   }
1028 
1029   return oat_file.release();
1030 }
1031 
InitializeFromElfFile(ElfFile * elf_file,VdexFile * vdex_file,const char * abs_dex_location,std::string * error_msg)1032 bool ElfOatFile::InitializeFromElfFile(ElfFile* elf_file,
1033                                        VdexFile* vdex_file,
1034                                        const char* abs_dex_location,
1035                                        std::string* error_msg) {
1036   ScopedTrace trace(__PRETTY_FUNCTION__);
1037   if (IsExecutable()) {
1038     *error_msg = "Cannot initialize from elf file in executable mode.";
1039     return false;
1040   }
1041   elf_file_.reset(elf_file);
1042   SetVdex(vdex_file);
1043   uint64_t offset, size;
1044   bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
1045   CHECK(has_section);
1046   SetBegin(elf_file->Begin() + offset);
1047   SetEnd(elf_file->Begin() + size + offset);
1048   // Ignore the optional .bss section when opening non-executable.
1049   return Setup(abs_dex_location, error_msg);
1050 }
1051 
Load(const std::string & elf_filename,uint8_t * oat_file_begin,bool writable,bool executable,bool low_4gb,std::string * error_msg)1052 bool ElfOatFile::Load(const std::string& elf_filename,
1053                       uint8_t* oat_file_begin,  // Override where the file is loaded to if not null
1054                       bool writable,
1055                       bool executable,
1056                       bool low_4gb,
1057                       std::string* error_msg) {
1058   ScopedTrace trace(__PRETTY_FUNCTION__);
1059   std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
1060   if (file == nullptr) {
1061     *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
1062     return false;
1063   }
1064   return ElfOatFile::ElfFileOpen(file.get(),
1065                                  oat_file_begin,
1066                                  writable,
1067                                  executable,
1068                                  low_4gb,
1069                                  error_msg);
1070 }
1071 
ElfFileOpen(File * file,uint8_t * oat_file_begin,bool writable,bool executable,bool low_4gb,std::string * error_msg)1072 bool ElfOatFile::ElfFileOpen(File* file,
1073                              uint8_t* oat_file_begin,
1074                              bool writable,
1075                              bool executable,
1076                              bool low_4gb,
1077                              std::string* error_msg) {
1078   ScopedTrace trace(__PRETTY_FUNCTION__);
1079   // TODO: rename requested_base to oat_data_begin
1080   elf_file_.reset(ElfFile::Open(file,
1081                                 writable,
1082                                 /*program_header_only*/true,
1083                                 low_4gb,
1084                                 error_msg,
1085                                 oat_file_begin));
1086   if (elf_file_ == nullptr) {
1087     DCHECK(!error_msg->empty());
1088     return false;
1089   }
1090   bool loaded = elf_file_->Load(file, executable, low_4gb, error_msg);
1091   DCHECK(loaded || !error_msg->empty());
1092   return loaded;
1093 }
1094 
1095 //////////////////////////
1096 // General OatFile code //
1097 //////////////////////////
1098 
ResolveRelativeEncodedDexLocation(const char * abs_dex_location,const std::string & rel_dex_location)1099 std::string OatFile::ResolveRelativeEncodedDexLocation(
1100       const char* abs_dex_location, const std::string& rel_dex_location) {
1101   if (abs_dex_location != nullptr && rel_dex_location[0] != '/') {
1102     // Strip :classes<N>.dex used for secondary multidex files.
1103     std::string base = DexFile::GetBaseLocation(rel_dex_location);
1104     std::string multidex_suffix = DexFile::GetMultiDexSuffix(rel_dex_location);
1105 
1106     // Check if the base is a suffix of the provided abs_dex_location.
1107     std::string target_suffix = "/" + base;
1108     std::string abs_location(abs_dex_location);
1109     if (abs_location.size() > target_suffix.size()) {
1110       size_t pos = abs_location.size() - target_suffix.size();
1111       if (abs_location.compare(pos, std::string::npos, target_suffix) == 0) {
1112         return abs_location + multidex_suffix;
1113       }
1114     }
1115   }
1116   return rel_dex_location;
1117 }
1118 
CheckLocation(const std::string & location)1119 static void CheckLocation(const std::string& location) {
1120   CHECK(!location.empty());
1121 }
1122 
OpenWithElfFile(ElfFile * elf_file,VdexFile * vdex_file,const std::string & location,const char * abs_dex_location,std::string * error_msg)1123 OatFile* OatFile::OpenWithElfFile(ElfFile* elf_file,
1124                                   VdexFile* vdex_file,
1125                                   const std::string& location,
1126                                   const char* abs_dex_location,
1127                                   std::string* error_msg) {
1128   std::unique_ptr<ElfOatFile> oat_file(new ElfOatFile(location, false /* executable */));
1129   return oat_file->InitializeFromElfFile(elf_file, vdex_file, abs_dex_location, error_msg)
1130       ? oat_file.release()
1131       : nullptr;
1132 }
1133 
Open(const std::string & oat_filename,const std::string & oat_location,uint8_t * requested_base,uint8_t * oat_file_begin,bool executable,bool low_4gb,const char * abs_dex_location,std::string * error_msg)1134 OatFile* OatFile::Open(const std::string& oat_filename,
1135                        const std::string& oat_location,
1136                        uint8_t* requested_base,
1137                        uint8_t* oat_file_begin,
1138                        bool executable,
1139                        bool low_4gb,
1140                        const char* abs_dex_location,
1141                        std::string* error_msg) {
1142   ScopedTrace trace("Open oat file " + oat_location);
1143   CHECK(!oat_filename.empty()) << oat_location;
1144   CheckLocation(oat_location);
1145 
1146   std::string vdex_filename = GetVdexFilename(oat_filename);
1147 
1148   // Check that the files even exist, fast-fail.
1149   if (kIsVdexEnabled && !OS::FileExists(vdex_filename.c_str())) {
1150     *error_msg = StringPrintf("File %s does not exist.", vdex_filename.c_str());
1151     return nullptr;
1152   } else if (!OS::FileExists(oat_filename.c_str())) {
1153     *error_msg = StringPrintf("File %s does not exist.", oat_filename.c_str());
1154     return nullptr;
1155   }
1156 
1157   // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
1158   // disabled.
1159   OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(vdex_filename,
1160                                                                  oat_filename,
1161                                                                  oat_location,
1162                                                                  requested_base,
1163                                                                  oat_file_begin,
1164                                                                  false /* writable */,
1165                                                                  executable,
1166                                                                  low_4gb,
1167                                                                  abs_dex_location,
1168                                                                  error_msg);
1169   if (with_dlopen != nullptr) {
1170     return with_dlopen;
1171   }
1172   if (kPrintDlOpenErrorMessage) {
1173     LOG(ERROR) << "Failed to dlopen: " << oat_filename << " with error " << *error_msg;
1174   }
1175   // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
1176   //
1177   // On target, dlopen may fail when compiling due to selinux restrictions on installd.
1178   //
1179   // We use our own ELF loader for Quick to deal with legacy apps that
1180   // open a generated dex file by name, remove the file, then open
1181   // another generated dex file with the same name. http://b/10614658
1182   //
1183   // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile.
1184   //
1185   //
1186   // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
1187   // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN.
1188   OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(vdex_filename,
1189                                                                 oat_filename,
1190                                                                 oat_location,
1191                                                                 requested_base,
1192                                                                 oat_file_begin,
1193                                                                 false /* writable */,
1194                                                                 executable,
1195                                                                 low_4gb,
1196                                                                 abs_dex_location,
1197                                                                 error_msg);
1198   return with_internal;
1199 }
1200 
OpenWritable(File * file,const std::string & location,const char * abs_dex_location,std::string * error_msg)1201 OatFile* OatFile::OpenWritable(File* file,
1202                                const std::string& location,
1203                                const char* abs_dex_location,
1204                                std::string* error_msg) {
1205   CheckLocation(location);
1206   return ElfOatFile::OpenElfFile(file,
1207                                  location,
1208                                  nullptr,
1209                                  nullptr,
1210                                  true,
1211                                  false,
1212                                  /*low_4gb*/false,
1213                                  abs_dex_location,
1214                                  error_msg);
1215 }
1216 
OpenReadable(File * file,const std::string & location,const char * abs_dex_location,std::string * error_msg)1217 OatFile* OatFile::OpenReadable(File* file,
1218                                const std::string& location,
1219                                const char* abs_dex_location,
1220                                std::string* error_msg) {
1221   CheckLocation(location);
1222   return ElfOatFile::OpenElfFile(file,
1223                                  location,
1224                                  nullptr,
1225                                  nullptr,
1226                                  false,
1227                                  false,
1228                                  /*low_4gb*/false,
1229                                  abs_dex_location,
1230                                  error_msg);
1231 }
1232 
OatFile(const std::string & location,bool is_executable)1233 OatFile::OatFile(const std::string& location, bool is_executable)
1234     : location_(location),
1235       vdex_(nullptr),
1236       begin_(nullptr),
1237       end_(nullptr),
1238       bss_begin_(nullptr),
1239       bss_end_(nullptr),
1240       bss_methods_(nullptr),
1241       bss_roots_(nullptr),
1242       is_executable_(is_executable),
1243       secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
1244   CHECK(!location_.empty());
1245 }
1246 
~OatFile()1247 OatFile::~OatFile() {
1248   STLDeleteElements(&oat_dex_files_storage_);
1249 }
1250 
GetOatHeader() const1251 const OatHeader& OatFile::GetOatHeader() const {
1252   return *reinterpret_cast<const OatHeader*>(Begin());
1253 }
1254 
Begin() const1255 const uint8_t* OatFile::Begin() const {
1256   CHECK(begin_ != nullptr);
1257   return begin_;
1258 }
1259 
End() const1260 const uint8_t* OatFile::End() const {
1261   CHECK(end_ != nullptr);
1262   return end_;
1263 }
1264 
BssBegin() const1265 const uint8_t* OatFile::BssBegin() const {
1266   return bss_begin_;
1267 }
1268 
BssEnd() const1269 const uint8_t* OatFile::BssEnd() const {
1270   return bss_end_;
1271 }
1272 
DexBegin() const1273 const uint8_t* OatFile::DexBegin() const {
1274   return kIsVdexEnabled ? vdex_->Begin() : Begin();
1275 }
1276 
DexEnd() const1277 const uint8_t* OatFile::DexEnd() const {
1278   return kIsVdexEnabled ? vdex_->End() : End();
1279 }
1280 
GetBssMethods() const1281 ArrayRef<ArtMethod*> OatFile::GetBssMethods() const {
1282   if (bss_methods_ != nullptr) {
1283     ArtMethod** methods = reinterpret_cast<ArtMethod**>(bss_methods_);
1284     ArtMethod** methods_end =
1285         reinterpret_cast<ArtMethod**>(bss_roots_ != nullptr ? bss_roots_ : bss_end_);
1286     return ArrayRef<ArtMethod*>(methods, methods_end - methods);
1287   } else {
1288     return ArrayRef<ArtMethod*>();
1289   }
1290 }
1291 
GetBssGcRoots() const1292 ArrayRef<GcRoot<mirror::Object>> OatFile::GetBssGcRoots() const {
1293   if (bss_roots_ != nullptr) {
1294     auto* roots = reinterpret_cast<GcRoot<mirror::Object>*>(bss_roots_);
1295     auto* roots_end = reinterpret_cast<GcRoot<mirror::Object>*>(bss_end_);
1296     return ArrayRef<GcRoot<mirror::Object>>(roots, roots_end - roots);
1297   } else {
1298     return ArrayRef<GcRoot<mirror::Object>>();
1299   }
1300 }
1301 
GetOatDexFile(const char * dex_location,const uint32_t * dex_location_checksum,std::string * error_msg) const1302 const OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
1303                                                   const uint32_t* dex_location_checksum,
1304                                                   std::string* error_msg) const {
1305   // NOTE: We assume here that the canonical location for a given dex_location never
1306   // changes. If it does (i.e. some symlink used by the filename changes) we may return
1307   // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
1308   // an identical file or fail; otherwise we may see some unpredictable failures.
1309 
1310   // TODO: Additional analysis of usage patterns to see if this can be simplified
1311   // without any performance loss, for example by not doing the first lock-free lookup.
1312 
1313   const OatFile::OatDexFile* oat_dex_file = nullptr;
1314   StringPiece key(dex_location);
1315   // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
1316   // directly mentioned in the oat file and doesn't require locking.
1317   auto primary_it = oat_dex_files_.find(key);
1318   if (primary_it != oat_dex_files_.end()) {
1319     oat_dex_file = primary_it->second;
1320     DCHECK(oat_dex_file != nullptr);
1321   } else {
1322     // This dex_location is not one of the dex locations directly mentioned in the
1323     // oat file. The correct lookup is via the canonical location but first see in
1324     // the secondary_oat_dex_files_ whether we've looked up this location before.
1325     MutexLock mu(Thread::Current(), secondary_lookup_lock_);
1326     auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
1327     if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
1328       oat_dex_file = secondary_lb->second;  // May be null.
1329     } else {
1330       // We haven't seen this dex_location before, we must check the canonical location.
1331       std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
1332       if (dex_canonical_location != dex_location) {
1333         StringPiece canonical_key(dex_canonical_location);
1334         auto canonical_it = oat_dex_files_.find(canonical_key);
1335         if (canonical_it != oat_dex_files_.end()) {
1336           oat_dex_file = canonical_it->second;
1337         }  // else keep null.
1338       }  // else keep null.
1339 
1340       // Copy the key to the string_cache_ and store the result in secondary map.
1341       string_cache_.emplace_back(key.data(), key.length());
1342       StringPiece key_copy(string_cache_.back());
1343       secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
1344     }
1345   }
1346 
1347   if (oat_dex_file == nullptr) {
1348     if (error_msg != nullptr) {
1349       std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
1350       *error_msg = "Failed to find OatDexFile for DexFile " + std::string(dex_location)
1351           + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation();
1352     }
1353     return nullptr;
1354   }
1355 
1356   if (dex_location_checksum != nullptr &&
1357       oat_dex_file->GetDexFileLocationChecksum() != *dex_location_checksum) {
1358     if (error_msg != nullptr) {
1359       std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location);
1360       std::string checksum = StringPrintf("0x%08x", oat_dex_file->GetDexFileLocationChecksum());
1361       std::string required_checksum = StringPrintf("0x%08x", *dex_location_checksum);
1362       *error_msg = "OatDexFile for DexFile " + std::string(dex_location)
1363           + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation()
1364           + " has checksum " + checksum + " but " + required_checksum + " was required";
1365     }
1366     return nullptr;
1367   }
1368   return oat_dex_file;
1369 }
1370 
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 MethodBssMapping * method_bss_mapping_data,const uint32_t * oat_class_offsets_pointer,uint8_t * dex_cache_arrays,const DexLayoutSections * dex_layout_sections)1371 OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
1372                                 const std::string& dex_file_location,
1373                                 const std::string& canonical_dex_file_location,
1374                                 uint32_t dex_file_location_checksum,
1375                                 const uint8_t* dex_file_pointer,
1376                                 const uint8_t* lookup_table_data,
1377                                 const MethodBssMapping* method_bss_mapping_data,
1378                                 const uint32_t* oat_class_offsets_pointer,
1379                                 uint8_t* dex_cache_arrays,
1380                                 const DexLayoutSections* dex_layout_sections)
1381     : oat_file_(oat_file),
1382       dex_file_location_(dex_file_location),
1383       canonical_dex_file_location_(canonical_dex_file_location),
1384       dex_file_location_checksum_(dex_file_location_checksum),
1385       dex_file_pointer_(dex_file_pointer),
1386       lookup_table_data_(lookup_table_data),
1387       method_bss_mapping_(method_bss_mapping_data),
1388       oat_class_offsets_pointer_(oat_class_offsets_pointer),
1389       dex_cache_arrays_(dex_cache_arrays),
1390       dex_layout_sections_(dex_layout_sections) {
1391   // Initialize TypeLookupTable.
1392   if (lookup_table_data_ != nullptr) {
1393     // Peek the number of classes from the DexFile.
1394     const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_);
1395     const uint32_t num_class_defs = dex_header->class_defs_size_;
1396     if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) > GetOatFile()->End()) {
1397       LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
1398     } else {
1399       lookup_table_ = TypeLookupTable::Open(dex_file_pointer_, lookup_table_data_, num_class_defs);
1400     }
1401   }
1402 }
1403 
OatDexFile(std::unique_ptr<TypeLookupTable> && lookup_table)1404 OatFile::OatDexFile::OatDexFile(std::unique_ptr<TypeLookupTable>&& lookup_table)
1405     : lookup_table_(std::move(lookup_table)) {}
1406 
~OatDexFile()1407 OatFile::OatDexFile::~OatDexFile() {}
1408 
FileSize() const1409 size_t OatFile::OatDexFile::FileSize() const {
1410   return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
1411 }
1412 
OpenDexFile(std::string * error_msg) const1413 std::unique_ptr<const DexFile> OatFile::OatDexFile::OpenDexFile(std::string* error_msg) const {
1414   ScopedTrace trace(__PRETTY_FUNCTION__);
1415   static constexpr bool kVerify = false;
1416   static constexpr bool kVerifyChecksum = false;
1417   return DexFile::Open(dex_file_pointer_,
1418                        FileSize(),
1419                        dex_file_location_,
1420                        dex_file_location_checksum_,
1421                        this,
1422                        kVerify,
1423                        kVerifyChecksum,
1424                        error_msg);
1425 }
1426 
GetOatClassOffset(uint16_t class_def_index) const1427 uint32_t OatFile::OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
1428   return oat_class_offsets_pointer_[class_def_index];
1429 }
1430 
GetOatClass(uint16_t class_def_index) const1431 OatFile::OatClass OatFile::OatDexFile::GetOatClass(uint16_t class_def_index) const {
1432   uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
1433 
1434   const uint8_t* oat_class_pointer = oat_file_->Begin() + oat_class_offset;
1435   CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation();
1436 
1437   const uint8_t* status_pointer = oat_class_pointer;
1438   CHECK_LT(status_pointer, oat_file_->End()) << oat_file_->GetLocation();
1439   mirror::Class::Status status =
1440       static_cast<mirror::Class::Status>(*reinterpret_cast<const int16_t*>(status_pointer));
1441   CHECK_LT(status, mirror::Class::kStatusMax);
1442 
1443   const uint8_t* type_pointer = status_pointer + sizeof(uint16_t);
1444   CHECK_LT(type_pointer, oat_file_->End()) << oat_file_->GetLocation();
1445   OatClassType type = static_cast<OatClassType>(*reinterpret_cast<const uint16_t*>(type_pointer));
1446   CHECK_LT(type, kOatClassMax);
1447 
1448   const uint8_t* after_type_pointer = type_pointer + sizeof(int16_t);
1449   CHECK_LE(after_type_pointer, oat_file_->End()) << oat_file_->GetLocation();
1450 
1451   uint32_t bitmap_size = 0;
1452   const uint8_t* bitmap_pointer = nullptr;
1453   const uint8_t* methods_pointer = nullptr;
1454   if (type != kOatClassNoneCompiled) {
1455     if (type == kOatClassSomeCompiled) {
1456       bitmap_size = static_cast<uint32_t>(*reinterpret_cast<const uint32_t*>(after_type_pointer));
1457       bitmap_pointer = after_type_pointer + sizeof(bitmap_size);
1458       CHECK_LE(bitmap_pointer, oat_file_->End()) << oat_file_->GetLocation();
1459       methods_pointer = bitmap_pointer + bitmap_size;
1460     } else {
1461       methods_pointer = after_type_pointer;
1462     }
1463     CHECK_LE(methods_pointer, oat_file_->End()) << oat_file_->GetLocation();
1464   }
1465 
1466   return OatFile::OatClass(oat_file_,
1467                            status,
1468                            type,
1469                            bitmap_size,
1470                            reinterpret_cast<const uint32_t*>(bitmap_pointer),
1471                            reinterpret_cast<const OatMethodOffsets*>(methods_pointer));
1472 }
1473 
FindClassDef(const DexFile & dex_file,const char * descriptor,size_t hash)1474 const DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_file,
1475                                                            const char* descriptor,
1476                                                            size_t hash) {
1477   const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
1478   DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash);
1479   if (LIKELY((oat_dex_file != nullptr) && (oat_dex_file->GetTypeLookupTable() != nullptr))) {
1480     const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable()->Lookup(descriptor, hash);
1481     return (class_def_idx != DexFile::kDexNoIndex) ? &dex_file.GetClassDef(class_def_idx) : nullptr;
1482   }
1483   // Fast path for rare no class defs case.
1484   const uint32_t num_class_defs = dex_file.NumClassDefs();
1485   if (num_class_defs == 0) {
1486     return nullptr;
1487   }
1488   const DexFile::TypeId* type_id = dex_file.FindTypeId(descriptor);
1489   if (type_id != nullptr) {
1490     dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id);
1491     return dex_file.FindClassDef(type_idx);
1492   }
1493   return nullptr;
1494 }
1495 
1496 // Madvise the dex file based on the state we are moving to.
MadviseDexFile(const DexFile & dex_file,MadviseState state)1497 void OatDexFile::MadviseDexFile(const DexFile& dex_file, MadviseState state) {
1498   Runtime* const runtime = Runtime::Current();
1499   const bool low_ram = runtime->GetHeap()->IsLowMemoryMode();
1500   // TODO: Also do madvise hints for non low ram devices.
1501   if (!low_ram) {
1502     return;
1503   }
1504   if (state == MadviseState::kMadviseStateAtLoad && runtime->MAdviseRandomAccess()) {
1505     // Default every dex file to MADV_RANDOM when its loaded by default for low ram devices.
1506     // Other devices have enough page cache to get performance benefits from loading more pages
1507     // into the page cache.
1508     MadviseLargestPageAlignedRegion(dex_file.Begin(),
1509                                     dex_file.Begin() + dex_file.Size(),
1510                                     MADV_RANDOM);
1511   }
1512   const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
1513   if (oat_dex_file != nullptr) {
1514     // Should always be there.
1515     const DexLayoutSections* const sections = oat_dex_file->GetDexLayoutSections();
1516     CHECK(sections != nullptr);
1517     sections->Madvise(&dex_file, state);
1518   }
1519 }
1520 
OatClass(const OatFile * oat_file,mirror::Class::Status status,OatClassType type,uint32_t bitmap_size,const uint32_t * bitmap_pointer,const OatMethodOffsets * methods_pointer)1521 OatFile::OatClass::OatClass(const OatFile* oat_file,
1522                             mirror::Class::Status status,
1523                             OatClassType type,
1524                             uint32_t bitmap_size,
1525                             const uint32_t* bitmap_pointer,
1526                             const OatMethodOffsets* methods_pointer)
1527     : oat_file_(oat_file), status_(status), type_(type),
1528       bitmap_(bitmap_pointer), methods_pointer_(methods_pointer) {
1529     switch (type_) {
1530       case kOatClassAllCompiled: {
1531         CHECK_EQ(0U, bitmap_size);
1532         CHECK(bitmap_pointer == nullptr);
1533         CHECK(methods_pointer != nullptr);
1534         break;
1535       }
1536       case kOatClassSomeCompiled: {
1537         CHECK_NE(0U, bitmap_size);
1538         CHECK(bitmap_pointer != nullptr);
1539         CHECK(methods_pointer != nullptr);
1540         break;
1541       }
1542       case kOatClassNoneCompiled: {
1543         CHECK_EQ(0U, bitmap_size);
1544         CHECK(bitmap_pointer == nullptr);
1545         CHECK(methods_pointer_ == nullptr);
1546         break;
1547       }
1548       case kOatClassMax: {
1549         LOG(FATAL) << "Invalid OatClassType " << type_;
1550         break;
1551       }
1552     }
1553 }
1554 
GetOatMethodOffsetsOffset(uint32_t method_index) const1555 uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
1556   const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
1557   if (oat_method_offsets == nullptr) {
1558     return 0u;
1559   }
1560   return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
1561 }
1562 
GetOatMethodOffsets(uint32_t method_index) const1563 const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
1564   // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index.
1565   if (methods_pointer_ == nullptr) {
1566     CHECK_EQ(kOatClassNoneCompiled, type_);
1567     return nullptr;
1568   }
1569   size_t methods_pointer_index;
1570   if (bitmap_ == nullptr) {
1571     CHECK_EQ(kOatClassAllCompiled, type_);
1572     methods_pointer_index = method_index;
1573   } else {
1574     CHECK_EQ(kOatClassSomeCompiled, type_);
1575     if (!BitVector::IsBitSet(bitmap_, method_index)) {
1576       return nullptr;
1577     }
1578     size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
1579     methods_pointer_index = num_set_bits;
1580   }
1581   const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
1582   return &oat_method_offsets;
1583 }
1584 
GetOatMethod(uint32_t method_index) const1585 const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
1586   const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
1587   if (oat_method_offsets == nullptr) {
1588     return OatMethod(nullptr, 0);
1589   }
1590   if (oat_file_->IsExecutable() ||
1591       Runtime::Current() == nullptr ||        // This case applies for oatdump.
1592       Runtime::Current()->IsAotCompiler()) {
1593     return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
1594   }
1595   // We aren't allowed to use the compiled code. We just force it down the interpreted / jit
1596   // version.
1597   return OatMethod(oat_file_->Begin(), 0);
1598 }
1599 
LinkMethod(ArtMethod * method) const1600 void OatFile::OatMethod::LinkMethod(ArtMethod* method) const {
1601   CHECK(method != nullptr);
1602   method->SetEntryPointFromQuickCompiledCode(GetQuickCode());
1603 }
1604 
IsPic() const1605 bool OatFile::IsPic() const {
1606   return GetOatHeader().IsPic();
1607   // TODO: Check against oat_patches. b/18144996
1608 }
1609 
IsDebuggable() const1610 bool OatFile::IsDebuggable() const {
1611   return GetOatHeader().IsDebuggable();
1612 }
1613 
GetCompilerFilter() const1614 CompilerFilter::Filter OatFile::GetCompilerFilter() const {
1615   return GetOatHeader().GetCompilerFilter();
1616 }
1617 
GetClassLoaderContext() const1618 std::string OatFile::GetClassLoaderContext() const {
1619   return GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
1620 };
1621 
FindOatClass(const DexFile & dex_file,uint16_t class_def_idx,bool * found)1622 OatFile::OatClass OatFile::FindOatClass(const DexFile& dex_file,
1623                                         uint16_t class_def_idx,
1624                                         bool* found) {
1625   DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
1626   const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
1627   if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
1628     *found = false;
1629     return OatFile::OatClass::Invalid();
1630   }
1631   *found = true;
1632   return oat_dex_file->GetOatClass(class_def_idx);
1633 }
1634 
AssertAotCompiler()1635 void OatFile::OatDexFile::AssertAotCompiler() {
1636   CHECK(Runtime::Current()->IsAotCompiler());
1637 }
1638 
1639 }  // namespace art
1640