oat_file.h revision a59dd80f9f48cb750d329d4d4af2d99d72b484d1
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 <string>
21#include <vector>
22
23#include "base/stringpiece.h"
24#include "dex_file.h"
25#include "invoke_type.h"
26#include "mem_map.h"
27#include "mirror/class.h"
28#include "oat.h"
29#include "os.h"
30
31namespace art {
32
33class BitVector;
34class ElfFile;
35class MemMap;
36class OatMethodOffsets;
37class OatHeader;
38
39class OatFile {
40 public:
41  // Open an oat file. Returns NULL on failure.  Requested base can
42  // optionally be used to request where the file should be loaded.
43  static OatFile* Open(const std::string& filename,
44                       const std::string& location,
45                       byte* requested_base,
46                       bool executable,
47                       std::string* error_msg);
48
49  // Open an oat file from an already opened File.
50  // Does not use dlopen underneath so cannot be used for runtime use
51  // where relocations may be required. Currently used from
52  // ImageWriter which wants to open a writable version from an existing
53  // file descriptor for patching.
54  static OatFile* OpenWritable(File* file, const std::string& location, std::string* error_msg);
55  // Opens an oat file from an already opened File. Maps it PROT_READ, MAP_PRIVATE.
56  static OatFile* OpenReadable(File* file, const std::string& location, std::string* error_msg);
57
58  // Open an oat file backed by a std::vector with the given location.
59  static OatFile* OpenMemory(std::vector<uint8_t>& oat_contents,
60                             const std::string& location,
61                             std::string* error_msg);
62
63  ~OatFile();
64
65  ElfFile* GetElfFile() const {
66    CHECK_NE(reinterpret_cast<uintptr_t>(elf_file_.get()), reinterpret_cast<uintptr_t>(nullptr))
67        << "Cannot get an elf file from " << GetLocation();
68    return elf_file_.get();
69  }
70
71  const std::string& GetLocation() const {
72    return location_;
73  }
74
75  const OatHeader& GetOatHeader() const;
76
77  class OatDexFile;
78
79  class OatMethod {
80   public:
81    void LinkMethod(mirror::ArtMethod* method) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
82
83    uint32_t GetCodeOffset() const {
84      return code_offset_;
85    }
86    uint32_t GetNativeGcMapOffset() const {
87      return native_gc_map_offset_;
88    }
89
90    const void* GetPortableCode() const {
91      // TODO: encode whether code is portable/quick in flags within OatMethod.
92      if (kUsePortableCompiler) {
93        return GetOatPointer<const void*>(code_offset_);
94      } else {
95        return nullptr;
96      }
97    }
98
99    const void* GetQuickCode() const {
100      if (kUsePortableCompiler) {
101        return nullptr;
102      } else {
103        return GetOatPointer<const void*>(code_offset_);
104      }
105    }
106
107    uint32_t GetPortableCodeSize() const {
108      // TODO: With Quick, we store the size before the code. With Portable, the code is in a .o
109      // file we don't manage ourselves. ELF symbols do have a concept of size, so we could capture
110      // that and store it somewhere, such as the OatMethod.
111      return 0;
112    }
113    uint32_t GetQuickCodeSize() const;
114
115    const uint8_t* GetNativeGcMap() const {
116      return GetOatPointer<const uint8_t*>(native_gc_map_offset_);
117    }
118
119    size_t GetFrameSizeInBytes() const;
120    uint32_t GetCoreSpillMask() const;
121    uint32_t GetFpSpillMask() const;
122    uint32_t GetMappingTableOffset() const;
123    uint32_t GetVmapTableOffset() const;
124    const uint8_t* GetMappingTable() const;
125    const uint8_t* GetVmapTable() const;
126
127    ~OatMethod();
128
129    // Create an OatMethod with offsets relative to the given base address
130    OatMethod(const byte* base,
131              const uint32_t code_offset,
132              const uint32_t gc_map_offset);
133
134   private:
135    template<class T>
136    T GetOatPointer(uint32_t offset) const {
137      if (offset == 0) {
138        return NULL;
139      }
140      return reinterpret_cast<T>(begin_ + offset);
141    }
142
143    const byte* begin_;
144
145    uint32_t code_offset_;
146    uint32_t native_gc_map_offset_;
147
148    friend class OatClass;
149  };
150
151  class OatClass {
152   public:
153    mirror::Class::Status GetStatus() const {
154      return status_;
155    }
156
157    OatClassType GetType() const {
158      return type_;
159    }
160
161    // Get the OatMethod entry based on its index into the class
162    // defintion. direct methods come first, followed by virtual
163    // methods. note that runtime created methods such as miranda
164    // methods are not included.
165    const OatMethod GetOatMethod(uint32_t method_index) const;
166
167   private:
168    OatClass(const OatFile* oat_file,
169             mirror::Class::Status status,
170             OatClassType type,
171             uint32_t bitmap_size,
172             const uint32_t* bitmap_pointer,
173             const OatMethodOffsets* methods_pointer);
174
175    const OatFile* const oat_file_;
176
177    const mirror::Class::Status status_;
178
179    const OatClassType type_;
180
181    const uint32_t* const bitmap_;
182
183    const OatMethodOffsets* methods_pointer_;
184
185    friend class OatDexFile;
186  };
187
188  class OatDexFile {
189   public:
190    // Opens the DexFile referred to by this OatDexFile from within the containing OatFile.
191    const DexFile* OpenDexFile(std::string* error_msg) const;
192
193    // Returns the size of the DexFile refered to by this OatDexFile.
194    size_t FileSize() const;
195
196    // Returns original path of DexFile that was the source of this OatDexFile.
197    const std::string& GetDexFileLocation() const {
198      return dex_file_location_;
199    }
200
201    // Returns checksum of original DexFile that was the source of this OatDexFile;
202    uint32_t GetDexFileLocationChecksum() const {
203      return dex_file_location_checksum_;
204    }
205
206    // Returns the OatClass for the class specified by the given DexFile class_def_index.
207    OatClass GetOatClass(uint16_t class_def_index) const;
208
209    ~OatDexFile();
210
211   private:
212    OatDexFile(const OatFile* oat_file,
213               const std::string& dex_file_location,
214               uint32_t dex_file_checksum,
215               const byte* dex_file_pointer,
216               const uint32_t* oat_class_offsets_pointer);
217
218    const OatFile* const oat_file_;
219    const std::string dex_file_location_;
220    const uint32_t dex_file_location_checksum_;
221    const byte* const dex_file_pointer_;
222    const uint32_t* const oat_class_offsets_pointer_;
223
224    friend class OatFile;
225    DISALLOW_COPY_AND_ASSIGN(OatDexFile);
226  };
227
228  const OatDexFile* GetOatDexFile(const char* dex_location,
229                                  const uint32_t* const dex_location_checksum,
230                                  bool exception_if_not_found = true) const;
231
232  std::vector<const OatDexFile*> GetOatDexFiles() const;
233
234  size_t Size() const {
235    return End() - Begin();
236  }
237
238  const byte* Begin() const;
239  const byte* End() const;
240
241 private:
242  static void CheckLocation(const std::string& location);
243
244  static OatFile* OpenDlopen(const std::string& elf_filename,
245                             const std::string& location,
246                             byte* requested_base,
247                             std::string* error_msg);
248
249  static OatFile* OpenElfFile(File* file,
250                              const std::string& location,
251                              byte* requested_base,
252                              bool writable,
253                              bool executable,
254                              std::string* error_msg);
255
256  explicit OatFile(const std::string& filename);
257  bool Dlopen(const std::string& elf_filename, byte* requested_base, std::string* error_msg);
258  bool ElfFileOpen(File* file, byte* requested_base, bool writable, bool executable,
259                   std::string* error_msg);
260  bool Setup(std::string* error_msg);
261
262  // The oat file name.
263  //
264  // The image will embed this to link its associated oat file.
265  const std::string location_;
266
267  // Pointer to OatHeader.
268  const byte* begin_;
269
270  // Pointer to end of oat region for bounds checking.
271  const byte* end_;
272
273  // Backing memory map for oat file during when opened by ElfWriter during initial compilation.
274  std::unique_ptr<MemMap> mem_map_;
275
276  // Backing memory map for oat file during cross compilation.
277  std::unique_ptr<ElfFile> elf_file_;
278
279  // dlopen handle during runtime.
280  void* dlopen_handle_;
281
282  // NOTE: We use a StringPiece as the key type to avoid a memory allocation on every lookup
283  // with a const char* key.
284  typedef SafeMap<StringPiece, const OatDexFile*> Table;
285  Table oat_dex_files_;
286
287  friend class OatClass;
288  friend class OatDexFile;
289  friend class OatDumper;  // For GetBase and GetLimit
290  DISALLOW_COPY_AND_ASSIGN(OatFile);
291};
292
293}  // namespace art
294
295#endif  // ART_RUNTIME_OAT_FILE_H_
296