oat_file.h revision 90443477f9a0061581c420775ce3b7eeae7468bc
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 16e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef ART_RUNTIME_OAT_FILE_H_ 18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#define ART_RUNTIME_OAT_FILE_H_ 19e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 203f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko#include <list> 21700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include <string> 22e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include <vector> 23e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 243f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko#include "base/mutex.h" 25539690a351d8c325707368729aafa2b4fa134d4cVladimir Marko#include "base/stringpiece.h" 262dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "dex_file.h" 272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "invoke_type.h" 282dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mem_map.h" 2998d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang#include "mirror/class.h" 302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "oat.h" 31700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "os.h" 32e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 33e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art { 34e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 35ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstromclass BitVector; 36700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstromclass ElfFile; 37700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstromclass MemMap; 38700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstromclass OatMethodOffsets; 3933e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogersclass OatHeader; 4007b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhlerclass OatDexFile; 41700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 4207b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhlerclass OatFile FINAL { 43e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom public: 4407b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler typedef art::OatDexFile OatDexFile; 4507b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 4684d7605f93f1e6e86a16e02017e305c90e93117aAlex Light // Opens an oat file contained within the given elf file. This is always opened as 4784d7605f93f1e6e86a16e02017e305c90e93117aAlex Light // non-executable at the moment. 4884d7605f93f1e6e86a16e02017e305c90e93117aAlex Light static OatFile* OpenWithElfFile(ElfFile* elf_file, const std::string& location, 49e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 5084d7605f93f1e6e86a16e02017e305c90e93117aAlex Light std::string* error_msg); 512cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // Open an oat file. Returns null on failure. Requested base can 52e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // optionally be used to request where the file should be loaded. 53e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler // See the ResolveRelativeEncodedDexLocation for a description of how the 54e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler // abs_dex_location argument is used. 55e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom static OatFile* Open(const std::string& filename, 56a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom const std::string& location, 5713735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* requested_base, 5846774767fcf7780d1455e755729198648d08742eIgor Murashkin uint8_t* oat_file_begin, 598d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers bool executable, 60e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 618d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string* error_msg); 62e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 63700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom // Open an oat file from an already opened File. 64265091e581c9f643b37e7966890911f09e223269Brian Carlstrom // Does not use dlopen underneath so cannot be used for runtime use 65265091e581c9f643b37e7966890911f09e223269Brian Carlstrom // where relocations may be required. Currently used from 66265091e581c9f643b37e7966890911f09e223269Brian Carlstrom // ImageWriter which wants to open a writable version from an existing 67265091e581c9f643b37e7966890911f09e223269Brian Carlstrom // file descriptor for patching. 68e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler static OatFile* OpenWritable(File* file, const std::string& location, 69e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 70e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler std::string* error_msg); 71a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light // Opens an oat file from an already opened File. Maps it PROT_READ, MAP_PRIVATE. 72e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler static OatFile* OpenReadable(File* file, const std::string& location, 73e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 74e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler std::string* error_msg); 75700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 76e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom ~OatFile(); 77e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 789dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light bool IsExecutable() const { 799dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light return is_executable_; 809dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light } 819dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light 827ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe bool IsPic() const; 837ba649636c4475c3992fa15a57acd2546d69ff38Andreas Gampe 840de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz // Indicates whether the oat file was compiled with full debugging capability. 850de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz bool IsDebuggable() const; 860de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz 8753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light ElfFile* GetElfFile() const { 8853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light CHECK_NE(reinterpret_cast<uintptr_t>(elf_file_.get()), reinterpret_cast<uintptr_t>(nullptr)) 8953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light << "Cannot get an elf file from " << GetLocation(); 9053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light return elf_file_.get(); 9153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 9253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 93e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const std::string& GetLocation() const { 94e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return location_; 95e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 96e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 97e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const OatHeader& GetOatHeader() const; 98e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 9907b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler class OatMethod FINAL { 1003320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom public: 101e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier void LinkMethod(ArtMethod* method) const; 102ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 103c04c800e7bda94abfadc8c2d30f58c50b261b612Nicolas Geoffray uint32_t GetCodeOffset() const; 104ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 105c04c800e7bda94abfadc8c2d30f58c50b261b612Nicolas Geoffray const void* GetQuickCode() const; 1062cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom 1072cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom // Returns size of quick code. 108ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uint32_t GetQuickCodeSize() const; 1092cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom uint32_t GetQuickCodeSizeOffset() const; 1102cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom 1112cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom // Returns OatQuickMethodHeader for debugging. Most callers should 1122cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom // use more specific methods such as GetQuickCodeSize. 1132cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom const OatQuickMethodHeader* GetOatQuickMethodHeader() const; 1142cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom uint32_t GetOatQuickMethodHeaderOffset() const; 1150c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien 1167624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko size_t GetFrameSizeInBytes() const; 1177624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko uint32_t GetCoreSpillMask() const; 1187624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko uint32_t GetFpSpillMask() const; 1192cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom 1208a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko const uint8_t* GetMappingTable() const; 1212cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom uint32_t GetMappingTableOffset() const; 1222cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom uint32_t GetMappingTableOffsetOffset() const; 1232cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom 1248a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko const uint8_t* GetVmapTable() const; 1252cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom uint32_t GetVmapTableOffset() const; 1262cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom uint32_t GetVmapTableOffsetOffset() const; 1278a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko 128957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier const uint8_t* GetGcMap() const; 129957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier uint32_t GetGcMapOffset() const; 130957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier uint32_t GetGcMapOffsetOffset() const; 131957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier 132ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom // Create an OatMethod with offsets relative to the given base address 133957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier OatMethod(const uint8_t* base, const uint32_t code_offset) 134957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier : begin_(base), code_offset_(code_offset) { 13597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers } 136758a801b66c134361a7b43f7e83f85d1fb800c4cAndreas Gampe OatMethod(const OatMethod&) = default; 13797b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers ~OatMethod() {} 1383320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 139758a801b66c134361a7b43f7e83f85d1fb800c4cAndreas Gampe OatMethod& operator=(const OatMethod&) = default; 140758a801b66c134361a7b43f7e83f85d1fb800c4cAndreas Gampe 14197b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers // A representation of an invalid OatMethod, used when an OatMethod or OatClass can't be found. 14297b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers // See ClassLinker::FindOatMethodFor. 14397b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers static const OatMethod Invalid() { 144957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier return OatMethod(nullptr, -1); 14597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers } 1464fcdc94d22a4608e355aa8df36240181149d10e8Nicolas Geoffray 147ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom private: 148ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom template<class T> 149ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom T GetOatPointer(uint32_t offset) const { 150ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (offset == 0) { 1512cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier return nullptr; 152ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 15330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers return reinterpret_cast<T>(begin_ + offset); 154ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 1553320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 156e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier const uint8_t* begin_; 157e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier uint32_t code_offset_; 158ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 159ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom friend class OatClass; 1603320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom }; 1613320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 16207b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler class OatClass FINAL { 163e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom public: 164ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom mirror::Class::Status GetStatus() const { 165ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return status_; 166ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 167ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 168ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom OatClassType GetType() const { 169ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom return type_; 170ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom } 1710755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom 172eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Get the OatMethod entry based on its index into the class 1732cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom // defintion. Direct methods come first, followed by virtual 1742cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom // methods. Note that runtime created methods such as miranda 175e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // methods are not included. 176aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom const OatMethod GetOatMethod(uint32_t method_index) const; 177e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 1782cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom // Return a pointer to the OatMethodOffsets for the requested 1792cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // method_index, or null if none is present. Note that most 1802cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom // callers should use GetOatMethod. 1812cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom const OatMethodOffsets* GetOatMethodOffsets(uint32_t method_index) const; 1822cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom 1832cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom // Return the offset from the start of the OatFile to the 1842cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom // OatMethodOffsets for the requested method_index, or 0 if none 1852cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom // is present. Note that most callers should use GetOatMethod. 1862cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom uint32_t GetOatMethodOffsetsOffset(uint32_t method_index) const; 1872cbaccb67e22c0b313a9785bfc65bcb4b25d0676Brian Carlstrom 18897b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers // A representation of an invalid OatClass, used when an OatClass can't be found. 18997b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers // See ClassLinker::FindOatClass. 19097b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers static OatClass Invalid() { 19197b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers return OatClass(nullptr, mirror::Class::kStatusError, kOatClassNoneCompiled, 0, nullptr, 19297b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers nullptr); 19397b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers } 1944fcdc94d22a4608e355aa8df36240181149d10e8Nicolas Geoffray 195e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom private: 1960755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom OatClass(const OatFile* oat_file, 1972dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class::Status status, 198ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom OatClassType type, 199ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom uint32_t bitmap_size, 200ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom const uint32_t* bitmap_pointer, 2010755ec5ea1dce0b549fc1adefeb52d89f119ebecBrian Carlstrom const OatMethodOffsets* methods_pointer); 2023320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 20397b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers const OatFile* const oat_file_; 204ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 20597b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers const mirror::Class::Status status_; 206ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 20797b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers const OatClassType type_; 208ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 20997b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers const uint32_t* const bitmap_; 210ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 21197b52f89e5e0b52a08d4b9a3953d0973a3cf5636Ian Rogers const OatMethodOffsets* const methods_pointer_; 212e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 21307b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler friend class art::OatDexFile; 214e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom }; 2158d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers const OatDexFile* GetOatDexFile(const char* dex_location, 216756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom const uint32_t* const dex_location_checksum, 2173f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko bool exception_if_not_found = true) const 21890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier REQUIRES(!secondary_lookup_lock_); 2198d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers 220aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko const std::vector<const OatDexFile*>& GetOatDexFiles() const { 221aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko return oat_dex_files_storage_; 222aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko } 223e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 22430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers size_t Size() const { 22530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers return End() - Begin(); 226e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 227e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 2285c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko size_t BssSize() const { 2295c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko return BssEnd() - BssBegin(); 2305c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko } 2315c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 23213735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* Begin() const; 23313735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* End() const; 23453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 2355c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko const uint8_t* BssBegin() const; 2365c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko const uint8_t* BssEnd() const; 2375c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 238e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler // Returns the absolute dex location for the encoded relative dex location. 239e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler // 2402cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // If not null, abs_dex_location is used to resolve the absolute dex 241e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler // location of relative dex locations encoded in the oat file. 242e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler // For example, given absolute location "/data/app/foo/base.apk", encoded 243e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler // dex locations "base.apk", "base.apk:classes2.dex", etc. would be resolved 244e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler // to "/data/app/foo/base.apk", "/data/app/foo/base.apk:classes2.dex", etc. 245e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler // Relative encoded dex locations that don't match the given abs_dex_location 246e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler // are left unchanged. 247e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler static std::string ResolveRelativeEncodedDexLocation( 248e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, const std::string& rel_dex_location); 249e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler 2507848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // Create a dependency list (dex locations and checksums) for the given dex files. 2517848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe static std::string EncodeDexFileDependencies(const std::vector<const DexFile*>& dex_files); 2527848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 2537848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // Check the given dependency list against their dex files - thus the name "Static," this does 2547848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // not check the class-loader environment, only whether there have been file updates. 2557848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe static bool CheckStaticDexFileDependencies(const char* dex_dependencies, std::string* msg); 2567848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 2577848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // Get the dex locations of a dependency list. Note: this is *not* cleaned for synthetic 2587848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe // locations of multidex files. 2597848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe static bool GetDexLocationsFromDependencies(const char* dex_dependencies, 2607848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe std::vector<std::string>* locations); 2617848da48a0a4241dedc1cc83ac4931e61575eb92Andreas Gampe 262e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom private: 263700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom static void CheckLocation(const std::string& location); 264700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 265fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe static OatFile* OpenDlopen(const std::string& elf_filename, 266fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe const std::string& location, 267fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe uint8_t* requested_base, 268fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe const char* abs_dex_location, 269fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe std::string* error_msg); 270fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe 271700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom static OatFile* OpenElfFile(File* file, 272700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom const std::string& location, 27313735955f39b3b304c37d2b2840663c131262c18Ian Rogers uint8_t* requested_base, 27446774767fcf7780d1455e755729198648d08742eIgor Murashkin uint8_t* oat_file_begin, // Override base if not null 275f1d3455064792ac1c486a4a9c24279a37b4af473Brian Carlstrom bool writable, 2768d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers bool executable, 277e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 2788d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string* error_msg); 279700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 2809dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light explicit OatFile(const std::string& filename, bool executable); 281fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe bool Dlopen(const std::string& elf_filename, uint8_t* requested_base, 282fa8429b967fe2260ece572337534c9dda6c50d8aAndreas Gampe const char* abs_dex_location, std::string* error_msg); 28346774767fcf7780d1455e755729198648d08742eIgor Murashkin bool ElfFileOpen(File* file, uint8_t* requested_base, 28446774767fcf7780d1455e755729198648d08742eIgor Murashkin uint8_t* oat_file_begin, // Override where the file is loaded to if not null 28546774767fcf7780d1455e755729198648d08742eIgor Murashkin bool writable, bool executable, 286e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler const char* abs_dex_location, 2878d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string* error_msg); 288e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler 289e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler bool Setup(const char* abs_dex_location, std::string* error_msg); 290e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 291e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // The oat file name. 292e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // 293e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // The image will embed this to link its associated oat file. 294e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const std::string location_; 295e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 296700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom // Pointer to OatHeader. 29713735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* begin_; 298700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 299700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom // Pointer to end of oat region for bounds checking. 30013735955f39b3b304c37d2b2840663c131262c18Ian Rogers const uint8_t* end_; 301700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 3022cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // Pointer to the .bss section, if present, otherwise null. 3035c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko const uint8_t* bss_begin_; 3045c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 3052cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // Pointer to the end of the .bss section, if present, otherwise null. 3065c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko const uint8_t* bss_end_; 3075c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko 3089dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light // Was this oat_file loaded executable? 3099dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light const bool is_executable_; 3109dcc4572949f6a8231a1b4ed859676ba6f411726Alex Light 311700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom // Backing memory map for oat file during when opened by ElfWriter during initial compilation. 312700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<MemMap> mem_map_; 313e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 314700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom // Backing memory map for oat file during cross compilation. 315700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<ElfFile> elf_file_; 316700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 317700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom // dlopen handle during runtime. 318700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom void* dlopen_handle_; 319700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 32082e73dcc290ae8603c8a2e533d6a8a19cc2983a3David Srbecky // Dummy memory map objects corresponding to the regions mapped by dlopen. 32182e73dcc290ae8603c8a2e533d6a8a19cc2983a3David Srbecky std::vector<std::unique_ptr<MemMap>> dlopen_mmaps_; 32282e73dcc290ae8603c8a2e533d6a8a19cc2983a3David Srbecky 323aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko // Owning storage for the OatDexFile objects. 324aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko std::vector<const OatDexFile*> oat_dex_files_storage_; 325aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko 3263f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // NOTE: We use a StringPiece as the key type to avoid a memory allocation on every 3273f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // lookup with a const char* key. The StringPiece doesn't own its backing storage, 3283f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // therefore we're using the OatDexFile::dex_file_location_ as the backing storage 3293f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // for keys in oat_dex_files_ and the string_cache_ entries for the backing storage 3303f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // of keys in secondary_oat_dex_files_ and oat_dex_files_by_canonical_location_. 331bad0267eaab9d6a522d05469ff90501deefdb88bMathieu Chartier typedef AllocationTrackingSafeMap<StringPiece, const OatDexFile*, kAllocatorTagOatFile> Table; 3323f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko 333aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko // Map each location and canonical location (if different) retrieved from the 334aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko // oat file to its OatDexFile. This map doesn't change after it's constructed in Setup() 335aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko // and therefore doesn't need any locking and provides the cheapest dex file lookup 3362cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier // for GetOatDexFile() for a very frequent use case. Never contains a null value. 337aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4Vladimir Marko Table oat_dex_files_; 3383f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko 3393f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // Lock guarding all members needed for secondary lookup in GetOatDexFile(). 3403f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko mutable Mutex secondary_lookup_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; 3413f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko 3423f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // If the primary oat_dex_files_ lookup fails, use a secondary map. This map stores 3433f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // the results of all previous secondary lookups, whether successful (non-null) or 3443f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // failed (null). If it doesn't contain an entry we need to calculate the canonical 3453f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // location and use oat_dex_files_by_canonical_location_. 3463f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko mutable Table secondary_oat_dex_files_ GUARDED_BY(secondary_lookup_lock_); 3473f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko 3483f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // Cache of strings. Contains the backing storage for keys in the secondary_oat_dex_files_ 3493f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // and the lazily initialized oat_dex_files_by_canonical_location_. 3503f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // NOTE: We're keeping references to contained strings in form of StringPiece and adding 3513f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // new strings to the end. The adding of a new element must not touch any previously stored 3523f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko // elements. std::list<> and std::deque<> satisfy this requirement, std::vector<> doesn't. 3533f5838d7d0b9fc63db0ccc35c2ea05ed29264986Vladimir Marko mutable std::list<std::string> string_cache_ GUARDED_BY(secondary_lookup_lock_); 354e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 355e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom friend class OatClass; 35607b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler friend class art::OatDexFile; 357e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes friend class OatDumper; // For GetBase and GetLimit 358e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom DISALLOW_COPY_AND_ASSIGN(OatFile); 359e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}; 360e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 36107b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler// OatDexFile should be an inner class of OatFile. Unfortunately, C++ doesn't 36207b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler// support forward declarations of inner classes, and we want to 36307b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler// forward-declare OatDexFile so that we can store an opaque pointer to an 36407b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler// OatDexFile in DexFile. 36507b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhlerclass OatDexFile FINAL { 36607b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler public: 36707b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler // Opens the DexFile referred to by this OatDexFile from within the containing OatFile. 36807b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler std::unique_ptr<const DexFile> OpenDexFile(std::string* error_msg) const; 36907b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 37007b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const OatFile* GetOatFile() const { 37107b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler return oat_file_; 37207b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler } 37307b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 37407b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler // Returns the size of the DexFile refered to by this OatDexFile. 37507b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler size_t FileSize() const; 37607b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 37707b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler // Returns original path of DexFile that was the source of this OatDexFile. 37807b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const std::string& GetDexFileLocation() const { 37907b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler return dex_file_location_; 38007b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler } 38107b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 38207b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler // Returns the canonical location of DexFile that was the source of this OatDexFile. 38307b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const std::string& GetCanonicalDexFileLocation() const { 38407b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler return canonical_dex_file_location_; 38507b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler } 38607b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 38707b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler // Returns checksum of original DexFile that was the source of this OatDexFile; 38807b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler uint32_t GetDexFileLocationChecksum() const { 38907b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler return dex_file_location_checksum_; 39007b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler } 39107b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 39207b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler // Returns the OatClass for the class specified by the given DexFile class_def_index. 39307b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler OatFile::OatClass GetOatClass(uint16_t class_def_index) const; 39407b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 39507b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler // Returns the offset to the OatClass information. Most callers should use GetOatClass. 39607b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler uint32_t GetOatClassOffset(uint16_t class_def_index) const; 39707b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 39807b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler ~OatDexFile(); 39907b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 40007b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler private: 40107b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler OatDexFile(const OatFile* oat_file, 40207b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const std::string& dex_file_location, 40307b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const std::string& canonical_dex_file_location, 40407b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler uint32_t dex_file_checksum, 40507b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const uint8_t* dex_file_pointer, 40607b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const uint32_t* oat_class_offsets_pointer); 40707b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 40807b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const OatFile* const oat_file_; 40907b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const std::string dex_file_location_; 41007b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const std::string canonical_dex_file_location_; 41107b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const uint32_t dex_file_location_checksum_; 41207b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const uint8_t* const dex_file_pointer_; 41307b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler const uint32_t* const oat_class_offsets_pointer_; 41407b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 41507b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler friend class OatFile; 41607b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler DISALLOW_COPY_AND_ASSIGN(OatDexFile); 41707b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler}; 41807b3c2351bb527ea91c084dc19434600af9ae66bRichard Uhler 419e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} // namespace art 420e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 421fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif // ART_RUNTIME_OAT_FILE_H_ 422