/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ART_RUNTIME_OAT_FILE_H_ #define ART_RUNTIME_OAT_FILE_H_ #include #include #include "dex_file.h" #include "invoke_type.h" #include "mem_map.h" #include "mirror/art_method.h" #include "oat.h" #include "os.h" namespace art { class BitVector; class ElfFile; class MemMap; class OatMethodOffsets; class OatHeader; class OatFile { public: // Returns an .odex file name next adjacent to the dex location. // For example, for "/foo/bar/baz.jar", return "/foo/bar/baz.odex". static std::string DexFilenameToOdexFilename(const std::string& location); // Open an oat file. Returns NULL on failure. Requested base can // optionally be used to request where the file should be loaded. static OatFile* Open(const std::string& filename, const std::string& location, byte* requested_base, bool executable, std::string* error_msg); // Open an oat file from an already opened File. // Does not use dlopen underneath so cannot be used for runtime use // where relocations may be required. Currently used from // ImageWriter which wants to open a writable version from an existing // file descriptor for patching. static OatFile* OpenWritable(File* file, const std::string& location, std::string* error_msg); // Open an oat file backed by a std::vector with the given location. static OatFile* OpenMemory(std::vector& oat_contents, const std::string& location, std::string* error_msg); ~OatFile(); const std::string& GetLocation() const { return location_; } const OatHeader& GetOatHeader() const; class OatDexFile; class OatMethod { public: void LinkMethod(mirror::ArtMethod* method) const; uint32_t GetCodeOffset() const { return code_offset_; } size_t GetFrameSizeInBytes() const { return frame_size_in_bytes_; } uint32_t GetCoreSpillMask() const { return core_spill_mask_; } uint32_t GetFpSpillMask() const { return fp_spill_mask_; } uint32_t GetNativeGcMapOffset() const { return native_gc_map_offset_; } const void* GetPortableCode() const { // TODO: encode whether code is portable/quick in flags within OatMethod. if (kUsePortableCompiler) { return GetOatPointer(code_offset_); } else { return nullptr; } } const void* GetQuickCode() const { if (kUsePortableCompiler) { return nullptr; } else { return GetOatPointer(code_offset_); } } uint32_t GetPortableCodeSize() const { // TODO: With Quick, we store the size before the code. With Portable, the code is in a .o // file we don't manage ourselves. ELF symbols do have a concept of size, so we could capture // that and store it somewhere, such as the OatMethod. return 0; } uint32_t GetQuickCodeSize() const; const uint8_t* GetNativeGcMap() const { return GetOatPointer(native_gc_map_offset_); } uint32_t GetMappingTableOffset() const; uint32_t GetVmapTableOffset() const; const uint8_t* GetMappingTable() const; const uint8_t* GetVmapTable() const; ~OatMethod(); // Create an OatMethod with offsets relative to the given base address OatMethod(const byte* base, const uint32_t code_offset, const size_t frame_size_in_bytes, const uint32_t core_spill_mask, const uint32_t fp_spill_mask, const uint32_t gc_map_offset); private: template T GetOatPointer(uint32_t offset) const { if (offset == 0) { return NULL; } return reinterpret_cast(begin_ + offset); } const byte* begin_; uint32_t code_offset_; size_t frame_size_in_bytes_; uint32_t core_spill_mask_; uint32_t fp_spill_mask_; uint32_t native_gc_map_offset_; friend class OatClass; }; class OatClass { public: mirror::Class::Status GetStatus() const { return status_; } OatClassType GetType() const { return type_; } // get the OatMethod entry based on its index into the class // defintion. direct methods come first, followed by virtual // methods. note that runtime created methods such as miranda // methods are not included. const OatMethod GetOatMethod(uint32_t method_index) const; private: OatClass(const OatFile* oat_file, mirror::Class::Status status, OatClassType type, uint32_t bitmap_size, const uint32_t* bitmap_pointer, const OatMethodOffsets* methods_pointer); const OatFile* const oat_file_; const mirror::Class::Status status_; const OatClassType type_; const uint32_t* const bitmap_; const OatMethodOffsets* methods_pointer_; friend class OatDexFile; }; class OatDexFile { public: // Opens the DexFile referred to by this OatDexFile from within the containing OatFile. const DexFile* OpenDexFile(std::string* error_msg) const; // Returns the size of the DexFile refered to by this OatDexFile. size_t FileSize() const; // Returns original path of DexFile that was the source of this OatDexFile. const std::string& GetDexFileLocation() const { return dex_file_location_; } // Returns checksum of original DexFile that was the source of this OatDexFile; uint32_t GetDexFileLocationChecksum() const { return dex_file_location_checksum_; } // Returns the OatClass for the class specified by the given DexFile class_def_index. OatClass GetOatClass(uint16_t class_def_index) const; ~OatDexFile(); private: OatDexFile(const OatFile* oat_file, const std::string& dex_file_location, uint32_t dex_file_checksum, const byte* dex_file_pointer, const uint32_t* oat_class_offsets_pointer); const OatFile* oat_file_; std::string dex_file_location_; uint32_t dex_file_location_checksum_; const byte* dex_file_pointer_; const uint32_t* oat_class_offsets_pointer_; friend class OatFile; DISALLOW_COPY_AND_ASSIGN(OatDexFile); }; const OatDexFile* GetOatDexFile(const char* dex_location, const uint32_t* const dex_location_checksum, bool exception_if_not_found = true) const; std::vector GetOatDexFiles() const; size_t Size() const { return End() - Begin(); } private: static void CheckLocation(const std::string& location); static OatFile* OpenDlopen(const std::string& elf_filename, const std::string& location, byte* requested_base, std::string* error_msg); static OatFile* OpenElfFile(File* file, const std::string& location, byte* requested_base, bool writable, bool executable, std::string* error_msg); explicit OatFile(const std::string& filename); bool Dlopen(const std::string& elf_filename, byte* requested_base, std::string* error_msg); bool ElfFileOpen(File* file, byte* requested_base, bool writable, bool executable, std::string* error_msg); bool Setup(std::string* error_msg); const byte* Begin() const; const byte* End() const; // The oat file name. // // The image will embed this to link its associated oat file. const std::string location_; // Pointer to OatHeader. const byte* begin_; // Pointer to end of oat region for bounds checking. const byte* end_; // Backing memory map for oat file during when opened by ElfWriter during initial compilation. UniquePtr mem_map_; // Backing memory map for oat file during cross compilation. UniquePtr elf_file_; // dlopen handle during runtime. void* dlopen_handle_; typedef SafeMap Table; Table oat_dex_files_; friend class OatClass; friend class OatDexFile; friend class OatDumper; // For GetBase and GetLimit DISALLOW_COPY_AND_ASSIGN(OatFile); }; } // namespace art #endif // ART_RUNTIME_OAT_FILE_H_