blob: 5a55fc6c958fda7d828f2363e5ec1927b50430b3 [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_COMPILER_OAT_WRITER_H_
18#define ART_COMPILER_OAT_WRITER_H_
Brian Carlstrom7940e442013-07-12 13:46:57 -070019
20#include <stdint.h>
Brian Carlstrom7940e442013-07-12 13:46:57 -070021#include <cstddef>
Ian Rogers700a4022014-05-19 16:49:03 -070022#include <memory>
Brian Carlstrom7940e442013-07-12 13:46:57 -070023
Vladimir Marko49b0f452015-12-10 13:49:19 +000024#include "base/dchecked_vector.h"
Vladimir Markob163bb72015-03-31 21:49:49 +010025#include "linker/relative_patcher.h" // For linker::RelativePatcherTargetProvider.
Brian Carlstrom7940e442013-07-12 13:46:57 -070026#include "mem_map.h"
Vladimir Markof4da6752014-08-01 19:04:18 +010027#include "method_reference.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070028#include "mirror/class.h"
Artem Udovichenkod9786b02015-10-14 16:36:55 +030029#include "oat.h"
Vladimir Marko9bdf1082016-01-21 12:15:52 +000030#include "os.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070031#include "safe_map.h"
Vladimir Marko9bdf1082016-01-21 12:15:52 +000032#include "ScopedFd.h"
Vladimir Marko49b0f452015-12-10 13:49:19 +000033#include "utils/array_ref.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070034
35namespace art {
36
Brian Carlstromba150c32013-08-27 17:31:03 -070037class BitVector;
Andreas Gampe79273802014-08-05 20:21:05 -070038class CompiledMethod;
Vladimir Marko20f85592015-03-19 10:07:02 +000039class CompilerDriver;
Vladimir Markof4da6752014-08-01 19:04:18 +010040class ImageWriter;
Brian Carlstrom7940e442013-07-12 13:46:57 -070041class OutputStream;
Vladimir Marko20f85592015-03-19 10:07:02 +000042class TimingLogger;
Artem Udovichenkod9786b02015-10-14 16:36:55 +030043class TypeLookupTable;
Vladimir Marko9bdf1082016-01-21 12:15:52 +000044class ZipEntry;
Brian Carlstrom7940e442013-07-12 13:46:57 -070045
David Srbeckyc5bfa972016-02-05 15:49:10 +000046namespace debug {
Vladimir Marko10c13562015-11-25 14:33:36 +000047struct MethodDebugInfo;
David Srbeckyc5bfa972016-02-05 15:49:10 +000048} // namespace debug
Vladimir Marko10c13562015-11-25 14:33:36 +000049
Brian Carlstrom7940e442013-07-12 13:46:57 -070050// OatHeader variable length with count of D OatDexFiles
51//
52// OatDexFile[0] one variable sized OatDexFile with offsets to Dex and OatClasses
53// OatDexFile[1]
54// ...
55// OatDexFile[D]
56//
57// Dex[0] one variable sized DexFile for each OatDexFile.
58// Dex[1] these are literal copies of the input .dex files.
59// ...
60// Dex[D]
61//
Artem Udovichenkod9786b02015-10-14 16:36:55 +030062// TypeLookupTable[0] one descriptor to class def index hash table for each OatDexFile.
63// TypeLookupTable[1]
64// ...
65// TypeLookupTable[D]
66//
Vladimir Marko9bdf1082016-01-21 12:15:52 +000067// ClassOffsets[0] one table of OatClass offsets for each class def for each OatDexFile.
68// ClassOffsets[1]
69// ...
70// ClassOffsets[D]
71//
Brian Carlstrom7940e442013-07-12 13:46:57 -070072// OatClass[0] one variable sized OatClass for each of C DexFile::ClassDefs
73// OatClass[1] contains OatClass entries with class status, offsets to code, etc.
74// ...
75// OatClass[C]
76//
Vladimir Marko96c6ab92014-04-08 14:00:50 +010077// GcMap one variable sized blob with GC map.
78// GcMap GC maps are deduplicated.
79// ...
80// GcMap
81//
82// VmapTable one variable sized VmapTable blob (quick compiler only).
83// VmapTable VmapTables are deduplicated.
84// ...
85// VmapTable
86//
87// MappingTable one variable sized blob with MappingTable (quick compiler only).
88// MappingTable MappingTables are deduplicated.
89// ...
90// MappingTable
91//
Brian Carlstrom7940e442013-07-12 13:46:57 -070092// padding if necessary so that the following code will be page aligned
93//
Vladimir Marko96c6ab92014-04-08 14:00:50 +010094// OatMethodHeader fixed size header for a CompiledMethod including the size of the MethodCode.
95// MethodCode one variable sized blob with the code of a CompiledMethod.
96// OatMethodHeader (OatMethodHeader, MethodCode) pairs are deduplicated.
97// MethodCode
Brian Carlstrom7940e442013-07-12 13:46:57 -070098// ...
Vladimir Marko96c6ab92014-04-08 14:00:50 +010099// OatMethodHeader
100// MethodCode
Brian Carlstrom7940e442013-07-12 13:46:57 -0700101//
102class OatWriter {
103 public:
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000104 enum class CreateTypeLookupTable {
105 kCreate,
106 kDontCreate,
107 kDefault = kCreate
108 };
109
110 OatWriter(bool compiling_boot_image, TimingLogger* timings);
111
112 // To produce a valid oat file, the user must first add sources with any combination of
113 // - AddDexFileSource(),
114 // - AddZippedDexFilesSource(),
115 // - AddRawDexFileSource().
116 // Then the user must call in order
117 // - WriteAndOpenDexFiles()
118 // - PrepareLayout(),
119 // - WriteRodata(),
120 // - WriteCode(),
121 // - WriteHeader().
122
123 // Add dex file source(s) from a file, either a plain dex file or
124 // a zip file with one or more dex files.
125 bool AddDexFileSource(
126 const char* filename,
127 const char* location,
128 CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
129 // Add dex file source(s) from a zip file specified by a file handle.
130 bool AddZippedDexFilesSource(
131 ScopedFd&& zip_fd,
132 const char* location,
133 CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
134 // Add dex file source from raw memory.
135 bool AddRawDexFileSource(
136 const ArrayRef<const uint8_t>& data,
137 const char* location,
138 uint32_t location_checksum,
139 CreateTypeLookupTable create_type_lookup_table = CreateTypeLookupTable::kDefault);
140 dchecked_vector<const char*> GetSourceLocations() const;
141
Andreas Gampe3a2bd292016-01-26 17:23:47 -0800142 // Write raw dex files to the .rodata section and open them from the oat file. The verify
143 // setting dictates whether the dex file verifier should check the dex files. This is generally
144 // the case, and should only be false for tests.
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000145 bool WriteAndOpenDexFiles(OutputStream* rodata,
146 File* file,
147 InstructionSet instruction_set,
148 const InstructionSetFeatures* instruction_set_features,
149 SafeMap<std::string, std::string>* key_value_store,
Andreas Gampe3a2bd292016-01-26 17:23:47 -0800150 bool verify,
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000151 /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
152 /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
153 // Prepare layout of remaining data.
154 void PrepareLayout(const CompilerDriver* compiler,
155 ImageWriter* image_writer,
156 const std::vector<const DexFile*>& dex_files);
157 // Write the rest of .rodata section (ClassOffsets[], OatClass[], maps).
158 bool WriteRodata(OutputStream* out);
159 // Write the code to the .text section.
160 bool WriteCode(OutputStream* out);
161 // Write the oat header. This finalizes the oat file.
162 bool WriteHeader(OutputStream* out,
163 uint32_t image_file_location_oat_checksum,
164 uintptr_t image_file_location_oat_begin,
165 int32_t image_patch_delta);
Brian Carlstromc50d8e12013-07-23 22:35:16 -0700166
Vladimir Marko09d09432015-09-08 13:47:48 +0100167 // Returns whether the oat file has an associated image.
168 bool HasImage() const {
169 // Since the image is being created at the same time as the oat file,
170 // check if there's an image writer.
171 return image_writer_ != nullptr;
172 }
173
Mathieu Chartierda5b28a2015-11-05 08:03:47 -0800174 bool HasBootImage() const {
175 return compiling_boot_image_;
176 }
177
Brian Carlstromc50d8e12013-07-23 22:35:16 -0700178 const OatHeader& GetOatHeader() const {
179 return *oat_header_;
180 }
181
182 size_t GetSize() const {
183 return size_;
184 }
185
Vladimir Marko5c42c292015-02-25 12:02:49 +0000186 size_t GetBssSize() const {
187 return bss_size_;
188 }
189
Vladimir Marko49b0f452015-12-10 13:49:19 +0000190 ArrayRef<const uintptr_t> GetAbsolutePatchLocations() const {
191 return ArrayRef<const uintptr_t>(absolute_patch_locations_);
Vladimir Markof4da6752014-08-01 19:04:18 +0100192 }
193
Brian Carlstrom7940e442013-07-12 13:46:57 -0700194 ~OatWriter();
195
David Srbeckyc5bfa972016-02-05 15:49:10 +0000196 ArrayRef<const debug::MethodDebugInfo> GetMethodDebugInfo() const {
197 return ArrayRef<const debug::MethodDebugInfo>(method_info_);
Mark Mendellae9fd932014-02-10 16:14:35 -0800198 }
199
Vladimir Markob163bb72015-03-31 21:49:49 +0100200 const CompilerDriver* GetCompilerDriver() {
201 return compiler_driver_;
202 }
203
Brian Carlstromc50d8e12013-07-23 22:35:16 -0700204 private:
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000205 class DexFileSource;
Vladimir Marko49b0f452015-12-10 13:49:19 +0000206 class OatClass;
207 class OatDexFile;
208
Vladimir Marko96c6ab92014-04-08 14:00:50 +0100209 // The DataAccess classes are helper classes that provide access to members related to
210 // a given map, i.e. GC map, mapping table or vmap table. By abstracting these away
211 // we can share a lot of code for processing the maps with template classes below.
212 struct GcMapDataAccess;
213 struct MappingTableDataAccess;
214 struct VmapTableDataAccess;
215
216 // The function VisitDexMethods() below iterates through all the methods in all
217 // the compiled dex files in order of their definitions. The method visitor
218 // classes provide individual bits of processing for each of the passes we need to
219 // first collect the data we want to write to the oat file and then, in later passes,
220 // to actually write it.
221 class DexMethodVisitor;
222 class OatDexMethodVisitor;
223 class InitOatClassesMethodVisitor;
224 class InitCodeMethodVisitor;
225 template <typename DataAccess>
226 class InitMapMethodVisitor;
227 class InitImageMethodVisitor;
228 class WriteCodeMethodVisitor;
229 template <typename DataAccess>
230 class WriteMapMethodVisitor;
231
232 // Visit all the methods in all the compiled dex files in their definition order
233 // with a given DexMethodVisitor.
234 bool VisitDexMethods(DexMethodVisitor* visitor);
235
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000236 size_t InitOatHeader(InstructionSet instruction_set,
237 const InstructionSetFeatures* instruction_set_features,
238 uint32_t num_dex_files,
239 SafeMap<std::string, std::string>* key_value_store);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700240 size_t InitOatDexFiles(size_t offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700241 size_t InitOatClasses(size_t offset);
Vladimir Marko96c6ab92014-04-08 14:00:50 +0100242 size_t InitOatMaps(size_t offset);
Vladimir Marko49b0f452015-12-10 13:49:19 +0000243 size_t InitOatCode(size_t offset);
244 size_t InitOatCodeDexFiles(size_t offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700245
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000246 bool WriteClassOffsets(OutputStream* out);
247 bool WriteClasses(OutputStream* out);
Vladimir Marko96c6ab92014-04-08 14:00:50 +0100248 size_t WriteMaps(OutputStream* out, const size_t file_offset, size_t relative_offset);
249 size_t WriteCode(OutputStream* out, const size_t file_offset, size_t relative_offset);
Ian Rogers3d504072014-03-01 09:16:49 -0800250 size_t WriteCodeDexFiles(OutputStream* out, const size_t file_offset, size_t relative_offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700251
Vladimir Marko49b0f452015-12-10 13:49:19 +0000252 bool GetOatDataOffset(OutputStream* out);
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000253 bool ReadDexFileHeader(File* file, OatDexFile* oat_dex_file);
254 bool ValidateDexFileHeader(const uint8_t* raw_header, const char* location);
255 bool WriteDexFiles(OutputStream* rodata, File* file);
256 bool WriteDexFile(OutputStream* rodata, File* file, OatDexFile* oat_dex_file);
257 bool SeekToDexFile(OutputStream* rodata, File* file, OatDexFile* oat_dex_file);
258 bool WriteDexFile(OutputStream* rodata, File* file, OatDexFile* oat_dex_file, ZipEntry* dex_file);
259 bool WriteDexFile(OutputStream* rodata, File* file, OatDexFile* oat_dex_file, File* dex_file);
260 bool WriteDexFile(OutputStream* rodata, OatDexFile* oat_dex_file, const uint8_t* dex_file);
261 bool WriteOatDexFiles(OutputStream* rodata);
262 bool ExtendForTypeLookupTables(OutputStream* rodata, File* file, size_t offset);
263 bool OpenDexFiles(File* file,
Andreas Gampe3a2bd292016-01-26 17:23:47 -0800264 bool verify,
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000265 /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
266 /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
267 bool WriteTypeLookupTables(MemMap* opened_dex_files_map,
268 const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files);
Vladimir Markof4da6752014-08-01 19:04:18 +0100269 bool WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta);
Vladimir Marko49b0f452015-12-10 13:49:19 +0000270 bool WriteData(OutputStream* out, const void* data, size_t size);
Vladimir Markof4da6752014-08-01 19:04:18 +0100271
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000272 enum class WriteState {
273 kAddingDexFileSources,
274 kPrepareLayout,
275 kWriteRoData,
276 kWriteText,
277 kWriteHeader,
278 kDone
279 };
280
281 WriteState write_state_;
282 TimingLogger* timings_;
283
284 std::vector<std::unique_ptr<File>> raw_dex_files_;
285 std::vector<std::unique_ptr<ZipArchive>> zip_archives_;
286 std::vector<std::unique_ptr<ZipEntry>> zipped_dex_files_;
287
288 // Using std::list<> which doesn't move elements around on push/emplace_back().
289 // We need this because we keep plain pointers to the strings' c_str().
290 std::list<std::string> zipped_dex_file_locations_;
291
David Srbeckyc5bfa972016-02-05 15:49:10 +0000292 dchecked_vector<debug::MethodDebugInfo> method_info_;
Mark Mendellae9fd932014-02-10 16:14:35 -0800293
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000294 const CompilerDriver* compiler_driver_;
295 ImageWriter* image_writer_;
Mathieu Chartierda5b28a2015-11-05 08:03:47 -0800296 const bool compiling_boot_image_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700297
298 // note OatFile does not take ownership of the DexFiles
299 const std::vector<const DexFile*>* dex_files_;
300
Brian Carlstromc50d8e12013-07-23 22:35:16 -0700301 // Size required for Oat data structures.
302 size_t size_;
303
Vladimir Marko5c42c292015-02-25 12:02:49 +0000304 // The size of the required .bss section holding the DexCache data.
305 size_t bss_size_;
306
Vladimir Marko09d09432015-09-08 13:47:48 +0100307 // Offsets of the dex cache arrays for each app dex file. For the
308 // boot image, this information is provided by the ImageWriter.
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100309 SafeMap<const DexFile*, size_t> dex_cache_arrays_offsets_; // DexFiles not owned.
Vladimir Marko09d09432015-09-08 13:47:48 +0100310
Vladimir Markof4da6752014-08-01 19:04:18 +0100311 // Offset of the oat data from the start of the mmapped region of the elf file.
312 size_t oat_data_offset_;
313
Brian Carlstrom7940e442013-07-12 13:46:57 -0700314 // data to write
Vladimir Marko49b0f452015-12-10 13:49:19 +0000315 std::unique_ptr<OatHeader> oat_header_;
316 dchecked_vector<OatDexFile> oat_dex_files_;
317 dchecked_vector<OatClass> oat_classes_;
Ian Rogers700a4022014-05-19 16:49:03 -0700318 std::unique_ptr<const std::vector<uint8_t>> jni_dlsym_lookup_;
Ian Rogers700a4022014-05-19 16:49:03 -0700319 std::unique_ptr<const std::vector<uint8_t>> quick_generic_jni_trampoline_;
320 std::unique_ptr<const std::vector<uint8_t>> quick_imt_conflict_trampoline_;
321 std::unique_ptr<const std::vector<uint8_t>> quick_resolution_trampoline_;
322 std::unique_ptr<const std::vector<uint8_t>> quick_to_interpreter_bridge_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700323
324 // output stats
325 uint32_t size_dex_file_alignment_;
326 uint32_t size_executable_offset_alignment_;
327 uint32_t size_oat_header_;
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700328 uint32_t size_oat_header_key_value_store_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700329 uint32_t size_dex_file_;
Ian Rogers468532e2013-08-05 10:56:33 -0700330 uint32_t size_interpreter_to_interpreter_bridge_;
331 uint32_t size_interpreter_to_compiled_code_bridge_;
332 uint32_t size_jni_dlsym_lookup_;
Andreas Gampe2da88232014-02-27 12:26:20 -0800333 uint32_t size_quick_generic_jni_trampoline_;
Jeff Hao88474b42013-10-23 16:24:40 -0700334 uint32_t size_quick_imt_conflict_trampoline_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700335 uint32_t size_quick_resolution_trampoline_;
Ian Rogers468532e2013-08-05 10:56:33 -0700336 uint32_t size_quick_to_interpreter_bridge_;
337 uint32_t size_trampoline_alignment_;
Vladimir Marko96c6ab92014-04-08 14:00:50 +0100338 uint32_t size_method_header_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700339 uint32_t size_code_;
340 uint32_t size_code_alignment_;
Vladimir Markof4da6752014-08-01 19:04:18 +0100341 uint32_t size_relative_call_thunks_;
Vladimir Markoc74658b2015-03-31 10:26:41 +0100342 uint32_t size_misc_thunks_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700343 uint32_t size_mapping_table_;
344 uint32_t size_vmap_table_;
345 uint32_t size_gc_map_;
346 uint32_t size_oat_dex_file_location_size_;
347 uint32_t size_oat_dex_file_location_data_;
348 uint32_t size_oat_dex_file_location_checksum_;
349 uint32_t size_oat_dex_file_offset_;
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000350 uint32_t size_oat_dex_file_class_offsets_offset_;
Vladimir Marko49b0f452015-12-10 13:49:19 +0000351 uint32_t size_oat_dex_file_lookup_table_offset_;
Vladimir Marko49b0f452015-12-10 13:49:19 +0000352 uint32_t size_oat_lookup_table_alignment_;
353 uint32_t size_oat_lookup_table_;
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000354 uint32_t size_oat_class_offsets_alignment_;
355 uint32_t size_oat_class_offsets_;
Brian Carlstromba150c32013-08-27 17:31:03 -0700356 uint32_t size_oat_class_type_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700357 uint32_t size_oat_class_status_;
Brian Carlstromba150c32013-08-27 17:31:03 -0700358 uint32_t size_oat_class_method_bitmaps_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700359 uint32_t size_oat_class_method_offsets_;
360
Vladimir Markob163bb72015-03-31 21:49:49 +0100361 std::unique_ptr<linker::RelativePatcher> relative_patcher_;
Vladimir Markof4da6752014-08-01 19:04:18 +0100362
David Srbeckyf8980872015-05-22 17:04:47 +0100363 // The locations of absolute patches relative to the start of the executable section.
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000364 dchecked_vector<uintptr_t> absolute_patch_locations_;
Vladimir Markof4da6752014-08-01 19:04:18 +0100365
Vladimir Markob163bb72015-03-31 21:49:49 +0100366 // Map method reference to assigned offset.
367 // Wrap the map in a class implementing linker::RelativePatcherTargetProvider.
368 class MethodOffsetMap FINAL : public linker::RelativePatcherTargetProvider {
369 public:
370 std::pair<bool, uint32_t> FindMethodOffset(MethodReference ref) OVERRIDE;
371 SafeMap<MethodReference, uint32_t, MethodReferenceComparator> map;
372 };
373 MethodOffsetMap method_offset_map_;
Vladimir Markof4da6752014-08-01 19:04:18 +0100374
Brian Carlstrom7940e442013-07-12 13:46:57 -0700375 DISALLOW_COPY_AND_ASSIGN(OatWriter);
376};
377
378} // namespace art
379
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700380#endif // ART_COMPILER_OAT_WRITER_H_