• 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 #ifndef ART_RUNTIME_OAT_FILE_H_
18 #define ART_RUNTIME_OAT_FILE_H_
19 
20 #include <list>
21 #include <string>
22 #include <string_view>
23 #include <vector>
24 
25 #include "base/array_ref.h"
26 #include "base/mutex.h"
27 #include "base/os.h"
28 #include "base/safe_map.h"
29 #include "base/tracking_safe_map.h"
30 #include "class_status.h"
31 #include "compiler_filter.h"
32 #include "dex/dex_file_layout.h"
33 #include "dex/type_lookup_table.h"
34 #include "dex/utf.h"
35 #include "index_bss_mapping.h"
36 #include "mirror/object.h"
37 #include "oat.h"
38 #include "runtime.h"
39 
40 namespace art {
41 
42 class BitVector;
43 class DexFile;
44 class ElfFile;
45 class DexLayoutSections;
46 template <class MirrorType> class GcRoot;
47 class MemMap;
48 class OatDexFile;
49 class OatHeader;
50 class OatMethodOffsets;
51 class OatQuickMethodHeader;
52 class VdexFile;
53 
54 namespace dex {
55 struct ClassDef;
56 }  // namespace dex
57 
58 namespace gc {
59 namespace collector {
60 class DummyOatFile;
61 }  // namespace collector
62 }  // namespace gc
63 
64 // Runtime representation of the OAT file format which holds compiler output.
65 // The class opens an OAT file from storage and maps it to memory, typically with
66 // dlopen and provides access to its internal data structures (see OatWriter for
67 // for more details about the OAT format).
68 // In the process of loading OAT, the class also loads the associated VDEX file
69 // with the input DEX files (see VdexFile for details about the VDEX format).
70 // The raw DEX data are accessible transparently through the OatDexFile objects.
71 
72 class OatFile {
73  public:
74   // Special classpath that skips shared library check.
75   static constexpr const char* kSpecialSharedLibrary = "&";
76 
77   // Opens an oat file contained within the given elf file. This is always opened as
78   // non-executable at the moment.
79   static OatFile* OpenWithElfFile(int zip_fd,
80                                   ElfFile* elf_file,
81                                   VdexFile* vdex_file,
82                                   const std::string& location,
83                                   const char* abs_dex_location,
84                                   std::string* error_msg);
85   // Open an oat file. Returns null on failure.  Requested base can
86   // optionally be used to request where the file should be loaded.
87   // See the ResolveRelativeEncodedDexLocation for a description of how the
88   // abs_dex_location argument is used.
89   static OatFile* Open(int zip_fd,
90                        const std::string& filename,
91                        const std::string& location,
92                        bool executable,
93                        bool low_4gb,
94                        const char* abs_dex_location,
95                        /*inout*/MemMap* reservation,  // Where to load if not null.
96                        /*out*/std::string* error_msg);
97 
98   // Similar to OatFile::Open(const std::string...), but accepts input vdex and
99   // odex files as file descriptors. We also take zip_fd in case the vdex does not
100   // contain the dex code, and we need to read it from the zip file.
101   static OatFile* Open(int zip_fd,
102                        int vdex_fd,
103                        int oat_fd,
104                        const std::string& oat_location,
105                        bool executable,
106                        bool low_4gb,
107                        const char* abs_dex_location,
108                        /*inout*/MemMap* reservation,  // Where to load if not null.
109                        /*out*/std::string* error_msg);
110 
111   // Open an oat file from an already opened File.
112   // Does not use dlopen underneath so cannot be used for runtime use
113   // where relocations may be required. Currently used from
114   // ImageWriter which wants to open a writable version from an existing
115   // file descriptor for patching.
116   static OatFile* OpenWritable(int zip_fd,
117                                File* file,
118                                const std::string& location,
119                                const char* abs_dex_location,
120                                std::string* error_msg);
121   // Open an oat file from an already opened File. Maps it PROT_READ, MAP_PRIVATE.
122   static OatFile* OpenReadable(int zip_fd,
123                                File* file,
124                                const std::string& location,
125                                const char* abs_dex_location,
126                                std::string* error_msg);
127 
128   // Initialize OatFile instance from an already loaded VdexFile. This assumes
129   // the vdex does not have a dex section and accepts a vector of DexFiles separately.
130   static OatFile* OpenFromVdex(const std::vector<const DexFile*>& dex_files,
131                                std::unique_ptr<VdexFile>&& vdex_file,
132                                const std::string& location);
133 
134   virtual ~OatFile();
135 
IsExecutable()136   bool IsExecutable() const {
137     return is_executable_;
138   }
139 
140   // Indicates whether the oat file was compiled with full debugging capability.
141   bool IsDebuggable() const;
142 
143   CompilerFilter::Filter GetCompilerFilter() const;
144 
145   std::string GetClassLoaderContext() const;
146 
147   const char* GetCompilationReason() const;
148 
GetLocation()149   const std::string& GetLocation() const {
150     return location_;
151   }
152 
153   const OatHeader& GetOatHeader() const;
154 
155   class OatMethod final {
156    public:
157     void LinkMethod(ArtMethod* method) const;
158 
159     uint32_t GetCodeOffset() const;
160 
161     const void* GetQuickCode() const;
162 
163     // Returns size of quick code.
164     uint32_t GetQuickCodeSize() const;
165     uint32_t GetQuickCodeSizeOffset() const;
166 
167     // Returns OatQuickMethodHeader for debugging. Most callers should
168     // use more specific methods such as GetQuickCodeSize.
169     const OatQuickMethodHeader* GetOatQuickMethodHeader() const;
170     uint32_t GetOatQuickMethodHeaderOffset() const;
171 
172     size_t GetFrameSizeInBytes() const;
173     uint32_t GetCoreSpillMask() const;
174     uint32_t GetFpSpillMask() const;
175 
176     const uint8_t* GetVmapTable() const;
177     uint32_t GetVmapTableOffset() const;
178     uint32_t GetVmapTableOffsetOffset() const;
179 
180     // Create an OatMethod with offsets relative to the given base address
OatMethod(const uint8_t * base,const uint32_t code_offset)181     OatMethod(const uint8_t* base, const uint32_t code_offset)
182         : begin_(base), code_offset_(code_offset) {
183     }
184     OatMethod(const OatMethod&) = default;
~OatMethod()185     ~OatMethod() {}
186 
187     OatMethod& operator=(const OatMethod&) = default;
188 
189     // A representation of an invalid OatMethod, used when an OatMethod or OatClass can't be found.
190     // See ClassLinker::FindOatMethodFor.
Invalid()191     static const OatMethod Invalid() {
192       return OatMethod(nullptr, -1);
193     }
194 
195    private:
196     template<class T>
GetOatPointer(uint32_t offset)197     T GetOatPointer(uint32_t offset) const {
198       if (offset == 0) {
199         return nullptr;
200       }
201       return reinterpret_cast<T>(begin_ + offset);
202     }
203 
204     const uint8_t* begin_;
205     uint32_t code_offset_;
206 
207     friend class OatClass;
208   };
209 
210   class OatClass final {
211    public:
GetStatus()212     ClassStatus GetStatus() const {
213       return status_;
214     }
215 
GetType()216     OatClassType GetType() const {
217       return type_;
218     }
219 
220     // Get the OatMethod entry based on its index into the class
221     // defintion. Direct methods come first, followed by virtual
222     // methods. Note that runtime created methods such as miranda
223     // methods are not included.
224     const OatMethod GetOatMethod(uint32_t method_index) const;
225 
226     // Return a pointer to the OatMethodOffsets for the requested
227     // method_index, or null if none is present. Note that most
228     // callers should use GetOatMethod.
229     const OatMethodOffsets* GetOatMethodOffsets(uint32_t method_index) const;
230 
231     // Return the offset from the start of the OatFile to the
232     // OatMethodOffsets for the requested method_index, or 0 if none
233     // is present. Note that most callers should use GetOatMethod.
234     uint32_t GetOatMethodOffsetsOffset(uint32_t method_index) const;
235 
236     // A representation of an invalid OatClass, used when an OatClass can't be found.
237     // See FindOatClass().
Invalid()238     static OatClass Invalid() {
239       return OatClass(/* oat_file= */ nullptr,
240                       ClassStatus::kErrorUnresolved,
241                       kOatClassNoneCompiled,
242                       /* bitmap_size= */ 0,
243                       /* bitmap_pointer= */ nullptr,
244                       /* methods_pointer= */ nullptr);
245     }
246 
247    private:
248     OatClass(const OatFile* oat_file,
249              ClassStatus status,
250              OatClassType type,
251              uint32_t bitmap_size,
252              const uint32_t* bitmap_pointer,
253              const OatMethodOffsets* methods_pointer);
254 
255     const OatFile* const oat_file_;
256 
257     const ClassStatus status_;
258 
259     const OatClassType type_;
260 
261     const uint32_t* const bitmap_;
262 
263     const OatMethodOffsets* const methods_pointer_;
264 
265     friend class art::OatDexFile;
266   };
267 
268   // Get the OatDexFile for the given dex_location within this oat file.
269   // If dex_location_checksum is non-null, the OatDexFile will only be
270   // returned if it has a matching checksum.
271   // If error_msg is non-null and no OatDexFile is returned, error_msg will
272   // be updated with a description of why no OatDexFile was returned.
273   const OatDexFile* GetOatDexFile(const char* dex_location,
274                                   const uint32_t* const dex_location_checksum,
275                                   /*out*/std::string* error_msg = nullptr) const
276       REQUIRES(!secondary_lookup_lock_);
277 
GetOatDexFiles()278   const std::vector<const OatDexFile*>& GetOatDexFiles() const {
279     return oat_dex_files_storage_;
280   }
281 
Size()282   size_t Size() const {
283     return End() - Begin();
284   }
285 
Contains(const void * p)286   bool Contains(const void* p) const {
287     return p >= Begin() && p < End();
288   }
289 
DataBimgRelRoSize()290   size_t DataBimgRelRoSize() const {
291     return DataBimgRelRoEnd() - DataBimgRelRoBegin();
292   }
293 
BssSize()294   size_t BssSize() const {
295     return BssEnd() - BssBegin();
296   }
297 
VdexSize()298   size_t VdexSize() const {
299     return VdexEnd() - VdexBegin();
300   }
301 
BssMethodsOffset()302   size_t BssMethodsOffset() const {
303     // Note: This is used only for symbolizer and needs to return a valid .bss offset.
304     return (bss_methods_ != nullptr) ? bss_methods_ - BssBegin() : BssRootsOffset();
305   }
306 
BssRootsOffset()307   size_t BssRootsOffset() const {
308     // Note: This is used only for symbolizer and needs to return a valid .bss offset.
309     return (bss_roots_ != nullptr) ? bss_roots_ - BssBegin() : BssSize();
310   }
311 
DexSize()312   size_t DexSize() const {
313     return DexEnd() - DexBegin();
314   }
315 
316   const uint8_t* Begin() const;
317   const uint8_t* End() const;
318 
DataBimgRelRoBegin()319   const uint8_t* DataBimgRelRoBegin() const { return data_bimg_rel_ro_begin_; }
DataBimgRelRoEnd()320   const uint8_t* DataBimgRelRoEnd() const { return data_bimg_rel_ro_end_; }
321 
BssBegin()322   const uint8_t* BssBegin() const { return bss_begin_; }
BssEnd()323   const uint8_t* BssEnd() const { return bss_end_; }
324 
VdexBegin()325   const uint8_t* VdexBegin() const { return vdex_begin_; }
VdexEnd()326   const uint8_t* VdexEnd() const { return vdex_end_; }
327 
328   const uint8_t* DexBegin() const;
329   const uint8_t* DexEnd() const;
330 
331   ArrayRef<const uint32_t> GetBootImageRelocations() const;
332   ArrayRef<ArtMethod*> GetBssMethods() const;
333   ArrayRef<GcRoot<mirror::Object>> GetBssGcRoots() const;
334 
335   // Initialize relocation sections (.data.bimg.rel.ro and .bss).
336   void InitializeRelocations() const;
337 
338   // Constructs the absolute dex location and/or dex file name for the relative dex
339   // location (`rel_dex_location`) in the oat file, using the `abs_dex_location` of
340   // the dex file this oat belongs to.
341   //
342   // The dex file name and dex location differ when cross compiling where the dex file
343   // name is the host path (for opening files) and dex location is the future path on target.
344   //
345   // If not null, abs_dex_location is used to resolve the absolute dex
346   // location of relative dex locations encoded in the oat file.
347   // For example, given absolute location "/data/app/foo/base.apk", encoded
348   // dex locations "base.apk", "base.apk!classes2.dex", etc. would be resolved
349   // to "/data/app/foo/base.apk", "/data/app/foo/base.apk!classes2.dex", etc.
350   // Relative encoded dex locations that don't match the given abs_dex_location
351   // are left unchanged.
352   //
353   // Computation of both `dex_file_location` and `dex_file_name` can be skipped
354   // by setting the corresponding out parameter to `nullptr`.
355   static void ResolveRelativeEncodedDexLocation(const char* abs_dex_location,
356                                                 const std::string& rel_dex_location,
357                                                 /* out */ std::string* dex_file_location,
358                                                 /* out */ std::string* dex_file_name = nullptr);
359 
360   // Finds the associated oat class for a dex_file and descriptor. Returns an invalid OatClass on
361   // error and sets found to false.
362   static OatClass FindOatClass(const DexFile& dex_file, uint16_t class_def_idx, bool* found);
363 
GetVdexFile()364   VdexFile* GetVdexFile() const {
365     return vdex_.get();
366   }
367 
368   // Whether the OatFile embeds the Dex code.
ContainsDexCode()369   bool ContainsDexCode() const {
370     return uncompressed_dex_files_ == nullptr;
371   }
372 
373  protected:
374   OatFile(const std::string& filename, bool executable);
375 
376  private:
377   // The oat file name.
378   //
379   // The image will embed this to link its associated oat file.
380   const std::string location_;
381 
382   // Pointer to the Vdex file with the Dex files for this Oat file.
383   std::unique_ptr<VdexFile> vdex_;
384 
385   // Pointer to OatHeader.
386   const uint8_t* begin_;
387 
388   // Pointer to end of oat region for bounds checking.
389   const uint8_t* end_;
390 
391   // Pointer to the .data.bimg.rel.ro section, if present, otherwise null.
392   const uint8_t* data_bimg_rel_ro_begin_;
393 
394   // Pointer to the end of the .data.bimg.rel.ro section, if present, otherwise null.
395   const uint8_t* data_bimg_rel_ro_end_;
396 
397   // Pointer to the .bss section, if present, otherwise null.
398   uint8_t* bss_begin_;
399 
400   // Pointer to the end of the .bss section, if present, otherwise null.
401   uint8_t* bss_end_;
402 
403   // Pointer to the beginning of the ArtMethod*s in .bss section, if present, otherwise null.
404   uint8_t* bss_methods_;
405 
406   // Pointer to the beginning of the GC roots in .bss section, if present, otherwise null.
407   uint8_t* bss_roots_;
408 
409   // Was this oat_file loaded executable?
410   const bool is_executable_;
411 
412   // Pointer to the .vdex section, if present, otherwise null.
413   uint8_t* vdex_begin_;
414 
415   // Pointer to the end of the .vdex section, if present, otherwise null.
416   uint8_t* vdex_end_;
417 
418   // Owning storage for the OatDexFile objects.
419   std::vector<const OatDexFile*> oat_dex_files_storage_;
420 
421   // NOTE: We use a std::string_view as the key type to avoid a memory allocation on every
422   // lookup with a const char* key. The std::string_view doesn't own its backing storage,
423   // therefore we're using the OatFile's stored dex location as the backing storage
424   // for keys in oat_dex_files_ and the string_cache_ entries for the backing storage
425   // of keys in secondary_oat_dex_files_ and oat_dex_files_by_canonical_location_.
426   using Table =
427       AllocationTrackingSafeMap<std::string_view, const OatDexFile*, kAllocatorTagOatFile>;
428 
429   // Map each location and canonical location (if different) retrieved from the
430   // oat file to its OatDexFile. This map doesn't change after it's constructed in Setup()
431   // and therefore doesn't need any locking and provides the cheapest dex file lookup
432   // for GetOatDexFile() for a very frequent use case. Never contains a null value.
433   Table oat_dex_files_;
434 
435   // Lock guarding all members needed for secondary lookup in GetOatDexFile().
436   mutable Mutex secondary_lookup_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
437 
438   // If the primary oat_dex_files_ lookup fails, use a secondary map. This map stores
439   // the results of all previous secondary lookups, whether successful (non-null) or
440   // failed (null). If it doesn't contain an entry we need to calculate the canonical
441   // location and use oat_dex_files_by_canonical_location_.
442   mutable Table secondary_oat_dex_files_ GUARDED_BY(secondary_lookup_lock_);
443 
444   // Cache of strings. Contains the backing storage for keys in the secondary_oat_dex_files_
445   // and the lazily initialized oat_dex_files_by_canonical_location_.
446   // NOTE: We're keeping references to contained strings in form of std::string_view and adding
447   // new strings to the end. The adding of a new element must not touch any previously stored
448   // elements. std::list<> and std::deque<> satisfy this requirement, std::vector<> doesn't.
449   mutable std::list<std::string> string_cache_ GUARDED_BY(secondary_lookup_lock_);
450 
451   // Cache of dex files mapped directly from a location, in case the OatFile does
452   // not embed the dex code.
453   std::unique_ptr<std::vector<std::unique_ptr<const DexFile>>> uncompressed_dex_files_;
454 
455   friend class gc::collector::DummyOatFile;  // For modifying begin_ and end_.
456   friend class OatClass;
457   friend class art::OatDexFile;
458   friend class OatDumper;  // For GetBase and GetLimit
459   friend class OatFileBase;
460   DISALLOW_COPY_AND_ASSIGN(OatFile);
461 };
462 
463 // OatDexFile should be an inner class of OatFile. Unfortunately, C++ doesn't
464 // support forward declarations of inner classes, and we want to
465 // forward-declare OatDexFile so that we can store an opaque pointer to an
466 // OatDexFile in DexFile.
467 class OatDexFile final {
468  public:
469   // Opens the DexFile referred to by this OatDexFile from within the containing OatFile.
470   std::unique_ptr<const DexFile> OpenDexFile(std::string* error_msg) const;
471 
472   // May return null if the OatDexFile only contains a type lookup table. This case only happens
473   // for the compiler to speed up compilation, or in jitzygote.
GetOatFile()474   const OatFile* GetOatFile() const {
475     // Avoid pulling in runtime.h in the header file.
476     if (kIsDebugBuild && oat_file_ == nullptr) {
477       if (!Runtime::Current()->IsUsingApexBootImageLocation()) {
478         AssertAotCompiler();
479       }
480     }
481     return oat_file_;
482   }
483 
484   // Returns the size of the DexFile refered to by this OatDexFile.
485   size_t FileSize() const;
486 
487   // Returns original path of DexFile that was the source of this OatDexFile.
GetDexFileLocation()488   const std::string& GetDexFileLocation() const {
489     return dex_file_location_;
490   }
491 
492   // Returns the canonical location of DexFile that was the source of this OatDexFile.
GetCanonicalDexFileLocation()493   const std::string& GetCanonicalDexFileLocation() const {
494     return canonical_dex_file_location_;
495   }
496 
497   // Returns checksum of original DexFile that was the source of this OatDexFile;
GetDexFileLocationChecksum()498   uint32_t GetDexFileLocationChecksum() const {
499     return dex_file_location_checksum_;
500   }
501 
502   // Returns the OatClass for the class specified by the given DexFile class_def_index.
503   OatFile::OatClass GetOatClass(uint16_t class_def_index) const;
504 
505   // Returns the offset to the OatClass information. Most callers should use GetOatClass.
506   uint32_t GetOatClassOffset(uint16_t class_def_index) const;
507 
GetLookupTableData()508   const uint8_t* GetLookupTableData() const {
509     return lookup_table_data_;
510   }
511 
GetMethodBssMapping()512   const IndexBssMapping* GetMethodBssMapping() const {
513     return method_bss_mapping_;
514   }
515 
GetTypeBssMapping()516   const IndexBssMapping* GetTypeBssMapping() const {
517     return type_bss_mapping_;
518   }
519 
GetStringBssMapping()520   const IndexBssMapping* GetStringBssMapping() const {
521     return string_bss_mapping_;
522   }
523 
GetDexFilePointer()524   const uint8_t* GetDexFilePointer() const {
525     return dex_file_pointer_;
526   }
527 
528   ArrayRef<const uint8_t> GetQuickenedInfoOf(const DexFile& dex_file,
529                                              uint32_t dex_method_idx) const;
530 
531   // Looks up a class definition by its class descriptor. Hash must be
532   // ComputeModifiedUtf8Hash(descriptor).
533   static const dex::ClassDef* FindClassDef(const DexFile& dex_file,
534                                            const char* descriptor,
535                                            size_t hash);
536 
537   // Madvise the dex file based on the state we are moving to.
538   static void MadviseDexFile(const DexFile& dex_file, MadviseState state);
539 
GetTypeLookupTable()540   const TypeLookupTable& GetTypeLookupTable() const {
541     return lookup_table_;
542   }
543 
544   ~OatDexFile();
545 
546   // Create only with a type lookup table, used by the compiler to speed up compilation.
547   explicit OatDexFile(TypeLookupTable&& lookup_table);
548 
549   // Return the dex layout sections.
GetDexLayoutSections()550   const DexLayoutSections* GetDexLayoutSections() const {
551     return dex_layout_sections_;
552   }
553 
554  private:
555   OatDexFile(const OatFile* oat_file,
556              const std::string& dex_file_location,
557              const std::string& canonical_dex_file_location,
558              uint32_t dex_file_checksum,
559              const uint8_t* dex_file_pointer,
560              const uint8_t* lookup_table_data,
561              const IndexBssMapping* method_bss_mapping,
562              const IndexBssMapping* type_bss_mapping,
563              const IndexBssMapping* string_bss_mapping,
564              const uint32_t* oat_class_offsets_pointer,
565              const DexLayoutSections* dex_layout_sections);
566 
567   // Create an OatDexFile wrapping an existing DexFile. Will set the OatDexFile
568   // pointer in the DexFile.
569   OatDexFile(const OatFile* oat_file,
570              const DexFile* dex_file,
571              const std::string& dex_file_location,
572              const std::string& canonical_dex_file_location);
573 
574   bool IsBackedByVdexOnly() const;
575 
576   static void AssertAotCompiler();
577 
578   const OatFile* const oat_file_ = nullptr;
579   const std::string dex_file_location_;
580   const std::string canonical_dex_file_location_;
581   const uint32_t dex_file_location_checksum_ = 0u;
582   const uint8_t* const dex_file_pointer_ = nullptr;
583   const uint8_t* const lookup_table_data_ = nullptr;
584   const IndexBssMapping* const method_bss_mapping_ = nullptr;
585   const IndexBssMapping* const type_bss_mapping_ = nullptr;
586   const IndexBssMapping* const string_bss_mapping_ = nullptr;
587   const uint32_t* const oat_class_offsets_pointer_ = nullptr;
588   TypeLookupTable lookup_table_;
589   const DexLayoutSections* const dex_layout_sections_ = nullptr;
590 
591   friend class OatFile;
592   friend class OatFileBase;
593   DISALLOW_COPY_AND_ASSIGN(OatDexFile);
594 };
595 
596 }  // namespace art
597 
598 #endif  // ART_RUNTIME_OAT_FILE_H_
599