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#include "oat_writer.h"
18
19#include <algorithm>
20#include <unistd.h>
21#include <zlib.h>
22
23#include "arch/arm64/instruction_set_features_arm64.h"
24#include "art_method-inl.h"
25#include "base/allocator.h"
26#include "base/bit_vector-inl.h"
27#include "base/enums.h"
28#include "base/file_magic.h"
29#include "base/logging.h"  // For VLOG
30#include "base/os.h"
31#include "base/safe_map.h"
32#include "base/stl_util.h"
33#include "base/unix_file/fd_file.h"
34#include "class_linker.h"
35#include "class_table-inl.h"
36#include "compiled_method-inl.h"
37#include "debug/method_debug_info.h"
38#include "dex/art_dex_file_loader.h"
39#include "dex/dex_file-inl.h"
40#include "dex/dex_file_loader.h"
41#include "dex/dex_file_types.h"
42#include "dex/standard_dex_file.h"
43#include "dex/verification_results.h"
44#include "dex_container.h"
45#include "dexlayout.h"
46#include "driver/compiler_driver-inl.h"
47#include "driver/compiler_options.h"
48#include "gc/space/image_space.h"
49#include "gc/space/space.h"
50#include "handle_scope-inl.h"
51#include "image_writer.h"
52#include "jit/profile_compilation_info.h"
53#include "linker/buffered_output_stream.h"
54#include "linker/file_output_stream.h"
55#include "linker/index_bss_mapping_encoder.h"
56#include "linker/linker_patch.h"
57#include "linker/multi_oat_relative_patcher.h"
58#include "linker/output_stream.h"
59#include "mirror/array.h"
60#include "mirror/class_loader.h"
61#include "mirror/dex_cache-inl.h"
62#include "mirror/object-inl.h"
63#include "oat_quick_method_header.h"
64#include "quicken_info.h"
65#include "scoped_thread_state_change-inl.h"
66#include "type_lookup_table.h"
67#include "utils/dex_cache_arrays_layout-inl.h"
68#include "vdex_file.h"
69#include "verifier/verifier_deps.h"
70#include "zip_archive.h"
71
72namespace art {
73namespace linker {
74
75namespace {  // anonymous namespace
76
77// If we write dex layout info in the oat file.
78static constexpr bool kWriteDexLayoutInfo = true;
79
80// Force the OAT method layout to be sorted-by-name instead of
81// the default (class_def_idx, method_idx).
82//
83// Otherwise if profiles are used, that will act as
84// the primary sort order.
85//
86// A bit easier to use for development since oatdump can easily
87// show that things are being re-ordered when two methods aren't adjacent.
88static constexpr bool kOatWriterForceOatCodeLayout = false;
89
90static constexpr bool kOatWriterDebugOatCodeLayout = false;
91
92typedef DexFile::Header __attribute__((aligned(1))) UnalignedDexFileHeader;
93
94const UnalignedDexFileHeader* AsUnalignedDexFileHeader(const uint8_t* raw_data) {
95    return reinterpret_cast<const UnalignedDexFileHeader*>(raw_data);
96}
97
98class ChecksumUpdatingOutputStream : public OutputStream {
99 public:
100  ChecksumUpdatingOutputStream(OutputStream* out, OatHeader* oat_header)
101      : OutputStream(out->GetLocation()), out_(out), oat_header_(oat_header) { }
102
103  bool WriteFully(const void* buffer, size_t byte_count) OVERRIDE {
104    oat_header_->UpdateChecksum(buffer, byte_count);
105    return out_->WriteFully(buffer, byte_count);
106  }
107
108  off_t Seek(off_t offset, Whence whence) OVERRIDE {
109    return out_->Seek(offset, whence);
110  }
111
112  bool Flush() OVERRIDE {
113    return out_->Flush();
114  }
115
116 private:
117  OutputStream* const out_;
118  OatHeader* const oat_header_;
119};
120
121inline uint32_t CodeAlignmentSize(uint32_t header_offset, const CompiledMethod& compiled_method) {
122  // We want to align the code rather than the preheader.
123  uint32_t unaligned_code_offset = header_offset + sizeof(OatQuickMethodHeader);
124  uint32_t aligned_code_offset =  compiled_method.AlignCode(unaligned_code_offset);
125  return aligned_code_offset - unaligned_code_offset;
126}
127
128}  // anonymous namespace
129
130// Defines the location of the raw dex file to write.
131class OatWriter::DexFileSource {
132 public:
133  enum Type {
134    kNone,
135    kZipEntry,
136    kRawFile,
137    kRawData,
138  };
139
140  explicit DexFileSource(ZipEntry* zip_entry)
141      : type_(kZipEntry), source_(zip_entry) {
142    DCHECK(source_ != nullptr);
143  }
144
145  explicit DexFileSource(File* raw_file)
146      : type_(kRawFile), source_(raw_file) {
147    DCHECK(source_ != nullptr);
148  }
149
150  explicit DexFileSource(const uint8_t* dex_file)
151      : type_(kRawData), source_(dex_file) {
152    DCHECK(source_ != nullptr);
153  }
154
155  Type GetType() const { return type_; }
156  bool IsZipEntry() const { return type_ == kZipEntry; }
157  bool IsRawFile() const { return type_ == kRawFile; }
158  bool IsRawData() const { return type_ == kRawData; }
159
160  ZipEntry* GetZipEntry() const {
161    DCHECK(IsZipEntry());
162    DCHECK(source_ != nullptr);
163    return static_cast<ZipEntry*>(const_cast<void*>(source_));
164  }
165
166  File* GetRawFile() const {
167    DCHECK(IsRawFile());
168    DCHECK(source_ != nullptr);
169    return static_cast<File*>(const_cast<void*>(source_));
170  }
171
172  const uint8_t* GetRawData() const {
173    DCHECK(IsRawData());
174    DCHECK(source_ != nullptr);
175    return static_cast<const uint8_t*>(source_);
176  }
177
178  void Clear() {
179    type_ = kNone;
180    source_ = nullptr;
181  }
182
183 private:
184  Type type_;
185  const void* source_;
186};
187
188// OatClassHeader is the header only part of the oat class that is required even when compilation
189// is not enabled.
190class OatWriter::OatClassHeader {
191 public:
192  OatClassHeader(uint32_t offset,
193                 uint32_t num_non_null_compiled_methods,
194                 uint32_t num_methods,
195                 ClassStatus status)
196      : status_(enum_cast<uint16_t>(status)),
197        offset_(offset) {
198    // We just arbitrarily say that 0 methods means kOatClassNoneCompiled and that we won't use
199    // kOatClassAllCompiled unless there is at least one compiled method. This means in an
200    // interpreter only system, we can assert that all classes are kOatClassNoneCompiled.
201    if (num_non_null_compiled_methods == 0) {
202      type_ = kOatClassNoneCompiled;
203    } else if (num_non_null_compiled_methods == num_methods) {
204      type_ = kOatClassAllCompiled;
205    } else {
206      type_ = kOatClassSomeCompiled;
207    }
208  }
209
210  bool Write(OatWriter* oat_writer, OutputStream* out, const size_t file_offset) const;
211
212  static size_t SizeOf() {
213    return sizeof(status_) + sizeof(type_);
214  }
215
216  // Data to write.
217  static_assert(enum_cast<>(ClassStatus::kLast) < (1 << 16), "class status won't fit in 16bits");
218  uint16_t status_;
219
220  static_assert(OatClassType::kOatClassMax < (1 << 16), "oat_class type won't fit in 16bits");
221  uint16_t type_;
222
223  // Offset of start of OatClass from beginning of OatHeader. It is
224  // used to validate file position when writing.
225  uint32_t offset_;
226};
227
228// The actual oat class body contains the information about compiled methods. It is only required
229// for compiler filters that have any compilation.
230class OatWriter::OatClass {
231 public:
232  OatClass(const dchecked_vector<CompiledMethod*>& compiled_methods,
233           uint32_t compiled_methods_with_code,
234           uint16_t oat_class_type);
235  OatClass(OatClass&& src) = default;
236  size_t SizeOf() const;
237  bool Write(OatWriter* oat_writer, OutputStream* out) const;
238
239  CompiledMethod* GetCompiledMethod(size_t class_def_method_index) const {
240    return compiled_methods_[class_def_method_index];
241  }
242
243  // CompiledMethods for each class_def_method_index, or null if no method is available.
244  dchecked_vector<CompiledMethod*> compiled_methods_;
245
246  // Offset from OatClass::offset_ to the OatMethodOffsets for the
247  // class_def_method_index. If 0, it means the corresponding
248  // CompiledMethod entry in OatClass::compiled_methods_ should be
249  // null and that the OatClass::type_ should be kOatClassBitmap.
250  dchecked_vector<uint32_t> oat_method_offsets_offsets_from_oat_class_;
251
252  // Data to write.
253  uint32_t method_bitmap_size_;
254
255  // bit vector indexed by ClassDef method index. When
256  // OatClassType::type_ is kOatClassBitmap, a set bit indicates the
257  // method has an OatMethodOffsets in methods_offsets_, otherwise
258  // the entry was ommited to save space. If OatClassType::type_ is
259  // not is kOatClassBitmap, the bitmap will be null.
260  std::unique_ptr<BitVector> method_bitmap_;
261
262  // OatMethodOffsets and OatMethodHeaders for each CompiledMethod
263  // present in the OatClass. Note that some may be missing if
264  // OatClass::compiled_methods_ contains null values (and
265  // oat_method_offsets_offsets_from_oat_class_ should contain 0
266  // values in this case).
267  dchecked_vector<OatMethodOffsets> method_offsets_;
268  dchecked_vector<OatQuickMethodHeader> method_headers_;
269
270 private:
271  size_t GetMethodOffsetsRawSize() const {
272    return method_offsets_.size() * sizeof(method_offsets_[0]);
273  }
274
275  DISALLOW_COPY_AND_ASSIGN(OatClass);
276};
277
278class OatWriter::OatDexFile {
279 public:
280  OatDexFile(const char* dex_file_location,
281             DexFileSource source,
282             CreateTypeLookupTable create_type_lookup_table,
283             uint32_t dex_file_location_checksun,
284             size_t dex_file_size);
285  OatDexFile(OatDexFile&& src) = default;
286
287  const char* GetLocation() const {
288    return dex_file_location_data_;
289  }
290
291  size_t SizeOf() const;
292  bool Write(OatWriter* oat_writer, OutputStream* out) const;
293  bool WriteClassOffsets(OatWriter* oat_writer, OutputStream* out);
294
295  size_t GetClassOffsetsRawSize() const {
296    return class_offsets_.size() * sizeof(class_offsets_[0]);
297  }
298
299  // The source of the dex file.
300  DexFileSource source_;
301
302  // Whether to create the type lookup table.
303  CreateTypeLookupTable create_type_lookup_table_;
304
305  // Dex file size. Passed in the constructor, but could be
306  // overwritten by LayoutAndWriteDexFile.
307  size_t dex_file_size_;
308
309  // Offset of start of OatDexFile from beginning of OatHeader. It is
310  // used to validate file position when writing.
311  size_t offset_;
312
313  ///// Start of data to write to vdex/oat file.
314
315  const uint32_t dex_file_location_size_;
316  const char* const dex_file_location_data_;
317
318  // The checksum of the dex file.
319  const uint32_t dex_file_location_checksum_;
320
321  // Offset of the dex file in the vdex file. Set when writing dex files in
322  // SeekToDexFile.
323  uint32_t dex_file_offset_;
324
325  // The lookup table offset in the oat file. Set in WriteTypeLookupTables.
326  uint32_t lookup_table_offset_;
327
328  // Class and BSS offsets set in PrepareLayout.
329  uint32_t class_offsets_offset_;
330  uint32_t method_bss_mapping_offset_;
331  uint32_t type_bss_mapping_offset_;
332  uint32_t string_bss_mapping_offset_;
333
334  // Offset of dex sections that will have different runtime madvise states.
335  // Set in WriteDexLayoutSections.
336  uint32_t dex_sections_layout_offset_;
337
338  // Data to write to a separate section. We set the length
339  // of the vector in OpenDexFiles.
340  dchecked_vector<uint32_t> class_offsets_;
341
342  // Dex section layout info to serialize.
343  DexLayoutSections dex_sections_layout_;
344
345  ///// End of data to write to vdex/oat file.
346 private:
347  DISALLOW_COPY_AND_ASSIGN(OatDexFile);
348};
349
350#define DCHECK_OFFSET() \
351  DCHECK_EQ(static_cast<off_t>(file_offset + relative_offset), out->Seek(0, kSeekCurrent)) \
352    << "file_offset=" << file_offset << " relative_offset=" << relative_offset
353
354#define DCHECK_OFFSET_() \
355  DCHECK_EQ(static_cast<off_t>(file_offset + offset_), out->Seek(0, kSeekCurrent)) \
356    << "file_offset=" << file_offset << " offset_=" << offset_
357
358OatWriter::OatWriter(bool compiling_boot_image,
359                     TimingLogger* timings,
360                     ProfileCompilationInfo* info,
361                     CompactDexLevel compact_dex_level)
362  : write_state_(WriteState::kAddingDexFileSources),
363    timings_(timings),
364    raw_dex_files_(),
365    zip_archives_(),
366    zipped_dex_files_(),
367    zipped_dex_file_locations_(),
368    compiler_driver_(nullptr),
369    image_writer_(nullptr),
370    compiling_boot_image_(compiling_boot_image),
371    extract_dex_files_into_vdex_(true),
372    dex_files_(nullptr),
373    vdex_size_(0u),
374    vdex_dex_files_offset_(0u),
375    vdex_dex_shared_data_offset_(0u),
376    vdex_verifier_deps_offset_(0u),
377    vdex_quickening_info_offset_(0u),
378    oat_size_(0u),
379    bss_start_(0u),
380    bss_size_(0u),
381    bss_methods_offset_(0u),
382    bss_roots_offset_(0u),
383    bss_method_entry_references_(),
384    bss_method_entries_(),
385    bss_type_entries_(),
386    bss_string_entries_(),
387    map_boot_image_tables_to_bss_(false),
388    oat_data_offset_(0u),
389    oat_header_(nullptr),
390    size_vdex_header_(0),
391    size_vdex_checksums_(0),
392    size_dex_file_alignment_(0),
393    size_executable_offset_alignment_(0),
394    size_oat_header_(0),
395    size_oat_header_key_value_store_(0),
396    size_dex_file_(0),
397    size_verifier_deps_(0),
398    size_verifier_deps_alignment_(0),
399    size_quickening_info_(0),
400    size_quickening_info_alignment_(0),
401    size_interpreter_to_interpreter_bridge_(0),
402    size_interpreter_to_compiled_code_bridge_(0),
403    size_jni_dlsym_lookup_(0),
404    size_quick_generic_jni_trampoline_(0),
405    size_quick_imt_conflict_trampoline_(0),
406    size_quick_resolution_trampoline_(0),
407    size_quick_to_interpreter_bridge_(0),
408    size_trampoline_alignment_(0),
409    size_method_header_(0),
410    size_code_(0),
411    size_code_alignment_(0),
412    size_relative_call_thunks_(0),
413    size_misc_thunks_(0),
414    size_vmap_table_(0),
415    size_method_info_(0),
416    size_oat_dex_file_location_size_(0),
417    size_oat_dex_file_location_data_(0),
418    size_oat_dex_file_location_checksum_(0),
419    size_oat_dex_file_offset_(0),
420    size_oat_dex_file_class_offsets_offset_(0),
421    size_oat_dex_file_lookup_table_offset_(0),
422    size_oat_dex_file_dex_layout_sections_offset_(0),
423    size_oat_dex_file_dex_layout_sections_(0),
424    size_oat_dex_file_dex_layout_sections_alignment_(0),
425    size_oat_dex_file_method_bss_mapping_offset_(0),
426    size_oat_dex_file_type_bss_mapping_offset_(0),
427    size_oat_dex_file_string_bss_mapping_offset_(0),
428    size_oat_lookup_table_alignment_(0),
429    size_oat_lookup_table_(0),
430    size_oat_class_offsets_alignment_(0),
431    size_oat_class_offsets_(0),
432    size_oat_class_type_(0),
433    size_oat_class_status_(0),
434    size_oat_class_method_bitmaps_(0),
435    size_oat_class_method_offsets_(0),
436    size_method_bss_mappings_(0u),
437    size_type_bss_mappings_(0u),
438    size_string_bss_mappings_(0u),
439    relative_patcher_(nullptr),
440    absolute_patch_locations_(),
441    profile_compilation_info_(info),
442    compact_dex_level_(compact_dex_level) {
443  // If we have a profile, always use at least the default compact dex level. The reason behind
444  // this is that CompactDex conversion is not more expensive than normal dexlayout.
445  if (info != nullptr && compact_dex_level_ == CompactDexLevel::kCompactDexLevelNone) {
446    compact_dex_level_ = kDefaultCompactDexLevel;
447  }
448}
449
450static bool ValidateDexFileHeader(const uint8_t* raw_header, const char* location) {
451  const bool valid_standard_dex_magic = DexFileLoader::IsMagicValid(raw_header);
452  if (!valid_standard_dex_magic) {
453    LOG(ERROR) << "Invalid magic number in dex file header. " << " File: " << location;
454    return false;
455  }
456  if (!DexFileLoader::IsVersionAndMagicValid(raw_header)) {
457    LOG(ERROR) << "Invalid version number in dex file header. " << " File: " << location;
458    return false;
459  }
460  const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_header);
461  if (header->file_size_ < sizeof(DexFile::Header)) {
462    LOG(ERROR) << "Dex file header specifies file size insufficient to contain the header."
463               << " File: " << location;
464    return false;
465  }
466  return true;
467}
468
469static const UnalignedDexFileHeader* GetDexFileHeader(File* file,
470                                                      uint8_t* raw_header,
471                                                      const char* location) {
472  // Read the dex file header and perform minimal verification.
473  if (!file->ReadFully(raw_header, sizeof(DexFile::Header))) {
474    PLOG(ERROR) << "Failed to read dex file header. Actual: "
475                << " File: " << location << " Output: " << file->GetPath();
476    return nullptr;
477  }
478  if (!ValidateDexFileHeader(raw_header, location)) {
479    return nullptr;
480  }
481
482  return AsUnalignedDexFileHeader(raw_header);
483}
484
485bool OatWriter::AddDexFileSource(const char* filename,
486                                 const char* location,
487                                 CreateTypeLookupTable create_type_lookup_table) {
488  DCHECK(write_state_ == WriteState::kAddingDexFileSources);
489  uint32_t magic;
490  std::string error_msg;
491  File fd = OpenAndReadMagic(filename, &magic, &error_msg);
492  if (fd.Fd() == -1) {
493    PLOG(ERROR) << "Failed to read magic number from dex file: '" << filename << "'";
494    return false;
495  } else if (DexFileLoader::IsMagicValid(magic)) {
496    uint8_t raw_header[sizeof(DexFile::Header)];
497    const UnalignedDexFileHeader* header = GetDexFileHeader(&fd, raw_header, location);
498    if (header == nullptr) {
499      return false;
500    }
501    // The file is open for reading, not writing, so it's OK to let the File destructor
502    // close it without checking for explicit Close(), so pass checkUsage = false.
503    raw_dex_files_.emplace_back(new File(fd.Release(), location, /* checkUsage */ false));
504    oat_dex_files_.emplace_back(/* OatDexFile */
505        location,
506        DexFileSource(raw_dex_files_.back().get()),
507        create_type_lookup_table,
508        header->checksum_,
509        header->file_size_);
510  } else if (IsZipMagic(magic)) {
511    if (!AddZippedDexFilesSource(std::move(fd), location, create_type_lookup_table)) {
512      return false;
513    }
514  } else {
515    LOG(ERROR) << "Expected valid zip or dex file: '" << filename << "'";
516    return false;
517  }
518  return true;
519}
520
521// Add dex file source(s) from a zip file specified by a file handle.
522bool OatWriter::AddZippedDexFilesSource(File&& zip_fd,
523                                        const char* location,
524                                        CreateTypeLookupTable create_type_lookup_table) {
525  DCHECK(write_state_ == WriteState::kAddingDexFileSources);
526  std::string error_msg;
527  zip_archives_.emplace_back(ZipArchive::OpenFromFd(zip_fd.Release(), location, &error_msg));
528  ZipArchive* zip_archive = zip_archives_.back().get();
529  if (zip_archive == nullptr) {
530    LOG(ERROR) << "Failed to open zip from file descriptor for '" << location << "': "
531        << error_msg;
532    return false;
533  }
534  for (size_t i = 0; ; ++i) {
535    std::string entry_name = DexFileLoader::GetMultiDexClassesDexName(i);
536    std::unique_ptr<ZipEntry> entry(zip_archive->Find(entry_name.c_str(), &error_msg));
537    if (entry == nullptr) {
538      break;
539    }
540    zipped_dex_files_.push_back(std::move(entry));
541    zipped_dex_file_locations_.push_back(DexFileLoader::GetMultiDexLocation(i, location));
542    const char* full_location = zipped_dex_file_locations_.back().c_str();
543    // We override the checksum from header with the CRC from ZIP entry.
544    oat_dex_files_.emplace_back(/* OatDexFile */
545        full_location,
546        DexFileSource(zipped_dex_files_.back().get()),
547        create_type_lookup_table,
548        zipped_dex_files_.back()->GetCrc32(),
549        zipped_dex_files_.back()->GetUncompressedLength());
550  }
551  if (zipped_dex_file_locations_.empty()) {
552    LOG(ERROR) << "No dex files in zip file '" << location << "': " << error_msg;
553    return false;
554  }
555  return true;
556}
557
558// Add dex file source(s) from a vdex file specified by a file handle.
559bool OatWriter::AddVdexDexFilesSource(const VdexFile& vdex_file,
560                                      const char* location,
561                                      CreateTypeLookupTable create_type_lookup_table) {
562  DCHECK(write_state_ == WriteState::kAddingDexFileSources);
563  DCHECK(vdex_file.HasDexSection());
564  const uint8_t* current_dex_data = nullptr;
565  for (size_t i = 0; i < vdex_file.GetVerifierDepsHeader().GetNumberOfDexFiles(); ++i) {
566    current_dex_data = vdex_file.GetNextDexFileData(current_dex_data);
567    if (current_dex_data == nullptr) {
568      LOG(ERROR) << "Unexpected number of dex files in vdex " << location;
569      return false;
570    }
571
572    if (!DexFileLoader::IsMagicValid(current_dex_data)) {
573      LOG(ERROR) << "Invalid magic in vdex file created from " << location;
574      return false;
575    }
576    // We used `zipped_dex_file_locations_` to keep the strings in memory.
577    zipped_dex_file_locations_.push_back(DexFileLoader::GetMultiDexLocation(i, location));
578    const char* full_location = zipped_dex_file_locations_.back().c_str();
579    const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(current_dex_data);
580    oat_dex_files_.emplace_back(/* OatDexFile */
581        full_location,
582        DexFileSource(current_dex_data),
583        create_type_lookup_table,
584        vdex_file.GetLocationChecksum(i),
585        header->file_size_);
586  }
587
588  if (vdex_file.GetNextDexFileData(current_dex_data) != nullptr) {
589    LOG(ERROR) << "Unexpected number of dex files in vdex " << location;
590    return false;
591  }
592
593  if (oat_dex_files_.empty()) {
594    LOG(ERROR) << "No dex files in vdex file created from " << location;
595    return false;
596  }
597  return true;
598}
599
600// Add dex file source from raw memory.
601bool OatWriter::AddRawDexFileSource(const ArrayRef<const uint8_t>& data,
602                                    const char* location,
603                                    uint32_t location_checksum,
604                                    CreateTypeLookupTable create_type_lookup_table) {
605  DCHECK(write_state_ == WriteState::kAddingDexFileSources);
606  if (data.size() < sizeof(DexFile::Header)) {
607    LOG(ERROR) << "Provided data is shorter than dex file header. size: "
608               << data.size() << " File: " << location;
609    return false;
610  }
611  if (!ValidateDexFileHeader(data.data(), location)) {
612    return false;
613  }
614  const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(data.data());
615  if (data.size() < header->file_size_) {
616    LOG(ERROR) << "Truncated dex file data. Data size: " << data.size()
617               << " file size from header: " << header->file_size_ << " File: " << location;
618    return false;
619  }
620
621  oat_dex_files_.emplace_back(/* OatDexFile */
622      location,
623      DexFileSource(data.data()),
624      create_type_lookup_table,
625      location_checksum,
626      header->file_size_);
627  return true;
628}
629
630dchecked_vector<std::string> OatWriter::GetSourceLocations() const {
631  dchecked_vector<std::string> locations;
632  locations.reserve(oat_dex_files_.size());
633  for (const OatDexFile& oat_dex_file : oat_dex_files_) {
634    locations.push_back(oat_dex_file.GetLocation());
635  }
636  return locations;
637}
638
639bool OatWriter::MayHaveCompiledMethods() const {
640  return CompilerFilter::IsAnyCompilationEnabled(
641      GetCompilerDriver()->GetCompilerOptions().GetCompilerFilter());
642}
643
644bool OatWriter::WriteAndOpenDexFiles(
645    File* vdex_file,
646    OutputStream* oat_rodata,
647    InstructionSet instruction_set,
648    const InstructionSetFeatures* instruction_set_features,
649    SafeMap<std::string, std::string>* key_value_store,
650    bool verify,
651    bool update_input_vdex,
652    CopyOption copy_dex_files,
653    /*out*/ std::vector<std::unique_ptr<MemMap>>* opened_dex_files_map,
654    /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) {
655  CHECK(write_state_ == WriteState::kAddingDexFileSources);
656
657  // Record the ELF rodata section offset, i.e. the beginning of the OAT data.
658  if (!RecordOatDataOffset(oat_rodata)) {
659     return false;
660  }
661
662  std::vector<std::unique_ptr<MemMap>> dex_files_map;
663  std::vector<std::unique_ptr<const DexFile>> dex_files;
664
665  // Initialize VDEX and OAT headers.
666
667  // Reserve space for Vdex header and checksums.
668  vdex_size_ = sizeof(VdexFile::VerifierDepsHeader) +
669      oat_dex_files_.size() * sizeof(VdexFile::VdexChecksum);
670  oat_size_ = InitOatHeader(instruction_set,
671                            instruction_set_features,
672                            dchecked_integral_cast<uint32_t>(oat_dex_files_.size()),
673                            key_value_store);
674
675  ChecksumUpdatingOutputStream checksum_updating_rodata(oat_rodata, oat_header_.get());
676
677  std::unique_ptr<BufferedOutputStream> vdex_out =
678      std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(vdex_file));
679  // Write DEX files into VDEX, mmap and open them.
680  if (!WriteDexFiles(vdex_out.get(), vdex_file, update_input_vdex, copy_dex_files) ||
681      !OpenDexFiles(vdex_file, verify, &dex_files_map, &dex_files)) {
682    return false;
683  }
684
685  // Write type lookup tables into the oat file.
686  if (!WriteTypeLookupTables(&checksum_updating_rodata, dex_files)) {
687    return false;
688  }
689
690  // Write dex layout sections into the oat file.
691  if (!WriteDexLayoutSections(&checksum_updating_rodata, dex_files)) {
692    return false;
693  }
694
695  *opened_dex_files_map = std::move(dex_files_map);
696  *opened_dex_files = std::move(dex_files);
697  write_state_ = WriteState::kPrepareLayout;
698  return true;
699}
700
701void OatWriter::PrepareLayout(MultiOatRelativePatcher* relative_patcher) {
702  CHECK(write_state_ == WriteState::kPrepareLayout);
703
704  relative_patcher_ = relative_patcher;
705  SetMultiOatRelativePatcherAdjustment();
706
707  if (compiling_boot_image_) {
708    CHECK(image_writer_ != nullptr);
709  }
710  InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
711  CHECK_EQ(instruction_set, oat_header_->GetInstructionSet());
712
713  {
714    TimingLogger::ScopedTiming split("InitBssLayout", timings_);
715    InitBssLayout(instruction_set);
716  }
717
718  uint32_t offset = oat_size_;
719  {
720    TimingLogger::ScopedTiming split("InitClassOffsets", timings_);
721    offset = InitClassOffsets(offset);
722  }
723  {
724    TimingLogger::ScopedTiming split("InitOatClasses", timings_);
725    offset = InitOatClasses(offset);
726  }
727  {
728    TimingLogger::ScopedTiming split("InitIndexBssMappings", timings_);
729    offset = InitIndexBssMappings(offset);
730  }
731  {
732    TimingLogger::ScopedTiming split("InitOatMaps", timings_);
733    offset = InitOatMaps(offset);
734  }
735  {
736    TimingLogger::ScopedTiming split("InitOatDexFiles", timings_);
737    oat_header_->SetOatDexFilesOffset(offset);
738    offset = InitOatDexFiles(offset);
739  }
740  {
741    TimingLogger::ScopedTiming split("InitOatCode", timings_);
742    offset = InitOatCode(offset);
743  }
744  {
745    TimingLogger::ScopedTiming split("InitOatCodeDexFiles", timings_);
746    offset = InitOatCodeDexFiles(offset);
747  }
748  oat_size_ = offset;
749  bss_start_ = (bss_size_ != 0u) ? RoundUp(oat_size_, kPageSize) : 0u;
750
751  CHECK_EQ(dex_files_->size(), oat_dex_files_.size());
752  if (compiling_boot_image_) {
753    CHECK_EQ(image_writer_ != nullptr,
754             oat_header_->GetStoreValueByKey(OatHeader::kImageLocationKey) == nullptr);
755  }
756
757  write_state_ = WriteState::kWriteRoData;
758}
759
760OatWriter::~OatWriter() {
761}
762
763class OatWriter::DexMethodVisitor {
764 public:
765  DexMethodVisitor(OatWriter* writer, size_t offset)
766      : writer_(writer),
767        offset_(offset),
768        dex_file_(nullptr),
769        class_def_index_(dex::kDexNoIndex) {}
770
771  virtual bool StartClass(const DexFile* dex_file, size_t class_def_index) {
772    DCHECK(dex_file_ == nullptr);
773    DCHECK_EQ(class_def_index_, dex::kDexNoIndex);
774    dex_file_ = dex_file;
775    class_def_index_ = class_def_index;
776    return true;
777  }
778
779  virtual bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) = 0;
780
781  virtual bool EndClass() {
782    if (kIsDebugBuild) {
783      dex_file_ = nullptr;
784      class_def_index_ = dex::kDexNoIndex;
785    }
786    return true;
787  }
788
789  size_t GetOffset() const {
790    return offset_;
791  }
792
793 protected:
794  virtual ~DexMethodVisitor() { }
795
796  OatWriter* const writer_;
797
798  // The offset is usually advanced for each visited method by the derived class.
799  size_t offset_;
800
801  // The dex file and class def index are set in StartClass().
802  const DexFile* dex_file_;
803  size_t class_def_index_;
804};
805
806class OatWriter::OatDexMethodVisitor : public DexMethodVisitor {
807 public:
808  OatDexMethodVisitor(OatWriter* writer, size_t offset)
809      : DexMethodVisitor(writer, offset),
810        oat_class_index_(0u),
811        method_offsets_index_(0u) {}
812
813  bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE {
814    DexMethodVisitor::StartClass(dex_file, class_def_index);
815    if (kIsDebugBuild && writer_->MayHaveCompiledMethods()) {
816      // There are no oat classes if there aren't any compiled methods.
817      CHECK_LT(oat_class_index_, writer_->oat_classes_.size());
818    }
819    method_offsets_index_ = 0u;
820    return true;
821  }
822
823  bool EndClass() OVERRIDE {
824    ++oat_class_index_;
825    return DexMethodVisitor::EndClass();
826  }
827
828 protected:
829  size_t oat_class_index_;
830  size_t method_offsets_index_;
831};
832
833static bool HasCompiledCode(const CompiledMethod* method) {
834  return method != nullptr && !method->GetQuickCode().empty();
835}
836
837static bool HasQuickeningInfo(const CompiledMethod* method) {
838  // The dextodexcompiler puts the quickening info table into the CompiledMethod
839  // for simplicity.
840  return method != nullptr && method->GetQuickCode().empty() && !method->GetVmapTable().empty();
841}
842
843class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor {
844 public:
845  explicit InitBssLayoutMethodVisitor(OatWriter* writer)
846      : DexMethodVisitor(writer, /* offset */ 0u) {}
847
848  bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED,
849                   const ClassDataItemIterator& it) OVERRIDE {
850    // Look for patches with .bss references and prepare maps with placeholders for their offsets.
851    CompiledMethod* compiled_method = writer_->compiler_driver_->GetCompiledMethod(
852        MethodReference(dex_file_, it.GetMemberIndex()));
853    if (HasCompiledCode(compiled_method)) {
854      for (const LinkerPatch& patch : compiled_method->GetPatches()) {
855        if (patch.GetType() == LinkerPatch::Type::kMethodBssEntry) {
856          MethodReference target_method = patch.TargetMethod();
857          AddBssReference(target_method,
858                          target_method.dex_file->NumMethodIds(),
859                          &writer_->bss_method_entry_references_);
860          writer_->bss_method_entries_.Overwrite(target_method, /* placeholder */ 0u);
861        } else if (patch.GetType() == LinkerPatch::Type::kTypeBssEntry) {
862          TypeReference target_type(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
863          AddBssReference(target_type,
864                          target_type.dex_file->NumTypeIds(),
865                          &writer_->bss_type_entry_references_);
866          writer_->bss_type_entries_.Overwrite(target_type, /* placeholder */ 0u);
867        } else if (patch.GetType() == LinkerPatch::Type::kStringBssEntry) {
868          StringReference target_string(patch.TargetStringDexFile(), patch.TargetStringIndex());
869          AddBssReference(target_string,
870                          target_string.dex_file->NumStringIds(),
871                          &writer_->bss_string_entry_references_);
872          writer_->bss_string_entries_.Overwrite(target_string, /* placeholder */ 0u);
873        } else if (patch.GetType() == LinkerPatch::Type::kStringInternTable ||
874                   patch.GetType() == LinkerPatch::Type::kTypeClassTable) {
875          writer_->map_boot_image_tables_to_bss_ = true;
876        }
877      }
878    } else {
879      DCHECK(compiled_method == nullptr || compiled_method->GetPatches().empty());
880    }
881    return true;
882  }
883
884 private:
885  void AddBssReference(const DexFileReference& ref,
886                       size_t number_of_indexes,
887                       /*inout*/ SafeMap<const DexFile*, BitVector>* references) {
888    // We currently support inlining of throwing instructions only when they originate in the
889    // same dex file as the outer method. All .bss references are used by throwing instructions.
890    DCHECK_EQ(dex_file_, ref.dex_file);
891
892    auto refs_it = references->find(ref.dex_file);
893    if (refs_it == references->end()) {
894      refs_it = references->Put(
895          ref.dex_file,
896          BitVector(number_of_indexes, /* expandable */ false, Allocator::GetMallocAllocator()));
897      refs_it->second.ClearAllBits();
898    }
899    refs_it->second.SetBit(ref.index);
900  }
901};
902
903class OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor {
904 public:
905  InitOatClassesMethodVisitor(OatWriter* writer, size_t offset)
906      : DexMethodVisitor(writer, offset),
907        compiled_methods_(),
908        compiled_methods_with_code_(0u) {
909    size_t num_classes = 0u;
910    for (const OatDexFile& oat_dex_file : writer_->oat_dex_files_) {
911      num_classes += oat_dex_file.class_offsets_.size();
912    }
913    // If we aren't compiling only reserve headers.
914    writer_->oat_class_headers_.reserve(num_classes);
915    if (writer->MayHaveCompiledMethods()) {
916      writer->oat_classes_.reserve(num_classes);
917    }
918    compiled_methods_.reserve(256u);
919    // If there are any classes, the class offsets allocation aligns the offset.
920    DCHECK(num_classes == 0u || IsAligned<4u>(offset));
921  }
922
923  bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE {
924    DexMethodVisitor::StartClass(dex_file, class_def_index);
925    compiled_methods_.clear();
926    compiled_methods_with_code_ = 0u;
927    return true;
928  }
929
930  bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED,
931                   const ClassDataItemIterator& it) OVERRIDE {
932    // Fill in the compiled_methods_ array for methods that have a
933    // CompiledMethod. We track the number of non-null entries in
934    // compiled_methods_with_code_ since we only want to allocate
935    // OatMethodOffsets for the compiled methods.
936    uint32_t method_idx = it.GetMemberIndex();
937    CompiledMethod* compiled_method =
938        writer_->compiler_driver_->GetCompiledMethod(MethodReference(dex_file_, method_idx));
939    compiled_methods_.push_back(compiled_method);
940    if (HasCompiledCode(compiled_method)) {
941      ++compiled_methods_with_code_;
942    }
943    return true;
944  }
945
946  bool EndClass() OVERRIDE {
947    ClassReference class_ref(dex_file_, class_def_index_);
948    ClassStatus status;
949    bool found = writer_->compiler_driver_->GetCompiledClass(class_ref, &status);
950    if (!found) {
951      VerificationResults* results = writer_->compiler_driver_->GetVerificationResults();
952      if (results != nullptr && results->IsClassRejected(class_ref)) {
953        // The oat class status is used only for verification of resolved classes,
954        // so use ClassStatus::kErrorResolved whether the class was resolved or unresolved
955        // during compile-time verification.
956        status = ClassStatus::kErrorResolved;
957      } else {
958        status = ClassStatus::kNotReady;
959      }
960    }
961
962    writer_->oat_class_headers_.emplace_back(offset_,
963                                             compiled_methods_with_code_,
964                                             compiled_methods_.size(),
965                                             status);
966    OatClassHeader& header = writer_->oat_class_headers_.back();
967    offset_ += header.SizeOf();
968    if (writer_->MayHaveCompiledMethods()) {
969      writer_->oat_classes_.emplace_back(compiled_methods_,
970                                         compiled_methods_with_code_,
971                                         header.type_);
972      offset_ += writer_->oat_classes_.back().SizeOf();
973    }
974    return DexMethodVisitor::EndClass();
975  }
976
977 private:
978  dchecked_vector<CompiledMethod*> compiled_methods_;
979  size_t compiled_methods_with_code_;
980};
981
982// CompiledMethod + metadata required to do ordered method layout.
983//
984// See also OrderedMethodVisitor.
985struct OatWriter::OrderedMethodData {
986  ProfileCompilationInfo::MethodHotness method_hotness;
987  OatClass* oat_class;
988  CompiledMethod* compiled_method;
989  MethodReference method_reference;
990  size_t method_offsets_index;
991
992  size_t class_def_index;
993  uint32_t access_flags;
994  const DexFile::CodeItem* code_item;
995
996  // A value of -1 denotes missing debug info
997  static constexpr size_t kDebugInfoIdxInvalid = static_cast<size_t>(-1);
998  // Index into writer_->method_info_
999  size_t debug_info_idx;
1000
1001  bool HasDebugInfo() const {
1002    return debug_info_idx != kDebugInfoIdxInvalid;
1003  }
1004
1005  // Bin each method according to the profile flags.
1006  //
1007  // Groups by e.g.
1008  //  -- not hot at all
1009  //  -- hot
1010  //  -- hot and startup
1011  //  -- hot and post-startup
1012  //  -- hot and startup and poststartup
1013  //  -- startup
1014  //  -- startup and post-startup
1015  //  -- post-startup
1016  //
1017  // (See MethodHotness enum definition for up-to-date binning order.)
1018  bool operator<(const OrderedMethodData& other) const {
1019    if (kOatWriterForceOatCodeLayout) {
1020      // Development flag: Override default behavior by sorting by name.
1021
1022      std::string name = method_reference.PrettyMethod();
1023      std::string other_name = other.method_reference.PrettyMethod();
1024      return name < other_name;
1025    }
1026
1027    // Use the profile's method hotness to determine sort order.
1028    if (GetMethodHotnessOrder() < other.GetMethodHotnessOrder()) {
1029      return true;
1030    }
1031
1032    // Default: retain the original order.
1033    return false;
1034  }
1035
1036 private:
1037  // Used to determine relative order for OAT code layout when determining
1038  // binning.
1039  size_t GetMethodHotnessOrder() const {
1040    bool hotness[] = {
1041      method_hotness.IsHot(),
1042      method_hotness.IsStartup(),
1043      method_hotness.IsPostStartup()
1044    };
1045
1046
1047    // Note: Bin-to-bin order does not matter. If the kernel does or does not read-ahead
1048    // any memory, it only goes into the buffer cache and does not grow the PSS until the first
1049    // time that memory is referenced in the process.
1050
1051    size_t hotness_bits = 0;
1052    for (size_t i = 0; i < arraysize(hotness); ++i) {
1053      if (hotness[i]) {
1054        hotness_bits |= (1 << i);
1055      }
1056    }
1057
1058    if (kIsDebugBuild) {
1059      // Check for bins that are always-empty given a real profile.
1060      if (method_hotness.IsHot() &&
1061              !method_hotness.IsStartup() && !method_hotness.IsPostStartup()) {
1062        std::string name = method_reference.PrettyMethod();
1063        LOG(FATAL) << "Method " << name << " had a Hot method that wasn't marked "
1064                   << "either start-up or post-startup. Possible corrupted profile?";
1065        // This is not fatal, so only warn.
1066      }
1067    }
1068
1069    return hotness_bits;
1070  }
1071};
1072
1073// Given a queue of CompiledMethod in some total order,
1074// visit each one in that order.
1075class OatWriter::OrderedMethodVisitor {
1076 public:
1077  explicit OrderedMethodVisitor(OrderedMethodList ordered_methods)
1078      : ordered_methods_(std::move(ordered_methods)) {
1079  }
1080
1081  virtual ~OrderedMethodVisitor() {}
1082
1083  // Invoke VisitMethod in the order of `ordered_methods`, then invoke VisitComplete.
1084  bool Visit() REQUIRES_SHARED(Locks::mutator_lock_) {
1085    if (!VisitStart()) {
1086      return false;
1087    }
1088
1089    for (const OrderedMethodData& method_data : ordered_methods_)  {
1090      if (!VisitMethod(method_data)) {
1091        return false;
1092      }
1093    }
1094
1095    return VisitComplete();
1096  }
1097
1098  // Invoked once at the beginning, prior to visiting anything else.
1099  //
1100  // Return false to abort further visiting.
1101  virtual bool VisitStart() { return true; }
1102
1103  // Invoked repeatedly in the order specified by `ordered_methods`.
1104  //
1105  // Return false to short-circuit and to stop visiting further methods.
1106  virtual bool VisitMethod(const OrderedMethodData& method_data)
1107      REQUIRES_SHARED(Locks::mutator_lock_)  = 0;
1108
1109  // Invoked once at the end, after every other method has been successfully visited.
1110  //
1111  // Return false to indicate the overall `Visit` has failed.
1112  virtual bool VisitComplete() = 0;
1113
1114  OrderedMethodList ReleaseOrderedMethods() {
1115    return std::move(ordered_methods_);
1116  }
1117
1118 private:
1119  // List of compiled methods, sorted by the order defined in OrderedMethodData.
1120  // Methods can be inserted more than once in case of duplicated methods.
1121  OrderedMethodList ordered_methods_;
1122};
1123
1124// Visit every compiled method in order to determine its order within the OAT file.
1125// Methods from the same class do not need to be adjacent in the OAT code.
1126class OatWriter::LayoutCodeMethodVisitor : public OatDexMethodVisitor {
1127 public:
1128  LayoutCodeMethodVisitor(OatWriter* writer, size_t offset)
1129      : OatDexMethodVisitor(writer, offset) {
1130  }
1131
1132  bool EndClass() OVERRIDE {
1133    OatDexMethodVisitor::EndClass();
1134    return true;
1135  }
1136
1137  bool VisitMethod(size_t class_def_method_index,
1138                   const ClassDataItemIterator& it)
1139      OVERRIDE
1140      REQUIRES_SHARED(Locks::mutator_lock_)  {
1141    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
1142
1143    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
1144    CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
1145
1146    if (HasCompiledCode(compiled_method)) {
1147      size_t debug_info_idx = OrderedMethodData::kDebugInfoIdxInvalid;
1148
1149      {
1150        const CompilerOptions& compiler_options = writer_->compiler_driver_->GetCompilerOptions();
1151        ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode();
1152        uint32_t code_size = quick_code.size() * sizeof(uint8_t);
1153
1154        // Debug method info must be pushed in the original order
1155        // (i.e. all methods from the same class must be adjacent in the debug info sections)
1156        // ElfCompilationUnitWriter::Write requires this.
1157        if (compiler_options.GenerateAnyDebugInfo() && code_size != 0) {
1158          debug::MethodDebugInfo info = debug::MethodDebugInfo();
1159          writer_->method_info_.push_back(info);
1160
1161          // The debug info is filled in LayoutReserveOffsetCodeMethodVisitor
1162          // once we know the offsets.
1163          //
1164          // Store the index into writer_->method_info_ since future push-backs
1165          // could reallocate and change the underlying data address.
1166          debug_info_idx = writer_->method_info_.size() - 1;
1167        }
1168      }
1169
1170      MethodReference method_ref(dex_file_, it.GetMemberIndex());
1171
1172      // Lookup method hotness from profile, if available.
1173      // Otherwise assume a default of none-hotness.
1174      ProfileCompilationInfo::MethodHotness method_hotness =
1175          writer_->profile_compilation_info_ != nullptr
1176              ? writer_->profile_compilation_info_->GetMethodHotness(method_ref)
1177              : ProfileCompilationInfo::MethodHotness();
1178
1179      // Handle duplicate methods by pushing them repeatedly.
1180      OrderedMethodData method_data = {
1181          method_hotness,
1182          oat_class,
1183          compiled_method,
1184          method_ref,
1185          method_offsets_index_,
1186          class_def_index_,
1187          it.GetMethodAccessFlags(),
1188          it.GetMethodCodeItem(),
1189          debug_info_idx
1190      };
1191      ordered_methods_.push_back(method_data);
1192
1193      method_offsets_index_++;
1194    }
1195
1196    return true;
1197  }
1198
1199  OrderedMethodList ReleaseOrderedMethods() {
1200    if (kOatWriterForceOatCodeLayout || writer_->profile_compilation_info_ != nullptr) {
1201      // Sort by the method ordering criteria (in OrderedMethodData).
1202      // Since most methods will have the same ordering criteria,
1203      // we preserve the original insertion order within the same sort order.
1204      std::stable_sort(ordered_methods_.begin(), ordered_methods_.end());
1205    } else {
1206      // The profile-less behavior is as if every method had 0 hotness
1207      // associated with it.
1208      //
1209      // Since sorting all methods with hotness=0 should give back the same
1210      // order as before, don't do anything.
1211      DCHECK(std::is_sorted(ordered_methods_.begin(), ordered_methods_.end()));
1212    }
1213
1214    return std::move(ordered_methods_);
1215  }
1216
1217 private:
1218  // List of compiled methods, later to be sorted by order defined in OrderedMethodData.
1219  // Methods can be inserted more than once in case of duplicated methods.
1220  OrderedMethodList ordered_methods_;
1221};
1222
1223// Given a method order, reserve the offsets for each CompiledMethod in the OAT file.
1224class OatWriter::LayoutReserveOffsetCodeMethodVisitor : public OrderedMethodVisitor {
1225 public:
1226  LayoutReserveOffsetCodeMethodVisitor(OatWriter* writer,
1227                                       size_t offset,
1228                                       OrderedMethodList ordered_methods)
1229      : LayoutReserveOffsetCodeMethodVisitor(writer,
1230                                             offset,
1231                                             writer->GetCompilerDriver()->GetCompilerOptions(),
1232                                             std::move(ordered_methods)) {
1233  }
1234
1235  virtual bool VisitComplete() OVERRIDE {
1236    offset_ = writer_->relative_patcher_->ReserveSpaceEnd(offset_);
1237    if (generate_debug_info_) {
1238      std::vector<debug::MethodDebugInfo> thunk_infos =
1239          relative_patcher_->GenerateThunkDebugInfo(executable_offset_);
1240      writer_->method_info_.insert(writer_->method_info_.end(),
1241                                   std::make_move_iterator(thunk_infos.begin()),
1242                                   std::make_move_iterator(thunk_infos.end()));
1243    }
1244    return true;
1245  }
1246
1247  virtual bool VisitMethod(const OrderedMethodData& method_data)
1248      OVERRIDE
1249      REQUIRES_SHARED(Locks::mutator_lock_) {
1250    OatClass* oat_class = method_data.oat_class;
1251    CompiledMethod* compiled_method = method_data.compiled_method;
1252    const MethodReference& method_ref = method_data.method_reference;
1253    uint16_t method_offsets_index_ = method_data.method_offsets_index;
1254    size_t class_def_index = method_data.class_def_index;
1255    uint32_t access_flags = method_data.access_flags;
1256    bool has_debug_info = method_data.HasDebugInfo();
1257    size_t debug_info_idx = method_data.debug_info_idx;
1258
1259    DCHECK(HasCompiledCode(compiled_method)) << method_ref.PrettyMethod();
1260
1261    // Derived from CompiledMethod.
1262    uint32_t quick_code_offset = 0;
1263
1264    ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode();
1265    uint32_t code_size = quick_code.size() * sizeof(uint8_t);
1266    uint32_t thumb_offset = compiled_method->CodeDelta();
1267
1268    // Deduplicate code arrays if we are not producing debuggable code.
1269    bool deduped = true;
1270    if (debuggable_) {
1271      quick_code_offset = relative_patcher_->GetOffset(method_ref);
1272      if (quick_code_offset != 0u) {
1273        // Duplicate methods, we want the same code for both of them so that the oat writer puts
1274        // the same code in both ArtMethods so that we do not get different oat code at runtime.
1275      } else {
1276        quick_code_offset = NewQuickCodeOffset(compiled_method, method_ref, thumb_offset);
1277        deduped = false;
1278      }
1279    } else {
1280      quick_code_offset = dedupe_map_.GetOrCreate(
1281          compiled_method,
1282          [this, &deduped, compiled_method, &method_ref, thumb_offset]() {
1283            deduped = false;
1284            return NewQuickCodeOffset(compiled_method, method_ref, thumb_offset);
1285          });
1286    }
1287
1288    if (code_size != 0) {
1289      if (relative_patcher_->GetOffset(method_ref) != 0u) {
1290        // TODO: Should this be a hard failure?
1291        LOG(WARNING) << "Multiple definitions of "
1292            << method_ref.dex_file->PrettyMethod(method_ref.index)
1293            << " offsets " << relative_patcher_->GetOffset(method_ref)
1294            << " " << quick_code_offset;
1295      } else {
1296        relative_patcher_->SetOffset(method_ref, quick_code_offset);
1297      }
1298    }
1299
1300    // Update quick method header.
1301    DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size());
1302    OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_];
1303    uint32_t vmap_table_offset = method_header->GetVmapTableOffset();
1304    uint32_t method_info_offset = method_header->GetMethodInfoOffset();
1305    // The code offset was 0 when the mapping/vmap table offset was set, so it's set
1306    // to 0-offset and we need to adjust it by code_offset.
1307    uint32_t code_offset = quick_code_offset - thumb_offset;
1308    CHECK(!compiled_method->GetQuickCode().empty());
1309    // If the code is compiled, we write the offset of the stack map relative
1310    // to the code.
1311    if (vmap_table_offset != 0u) {
1312      vmap_table_offset += code_offset;
1313      DCHECK_LT(vmap_table_offset, code_offset);
1314    }
1315    if (method_info_offset != 0u) {
1316      method_info_offset += code_offset;
1317      DCHECK_LT(method_info_offset, code_offset);
1318    }
1319    uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
1320    uint32_t core_spill_mask = compiled_method->GetCoreSpillMask();
1321    uint32_t fp_spill_mask = compiled_method->GetFpSpillMask();
1322    *method_header = OatQuickMethodHeader(vmap_table_offset,
1323                                          method_info_offset,
1324                                          frame_size_in_bytes,
1325                                          core_spill_mask,
1326                                          fp_spill_mask,
1327                                          code_size);
1328
1329    if (!deduped) {
1330      // Update offsets. (Checksum is updated when writing.)
1331      offset_ += sizeof(*method_header);  // Method header is prepended before code.
1332      offset_ += code_size;
1333      // Record absolute patch locations.
1334      if (!compiled_method->GetPatches().empty()) {
1335        uintptr_t base_loc = offset_ - code_size - writer_->oat_header_->GetExecutableOffset();
1336        for (const LinkerPatch& patch : compiled_method->GetPatches()) {
1337          if (!patch.IsPcRelative()) {
1338            writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset());
1339          }
1340        }
1341      }
1342    }
1343
1344    // Exclude quickened dex methods (code_size == 0) since they have no native code.
1345    if (generate_debug_info_ && code_size != 0) {
1346      DCHECK(has_debug_info);
1347
1348      bool has_code_info = method_header->IsOptimized();
1349      // Record debug information for this function if we are doing that.
1350      debug::MethodDebugInfo& info = writer_->method_info_[debug_info_idx];
1351      DCHECK(info.custom_name.empty());
1352      info.dex_file = method_ref.dex_file;
1353      info.class_def_index = class_def_index;
1354      info.dex_method_index = method_ref.index;
1355      info.access_flags = access_flags;
1356      // For intrinsics emitted by codegen, the code has no relation to the original code item.
1357      info.code_item = compiled_method->IsIntrinsic() ? nullptr : method_data.code_item;
1358      info.isa = compiled_method->GetInstructionSet();
1359      info.deduped = deduped;
1360      info.is_native_debuggable = native_debuggable_;
1361      info.is_optimized = method_header->IsOptimized();
1362      info.is_code_address_text_relative = true;
1363      info.code_address = code_offset - executable_offset_;
1364      info.code_size = code_size;
1365      info.frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
1366      info.code_info = has_code_info ? compiled_method->GetVmapTable().data() : nullptr;
1367      info.cfi = compiled_method->GetCFIInfo();
1368    } else {
1369      DCHECK(!has_debug_info);
1370    }
1371
1372    DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
1373    OatMethodOffsets* offsets = &oat_class->method_offsets_[method_offsets_index_];
1374    offsets->code_offset_ = quick_code_offset;
1375
1376    return true;
1377  }
1378
1379  size_t GetOffset() const {
1380    return offset_;
1381  }
1382
1383 private:
1384  LayoutReserveOffsetCodeMethodVisitor(OatWriter* writer,
1385                                       size_t offset,
1386                                       const CompilerOptions& compiler_options,
1387                                       OrderedMethodList ordered_methods)
1388      : OrderedMethodVisitor(std::move(ordered_methods)),
1389        writer_(writer),
1390        offset_(offset),
1391        relative_patcher_(writer->relative_patcher_),
1392        executable_offset_(writer->oat_header_->GetExecutableOffset()),
1393        debuggable_(compiler_options.GetDebuggable()),
1394        native_debuggable_(compiler_options.GetNativeDebuggable()),
1395        generate_debug_info_(compiler_options.GenerateAnyDebugInfo()) {
1396    writer->absolute_patch_locations_.reserve(
1397        writer->GetCompilerDriver()->GetNonRelativeLinkerPatchCount());
1398  }
1399
1400  struct CodeOffsetsKeyComparator {
1401    bool operator()(const CompiledMethod* lhs, const CompiledMethod* rhs) const {
1402      // Code is deduplicated by CompilerDriver, compare only data pointers.
1403      if (lhs->GetQuickCode().data() != rhs->GetQuickCode().data()) {
1404        return lhs->GetQuickCode().data() < rhs->GetQuickCode().data();
1405      }
1406      // If the code is the same, all other fields are likely to be the same as well.
1407      if (UNLIKELY(lhs->GetVmapTable().data() != rhs->GetVmapTable().data())) {
1408        return lhs->GetVmapTable().data() < rhs->GetVmapTable().data();
1409      }
1410      if (UNLIKELY(lhs->GetMethodInfo().data() != rhs->GetMethodInfo().data())) {
1411        return lhs->GetMethodInfo().data() < rhs->GetMethodInfo().data();
1412      }
1413      if (UNLIKELY(lhs->GetPatches().data() != rhs->GetPatches().data())) {
1414        return lhs->GetPatches().data() < rhs->GetPatches().data();
1415      }
1416      if (UNLIKELY(lhs->IsIntrinsic() != rhs->IsIntrinsic())) {
1417        return rhs->IsIntrinsic();
1418      }
1419      return false;
1420    }
1421  };
1422
1423  uint32_t NewQuickCodeOffset(CompiledMethod* compiled_method,
1424                              const MethodReference& method_ref,
1425                              uint32_t thumb_offset) {
1426    offset_ = relative_patcher_->ReserveSpace(offset_, compiled_method, method_ref);
1427    offset_ += CodeAlignmentSize(offset_, *compiled_method);
1428    DCHECK_ALIGNED_PARAM(offset_ + sizeof(OatQuickMethodHeader),
1429                         GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
1430    return offset_ + sizeof(OatQuickMethodHeader) + thumb_offset;
1431  }
1432
1433  OatWriter* writer_;
1434
1435  // Offset of the code of the compiled methods.
1436  size_t offset_;
1437
1438  // Deduplication is already done on a pointer basis by the compiler driver,
1439  // so we can simply compare the pointers to find out if things are duplicated.
1440  SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_;
1441
1442  // Cache writer_'s members and compiler options.
1443  MultiOatRelativePatcher* relative_patcher_;
1444  uint32_t executable_offset_;
1445  const bool debuggable_;
1446  const bool native_debuggable_;
1447  const bool generate_debug_info_;
1448};
1449
1450class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor {
1451 public:
1452  InitMapMethodVisitor(OatWriter* writer, size_t offset)
1453      : OatDexMethodVisitor(writer, offset) {}
1454
1455  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it ATTRIBUTE_UNUSED)
1456      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
1457    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
1458    CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
1459
1460    if (HasCompiledCode(compiled_method)) {
1461      DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
1462      DCHECK_EQ(oat_class->method_headers_[method_offsets_index_].GetVmapTableOffset(), 0u);
1463
1464      ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
1465      uint32_t map_size = map.size() * sizeof(map[0]);
1466      if (map_size != 0u) {
1467        size_t offset = dedupe_map_.GetOrCreate(
1468            map.data(),
1469            [this, map_size]() {
1470              uint32_t new_offset = offset_;
1471              offset_ += map_size;
1472              return new_offset;
1473            });
1474        // Code offset is not initialized yet, so set the map offset to 0u-offset.
1475        DCHECK_EQ(oat_class->method_offsets_[method_offsets_index_].code_offset_, 0u);
1476        oat_class->method_headers_[method_offsets_index_].SetVmapTableOffset(0u - offset);
1477      }
1478      ++method_offsets_index_;
1479    }
1480
1481    return true;
1482  }
1483
1484 private:
1485  // Deduplication is already done on a pointer basis by the compiler driver,
1486  // so we can simply compare the pointers to find out if things are duplicated.
1487  SafeMap<const uint8_t*, uint32_t> dedupe_map_;
1488};
1489
1490class OatWriter::InitMethodInfoVisitor : public OatDexMethodVisitor {
1491 public:
1492  InitMethodInfoVisitor(OatWriter* writer, size_t offset) : OatDexMethodVisitor(writer, offset) {}
1493
1494  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it ATTRIBUTE_UNUSED)
1495      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
1496    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
1497    CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
1498
1499    if (HasCompiledCode(compiled_method)) {
1500      DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
1501      DCHECK_EQ(oat_class->method_headers_[method_offsets_index_].GetMethodInfoOffset(), 0u);
1502      ArrayRef<const uint8_t> map = compiled_method->GetMethodInfo();
1503      const uint32_t map_size = map.size() * sizeof(map[0]);
1504      if (map_size != 0u) {
1505        size_t offset = dedupe_map_.GetOrCreate(
1506            map.data(),
1507            [this, map_size]() {
1508              uint32_t new_offset = offset_;
1509              offset_ += map_size;
1510              return new_offset;
1511            });
1512        // Code offset is not initialized yet, so set the map offset to 0u-offset.
1513        DCHECK_EQ(oat_class->method_offsets_[method_offsets_index_].code_offset_, 0u);
1514        oat_class->method_headers_[method_offsets_index_].SetMethodInfoOffset(0u - offset);
1515      }
1516      ++method_offsets_index_;
1517    }
1518
1519    return true;
1520  }
1521
1522 private:
1523  // Deduplication is already done on a pointer basis by the compiler driver,
1524  // so we can simply compare the pointers to find out if things are duplicated.
1525  SafeMap<const uint8_t*, uint32_t> dedupe_map_;
1526};
1527
1528class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor {
1529 public:
1530  InitImageMethodVisitor(OatWriter* writer,
1531                         size_t offset,
1532                         const std::vector<const DexFile*>* dex_files)
1533      : OatDexMethodVisitor(writer, offset),
1534        pointer_size_(GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet())),
1535        class_loader_(writer->HasImage() ? writer->image_writer_->GetClassLoader() : nullptr),
1536        dex_files_(dex_files),
1537        class_linker_(Runtime::Current()->GetClassLinker()) {}
1538
1539  // Handle copied methods here. Copy pointer to quick code from
1540  // an origin method to a copied method only if they are
1541  // in the same oat file. If the origin and the copied methods are
1542  // in different oat files don't touch the copied method.
1543  // References to other oat files are not supported yet.
1544  bool StartClass(const DexFile* dex_file, size_t class_def_index) OVERRIDE
1545      REQUIRES_SHARED(Locks::mutator_lock_) {
1546    OatDexMethodVisitor::StartClass(dex_file, class_def_index);
1547    // Skip classes that are not in the image.
1548    if (!IsImageClass()) {
1549      return true;
1550    }
1551    ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(Thread::Current(), *dex_file);
1552    const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
1553    mirror::Class* klass = dex_cache->GetResolvedType(class_def.class_idx_);
1554    if (klass != nullptr) {
1555      for (ArtMethod& method : klass->GetCopiedMethods(pointer_size_)) {
1556        // Find origin method. Declaring class and dex_method_idx
1557        // in the copied method should be the same as in the origin
1558        // method.
1559        mirror::Class* declaring_class = method.GetDeclaringClass();
1560        ArtMethod* origin = declaring_class->FindClassMethod(
1561            declaring_class->GetDexCache(),
1562            method.GetDexMethodIndex(),
1563            pointer_size_);
1564        CHECK(origin != nullptr);
1565        CHECK(!origin->IsDirect());
1566        CHECK(origin->GetDeclaringClass() == declaring_class);
1567        if (IsInOatFile(&declaring_class->GetDexFile())) {
1568          const void* code_ptr =
1569              origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
1570          if (code_ptr == nullptr) {
1571            methods_to_process_.push_back(std::make_pair(&method, origin));
1572          } else {
1573            method.SetEntryPointFromQuickCompiledCodePtrSize(
1574                code_ptr, pointer_size_);
1575          }
1576        }
1577      }
1578    }
1579    return true;
1580  }
1581
1582  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE
1583      REQUIRES_SHARED(Locks::mutator_lock_) {
1584    // Skip methods that are not in the image.
1585    if (!IsImageClass()) {
1586      return true;
1587    }
1588
1589    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
1590    CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
1591
1592    OatMethodOffsets offsets(0u);
1593    if (HasCompiledCode(compiled_method)) {
1594      DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
1595      offsets = oat_class->method_offsets_[method_offsets_index_];
1596      ++method_offsets_index_;
1597    }
1598
1599    Thread* self = Thread::Current();
1600    ObjPtr<mirror::DexCache> dex_cache = class_linker_->FindDexCache(self, *dex_file_);
1601    ArtMethod* method;
1602    if (writer_->HasBootImage()) {
1603      const InvokeType invoke_type = it.GetMethodInvokeType(
1604          dex_file_->GetClassDef(class_def_index_));
1605      // Unchecked as we hold mutator_lock_ on entry.
1606      ScopedObjectAccessUnchecked soa(self);
1607      StackHandleScope<1> hs(self);
1608      method = class_linker_->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
1609          it.GetMemberIndex(),
1610          hs.NewHandle(dex_cache),
1611          ScopedNullHandle<mirror::ClassLoader>(),
1612          /* referrer */ nullptr,
1613          invoke_type);
1614      if (method == nullptr) {
1615        LOG(FATAL_WITHOUT_ABORT) << "Unexpected failure to resolve a method: "
1616            << dex_file_->PrettyMethod(it.GetMemberIndex(), true);
1617        self->AssertPendingException();
1618        mirror::Throwable* exc = self->GetException();
1619        std::string dump = exc->Dump();
1620        LOG(FATAL) << dump;
1621        UNREACHABLE();
1622      }
1623    } else {
1624      // Should already have been resolved by the compiler.
1625      // It may not be resolved if the class failed to verify, in this case, don't set the
1626      // entrypoint. This is not fatal since we shall use a resolution method.
1627      method = class_linker_->LookupResolvedMethod(it.GetMemberIndex(), dex_cache, class_loader_);
1628    }
1629    if (method != nullptr &&
1630        compiled_method != nullptr &&
1631        compiled_method->GetQuickCode().size() != 0) {
1632      method->SetEntryPointFromQuickCompiledCodePtrSize(
1633          reinterpret_cast<void*>(offsets.code_offset_), pointer_size_);
1634    }
1635
1636    return true;
1637  }
1638
1639  // Check whether current class is image class
1640  bool IsImageClass() {
1641    const DexFile::TypeId& type_id =
1642        dex_file_->GetTypeId(dex_file_->GetClassDef(class_def_index_).class_idx_);
1643    const char* class_descriptor = dex_file_->GetTypeDescriptor(type_id);
1644    return writer_->GetCompilerDriver()->IsImageClass(class_descriptor);
1645  }
1646
1647  // Check whether specified dex file is in the compiled oat file.
1648  bool IsInOatFile(const DexFile* dex_file) {
1649    return ContainsElement(*dex_files_, dex_file);
1650  }
1651
1652  // Assign a pointer to quick code for copied methods
1653  // not handled in the method StartClass
1654  void Postprocess() {
1655    for (std::pair<ArtMethod*, ArtMethod*>& p : methods_to_process_) {
1656      ArtMethod* method = p.first;
1657      ArtMethod* origin = p.second;
1658      const void* code_ptr =
1659          origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
1660      if (code_ptr != nullptr) {
1661        method->SetEntryPointFromQuickCompiledCodePtrSize(code_ptr, pointer_size_);
1662      }
1663    }
1664  }
1665
1666 private:
1667  const PointerSize pointer_size_;
1668  ObjPtr<mirror::ClassLoader> class_loader_;
1669  const std::vector<const DexFile*>* dex_files_;
1670  ClassLinker* const class_linker_;
1671  std::vector<std::pair<ArtMethod*, ArtMethod*>> methods_to_process_;
1672};
1673
1674class OatWriter::WriteCodeMethodVisitor : public OrderedMethodVisitor {
1675 public:
1676  WriteCodeMethodVisitor(OatWriter* writer,
1677                         OutputStream* out,
1678                         const size_t file_offset,
1679                         size_t relative_offset,
1680                         OrderedMethodList ordered_methods)
1681      : OrderedMethodVisitor(std::move(ordered_methods)),
1682        writer_(writer),
1683        offset_(relative_offset),
1684        dex_file_(nullptr),
1685        pointer_size_(GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet())),
1686        class_loader_(writer->HasImage() ? writer->image_writer_->GetClassLoader() : nullptr),
1687        out_(out),
1688        file_offset_(file_offset),
1689        class_linker_(Runtime::Current()->GetClassLinker()),
1690        dex_cache_(nullptr),
1691        no_thread_suspension_("OatWriter patching") {
1692    patched_code_.reserve(16 * KB);
1693    if (writer_->HasBootImage()) {
1694      // If we're creating the image, the address space must be ready so that we can apply patches.
1695      CHECK(writer_->image_writer_->IsImageAddressSpaceReady());
1696    }
1697  }
1698
1699  virtual bool VisitStart() OVERRIDE {
1700    return true;
1701  }
1702
1703  void UpdateDexFileAndDexCache(const DexFile* dex_file)
1704      REQUIRES_SHARED(Locks::mutator_lock_) {
1705    dex_file_ = dex_file;
1706
1707    // Ordered method visiting is only for compiled methods.
1708    DCHECK(writer_->MayHaveCompiledMethods());
1709
1710    if (writer_->GetCompilerDriver()->GetCompilerOptions().IsAotCompilationEnabled()) {
1711      // Only need to set the dex cache if we have compilation. Other modes might have unloaded it.
1712      if (dex_cache_ == nullptr || dex_cache_->GetDexFile() != dex_file) {
1713        dex_cache_ = class_linker_->FindDexCache(Thread::Current(), *dex_file);
1714        DCHECK(dex_cache_ != nullptr);
1715      }
1716    }
1717  }
1718
1719  virtual bool VisitComplete() {
1720    offset_ = writer_->relative_patcher_->WriteThunks(out_, offset_);
1721    if (UNLIKELY(offset_ == 0u)) {
1722      PLOG(ERROR) << "Failed to write final relative call thunks";
1723      return false;
1724    }
1725    return true;
1726  }
1727
1728  virtual bool VisitMethod(const OrderedMethodData& method_data) OVERRIDE
1729      REQUIRES_SHARED(Locks::mutator_lock_) {
1730    const MethodReference& method_ref = method_data.method_reference;
1731    UpdateDexFileAndDexCache(method_ref.dex_file);
1732
1733    OatClass* oat_class = method_data.oat_class;
1734    CompiledMethod* compiled_method = method_data.compiled_method;
1735    uint16_t method_offsets_index = method_data.method_offsets_index;
1736
1737    // No thread suspension since dex_cache_ that may get invalidated if that occurs.
1738    ScopedAssertNoThreadSuspension tsc(__FUNCTION__);
1739    DCHECK(HasCompiledCode(compiled_method)) << method_ref.PrettyMethod();
1740
1741    // TODO: cleanup DCHECK_OFFSET_ to accept file_offset as parameter.
1742    size_t file_offset = file_offset_;  // Used by DCHECK_OFFSET_ macro.
1743    OutputStream* out = out_;
1744
1745    ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode();
1746    uint32_t code_size = quick_code.size() * sizeof(uint8_t);
1747
1748    // Deduplicate code arrays.
1749    const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index];
1750    if (method_offsets.code_offset_ > offset_) {
1751      offset_ = writer_->relative_patcher_->WriteThunks(out, offset_);
1752      if (offset_ == 0u) {
1753        ReportWriteFailure("relative call thunk", method_ref);
1754        return false;
1755      }
1756      uint32_t alignment_size = CodeAlignmentSize(offset_, *compiled_method);
1757      if (alignment_size != 0) {
1758        if (!writer_->WriteCodeAlignment(out, alignment_size)) {
1759          ReportWriteFailure("code alignment padding", method_ref);
1760          return false;
1761        }
1762        offset_ += alignment_size;
1763        DCHECK_OFFSET_();
1764      }
1765      DCHECK_ALIGNED_PARAM(offset_ + sizeof(OatQuickMethodHeader),
1766                           GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
1767      DCHECK_EQ(method_offsets.code_offset_,
1768                offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta())
1769          << dex_file_->PrettyMethod(method_ref.index);
1770      const OatQuickMethodHeader& method_header =
1771          oat_class->method_headers_[method_offsets_index];
1772      if (!out->WriteFully(&method_header, sizeof(method_header))) {
1773        ReportWriteFailure("method header", method_ref);
1774        return false;
1775      }
1776      writer_->size_method_header_ += sizeof(method_header);
1777      offset_ += sizeof(method_header);
1778      DCHECK_OFFSET_();
1779
1780      if (!compiled_method->GetPatches().empty()) {
1781        patched_code_.assign(quick_code.begin(), quick_code.end());
1782        quick_code = ArrayRef<const uint8_t>(patched_code_);
1783        for (const LinkerPatch& patch : compiled_method->GetPatches()) {
1784          uint32_t literal_offset = patch.LiteralOffset();
1785          switch (patch.GetType()) {
1786            case LinkerPatch::Type::kMethodBssEntry: {
1787              uint32_t target_offset =
1788                  writer_->bss_start_ + writer_->bss_method_entries_.Get(patch.TargetMethod());
1789              writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
1790                                                                   patch,
1791                                                                   offset_ + literal_offset,
1792                                                                   target_offset);
1793              break;
1794            }
1795            case LinkerPatch::Type::kCallRelative: {
1796              // NOTE: Relative calls across oat files are not supported.
1797              uint32_t target_offset = GetTargetOffset(patch);
1798              writer_->relative_patcher_->PatchCall(&patched_code_,
1799                                                    literal_offset,
1800                                                    offset_ + literal_offset,
1801                                                    target_offset);
1802              break;
1803            }
1804            case LinkerPatch::Type::kStringRelative: {
1805              uint32_t target_offset = GetTargetObjectOffset(GetTargetString(patch));
1806              writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
1807                                                                   patch,
1808                                                                   offset_ + literal_offset,
1809                                                                   target_offset);
1810              break;
1811            }
1812            case LinkerPatch::Type::kStringInternTable: {
1813              uint32_t target_offset = GetInternTableEntryOffset(patch);
1814              writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
1815                                                                   patch,
1816                                                                   offset_ + literal_offset,
1817                                                                   target_offset);
1818              break;
1819            }
1820            case LinkerPatch::Type::kStringBssEntry: {
1821              StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex());
1822              uint32_t target_offset =
1823                  writer_->bss_start_ + writer_->bss_string_entries_.Get(ref);
1824              writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
1825                                                                   patch,
1826                                                                   offset_ + literal_offset,
1827                                                                   target_offset);
1828              break;
1829            }
1830            case LinkerPatch::Type::kTypeRelative: {
1831              uint32_t target_offset = GetTargetObjectOffset(GetTargetType(patch));
1832              writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
1833                                                                   patch,
1834                                                                   offset_ + literal_offset,
1835                                                                   target_offset);
1836              break;
1837            }
1838            case LinkerPatch::Type::kTypeClassTable: {
1839              uint32_t target_offset = GetClassTableEntryOffset(patch);
1840              writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
1841                                                                   patch,
1842                                                                   offset_ + literal_offset,
1843                                                                   target_offset);
1844              break;
1845            }
1846            case LinkerPatch::Type::kTypeBssEntry: {
1847              TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
1848              uint32_t target_offset = writer_->bss_start_ + writer_->bss_type_entries_.Get(ref);
1849              writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
1850                                                                   patch,
1851                                                                   offset_ + literal_offset,
1852                                                                   target_offset);
1853              break;
1854            }
1855            case LinkerPatch::Type::kCall: {
1856              uint32_t target_offset = GetTargetOffset(patch);
1857              PatchCodeAddress(&patched_code_, literal_offset, target_offset);
1858              break;
1859            }
1860            case LinkerPatch::Type::kMethodRelative: {
1861              uint32_t target_offset = GetTargetMethodOffset(GetTargetMethod(patch));
1862              writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
1863                                                                   patch,
1864                                                                   offset_ + literal_offset,
1865                                                                   target_offset);
1866              break;
1867            }
1868            case LinkerPatch::Type::kBakerReadBarrierBranch: {
1869              writer_->relative_patcher_->PatchBakerReadBarrierBranch(&patched_code_,
1870                                                                      patch,
1871                                                                      offset_ + literal_offset);
1872              break;
1873            }
1874            default: {
1875              DCHECK(false) << "Unexpected linker patch type: " << patch.GetType();
1876              break;
1877            }
1878          }
1879        }
1880      }
1881
1882      if (!out->WriteFully(quick_code.data(), code_size)) {
1883        ReportWriteFailure("method code", method_ref);
1884        return false;
1885      }
1886      writer_->size_code_ += code_size;
1887      offset_ += code_size;
1888    }
1889    DCHECK_OFFSET_();
1890
1891    return true;
1892  }
1893
1894  size_t GetOffset() const {
1895    return offset_;
1896  }
1897
1898 private:
1899  OatWriter* const writer_;
1900
1901  // Updated in VisitMethod as methods are written out.
1902  size_t offset_;
1903
1904  // Potentially varies with every different VisitMethod.
1905  // Used to determine which DexCache to use when finding ArtMethods.
1906  const DexFile* dex_file_;
1907
1908  // Pointer size we are compiling to.
1909  const PointerSize pointer_size_;
1910  // The image writer's classloader, if there is one, else null.
1911  ObjPtr<mirror::ClassLoader> class_loader_;
1912  // Stream to output file, where the OAT code will be written to.
1913  OutputStream* const out_;
1914  const size_t file_offset_;
1915  ClassLinker* const class_linker_;
1916  ObjPtr<mirror::DexCache> dex_cache_;
1917  std::vector<uint8_t> patched_code_;
1918  const ScopedAssertNoThreadSuspension no_thread_suspension_;
1919
1920  void ReportWriteFailure(const char* what, const MethodReference& method_ref) {
1921    PLOG(ERROR) << "Failed to write " << what << " for "
1922        << method_ref.PrettyMethod() << " to " << out_->GetLocation();
1923  }
1924
1925  ArtMethod* GetTargetMethod(const LinkerPatch& patch)
1926      REQUIRES_SHARED(Locks::mutator_lock_) {
1927    MethodReference ref = patch.TargetMethod();
1928    ObjPtr<mirror::DexCache> dex_cache =
1929        (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache(
1930            Thread::Current(), *ref.dex_file);
1931    ArtMethod* method =
1932        class_linker_->LookupResolvedMethod(ref.index, dex_cache, class_loader_);
1933    CHECK(method != nullptr);
1934    return method;
1935  }
1936
1937  uint32_t GetTargetOffset(const LinkerPatch& patch) REQUIRES_SHARED(Locks::mutator_lock_) {
1938    uint32_t target_offset = writer_->relative_patcher_->GetOffset(patch.TargetMethod());
1939    // If there's no new compiled code, either we're compiling an app and the target method
1940    // is in the boot image, or we need to point to the correct trampoline.
1941    if (UNLIKELY(target_offset == 0)) {
1942      ArtMethod* target = GetTargetMethod(patch);
1943      DCHECK(target != nullptr);
1944      const void* oat_code_offset =
1945          target->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
1946      if (oat_code_offset != 0) {
1947        DCHECK(!writer_->HasBootImage());
1948        DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickResolutionStub(oat_code_offset));
1949        DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(oat_code_offset));
1950        DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickGenericJniStub(oat_code_offset));
1951        target_offset = PointerToLowMemUInt32(oat_code_offset);
1952      } else {
1953        target_offset = target->IsNative()
1954            ? writer_->oat_header_->GetQuickGenericJniTrampolineOffset()
1955            : writer_->oat_header_->GetQuickToInterpreterBridgeOffset();
1956      }
1957    }
1958    return target_offset;
1959  }
1960
1961  ObjPtr<mirror::DexCache> GetDexCache(const DexFile* target_dex_file)
1962      REQUIRES_SHARED(Locks::mutator_lock_) {
1963    return (target_dex_file == dex_file_)
1964        ? dex_cache_
1965        : class_linker_->FindDexCache(Thread::Current(), *target_dex_file);
1966  }
1967
1968  ObjPtr<mirror::Class> GetTargetType(const LinkerPatch& patch)
1969      REQUIRES_SHARED(Locks::mutator_lock_) {
1970    DCHECK(writer_->HasImage());
1971    ObjPtr<mirror::DexCache> dex_cache = GetDexCache(patch.TargetTypeDexFile());
1972    ObjPtr<mirror::Class> type =
1973        class_linker_->LookupResolvedType(patch.TargetTypeIndex(), dex_cache, class_loader_);
1974    CHECK(type != nullptr);
1975    return type;
1976  }
1977
1978  ObjPtr<mirror::String> GetTargetString(const LinkerPatch& patch)
1979      REQUIRES_SHARED(Locks::mutator_lock_) {
1980    ClassLinker* linker = Runtime::Current()->GetClassLinker();
1981    ObjPtr<mirror::String> string =
1982        linker->LookupString(patch.TargetStringIndex(), GetDexCache(patch.TargetStringDexFile()));
1983    DCHECK(string != nullptr);
1984    DCHECK(writer_->HasBootImage() ||
1985           Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(string));
1986    return string;
1987  }
1988
1989  uint32_t GetTargetMethodOffset(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
1990    DCHECK(writer_->HasBootImage());
1991    method = writer_->image_writer_->GetImageMethodAddress(method);
1992    size_t oat_index = writer_->image_writer_->GetOatIndexForDexFile(dex_file_);
1993    uintptr_t oat_data_begin = writer_->image_writer_->GetOatDataBegin(oat_index);
1994    // TODO: Clean up offset types. The target offset must be treated as signed.
1995    return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(method) - oat_data_begin);
1996  }
1997
1998  uint32_t GetTargetObjectOffset(ObjPtr<mirror::Object> object)
1999      REQUIRES_SHARED(Locks::mutator_lock_) {
2000    DCHECK(writer_->HasBootImage());
2001    object = writer_->image_writer_->GetImageAddress(object.Ptr());
2002    size_t oat_index = writer_->image_writer_->GetOatIndexForDexFile(dex_file_);
2003    uintptr_t oat_data_begin = writer_->image_writer_->GetOatDataBegin(oat_index);
2004    // TODO: Clean up offset types. The target offset must be treated as signed.
2005    return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object.Ptr()) - oat_data_begin);
2006  }
2007
2008  void PatchObjectAddress(std::vector<uint8_t>* code, uint32_t offset, mirror::Object* object)
2009      REQUIRES_SHARED(Locks::mutator_lock_) {
2010    if (writer_->HasBootImage()) {
2011      object = writer_->image_writer_->GetImageAddress(object);
2012    } else {
2013      // NOTE: We're using linker patches for app->boot references when the image can
2014      // be relocated and therefore we need to emit .oat_patches. We're not using this
2015      // for app->app references, so check that the object is in the image space.
2016      DCHECK(Runtime::Current()->GetHeap()->FindSpaceFromObject(object, false)->IsImageSpace());
2017    }
2018    // Note: We only patch targeting Objects in image which is in the low 4gb.
2019    uint32_t address = PointerToLowMemUInt32(object);
2020    DCHECK_LE(offset + 4, code->size());
2021    uint8_t* data = &(*code)[offset];
2022    data[0] = address & 0xffu;
2023    data[1] = (address >> 8) & 0xffu;
2024    data[2] = (address >> 16) & 0xffu;
2025    data[3] = (address >> 24) & 0xffu;
2026  }
2027
2028  void PatchCodeAddress(std::vector<uint8_t>* code, uint32_t offset, uint32_t target_offset)
2029      REQUIRES_SHARED(Locks::mutator_lock_) {
2030    uint32_t address = target_offset;
2031    if (writer_->HasBootImage()) {
2032      size_t oat_index = writer_->image_writer_->GetOatIndexForDexCache(dex_cache_);
2033      // TODO: Clean up offset types.
2034      // The target_offset must be treated as signed for cross-oat patching.
2035      const void* target = reinterpret_cast<const void*>(
2036          writer_->image_writer_->GetOatDataBegin(oat_index) +
2037          static_cast<int32_t>(target_offset));
2038      address = PointerToLowMemUInt32(target);
2039    }
2040    DCHECK_LE(offset + 4, code->size());
2041    uint8_t* data = &(*code)[offset];
2042    data[0] = address & 0xffu;
2043    data[1] = (address >> 8) & 0xffu;
2044    data[2] = (address >> 16) & 0xffu;
2045    data[3] = (address >> 24) & 0xffu;
2046  }
2047
2048  // Calculate the offset of the InternTable slot (GcRoot<String>) when mmapped to the .bss.
2049  uint32_t GetInternTableEntryOffset(const LinkerPatch& patch)
2050      REQUIRES_SHARED(Locks::mutator_lock_) {
2051    DCHECK(!writer_->HasBootImage());
2052    const uint8_t* string_root = writer_->LookupBootImageInternTableSlot(
2053        *patch.TargetStringDexFile(), patch.TargetStringIndex());
2054    DCHECK(string_root != nullptr);
2055    return GetBootImageTableEntryOffset(string_root);
2056  }
2057
2058  // Calculate the offset of the ClassTable::TableSlot when mmapped to the .bss.
2059  uint32_t GetClassTableEntryOffset(const LinkerPatch& patch)
2060      REQUIRES_SHARED(Locks::mutator_lock_) {
2061    DCHECK(!writer_->HasBootImage());
2062    const uint8_t* table_slot =
2063        writer_->LookupBootImageClassTableSlot(*patch.TargetTypeDexFile(), patch.TargetTypeIndex());
2064    DCHECK(table_slot != nullptr);
2065    return GetBootImageTableEntryOffset(table_slot);
2066  }
2067
2068  uint32_t GetBootImageTableEntryOffset(const uint8_t* raw_root) {
2069    uint32_t base_offset = writer_->bss_start_;
2070    for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
2071      const uint8_t* const_tables_begin =
2072          space->Begin() + space->GetImageHeader().GetBootImageConstantTablesOffset();
2073      size_t offset = static_cast<size_t>(raw_root - const_tables_begin);
2074      if (offset < space->GetImageHeader().GetBootImageConstantTablesSize()) {
2075        DCHECK_LE(base_offset + offset, writer_->bss_start_ + writer_->bss_methods_offset_);
2076        return base_offset + offset;
2077      }
2078      base_offset += space->GetImageHeader().GetBootImageConstantTablesSize();
2079    }
2080    LOG(FATAL) << "Didn't find boot image string in boot image intern tables!";
2081    UNREACHABLE();
2082  }
2083};
2084
2085class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor {
2086 public:
2087  WriteMapMethodVisitor(OatWriter* writer,
2088                        OutputStream* out,
2089                        const size_t file_offset,
2090                        size_t relative_offset)
2091      : OatDexMethodVisitor(writer, relative_offset),
2092        out_(out),
2093        file_offset_(file_offset) {}
2094
2095  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE {
2096    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
2097    const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
2098
2099    if (HasCompiledCode(compiled_method)) {
2100      size_t file_offset = file_offset_;
2101      OutputStream* out = out_;
2102
2103      uint32_t map_offset = oat_class->method_headers_[method_offsets_index_].GetVmapTableOffset();
2104      uint32_t code_offset = oat_class->method_offsets_[method_offsets_index_].code_offset_;
2105      ++method_offsets_index_;
2106
2107      DCHECK((compiled_method->GetVmapTable().size() == 0u && map_offset == 0u) ||
2108             (compiled_method->GetVmapTable().size() != 0u && map_offset != 0u))
2109          << compiled_method->GetVmapTable().size() << " " << map_offset << " "
2110          << dex_file_->PrettyMethod(it.GetMemberIndex());
2111
2112      // If vdex is enabled, only emit the map for compiled code. The quickening info
2113      // is emitted in the vdex already.
2114      if (map_offset != 0u) {
2115        // Transform map_offset to actual oat data offset.
2116        map_offset = (code_offset - compiled_method->CodeDelta()) - map_offset;
2117        DCHECK_NE(map_offset, 0u);
2118        DCHECK_LE(map_offset, offset_) << dex_file_->PrettyMethod(it.GetMemberIndex());
2119
2120        ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
2121        size_t map_size = map.size() * sizeof(map[0]);
2122        if (map_offset == offset_) {
2123          // Write deduplicated map (code info for Optimizing or transformation info for dex2dex).
2124          if (UNLIKELY(!out->WriteFully(map.data(), map_size))) {
2125            ReportWriteFailure(it);
2126            return false;
2127          }
2128          offset_ += map_size;
2129        }
2130      }
2131      DCHECK_OFFSET_();
2132    }
2133
2134    return true;
2135  }
2136
2137 private:
2138  OutputStream* const out_;
2139  size_t const file_offset_;
2140
2141  void ReportWriteFailure(const ClassDataItemIterator& it) {
2142    PLOG(ERROR) << "Failed to write map for "
2143        << dex_file_->PrettyMethod(it.GetMemberIndex()) << " to " << out_->GetLocation();
2144  }
2145};
2146
2147class OatWriter::WriteMethodInfoVisitor : public OatDexMethodVisitor {
2148 public:
2149  WriteMethodInfoVisitor(OatWriter* writer,
2150                         OutputStream* out,
2151                         const size_t file_offset,
2152                         size_t relative_offset)
2153      : OatDexMethodVisitor(writer, relative_offset),
2154        out_(out),
2155        file_offset_(file_offset) {}
2156
2157  bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) OVERRIDE {
2158    OatClass* oat_class = &writer_->oat_classes_[oat_class_index_];
2159    const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
2160
2161    if (HasCompiledCode(compiled_method)) {
2162      size_t file_offset = file_offset_;
2163      OutputStream* out = out_;
2164      uint32_t map_offset = oat_class->method_headers_[method_offsets_index_].GetMethodInfoOffset();
2165      uint32_t code_offset = oat_class->method_offsets_[method_offsets_index_].code_offset_;
2166      ++method_offsets_index_;
2167      DCHECK((compiled_method->GetMethodInfo().size() == 0u && map_offset == 0u) ||
2168             (compiled_method->GetMethodInfo().size() != 0u && map_offset != 0u))
2169          << compiled_method->GetMethodInfo().size() << " " << map_offset << " "
2170          << dex_file_->PrettyMethod(it.GetMemberIndex());
2171      if (map_offset != 0u) {
2172        // Transform map_offset to actual oat data offset.
2173        map_offset = (code_offset - compiled_method->CodeDelta()) - map_offset;
2174        DCHECK_NE(map_offset, 0u);
2175        DCHECK_LE(map_offset, offset_) << dex_file_->PrettyMethod(it.GetMemberIndex());
2176
2177        ArrayRef<const uint8_t> map = compiled_method->GetMethodInfo();
2178        size_t map_size = map.size() * sizeof(map[0]);
2179        if (map_offset == offset_) {
2180          // Write deduplicated map (code info for Optimizing or transformation info for dex2dex).
2181          if (UNLIKELY(!out->WriteFully(map.data(), map_size))) {
2182            ReportWriteFailure(it);
2183            return false;
2184          }
2185          offset_ += map_size;
2186        }
2187      }
2188      DCHECK_OFFSET_();
2189    }
2190
2191    return true;
2192  }
2193
2194 private:
2195  OutputStream* const out_;
2196  size_t const file_offset_;
2197
2198  void ReportWriteFailure(const ClassDataItemIterator& it) {
2199    PLOG(ERROR) << "Failed to write map for "
2200        << dex_file_->PrettyMethod(it.GetMemberIndex()) << " to " << out_->GetLocation();
2201  }
2202};
2203
2204// Visit all methods from all classes in all dex files with the specified visitor.
2205bool OatWriter::VisitDexMethods(DexMethodVisitor* visitor) {
2206  for (const DexFile* dex_file : *dex_files_) {
2207    const size_t class_def_count = dex_file->NumClassDefs();
2208    for (size_t class_def_index = 0; class_def_index != class_def_count; ++class_def_index) {
2209      if (UNLIKELY(!visitor->StartClass(dex_file, class_def_index))) {
2210        return false;
2211      }
2212      if (MayHaveCompiledMethods()) {
2213        const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
2214        const uint8_t* class_data = dex_file->GetClassData(class_def);
2215        if (class_data != nullptr) {  // ie not an empty class, such as a marker interface
2216          ClassDataItemIterator it(*dex_file, class_data);
2217          it.SkipAllFields();
2218          size_t class_def_method_index = 0u;
2219          while (it.HasNextMethod()) {
2220            if (!visitor->VisitMethod(class_def_method_index, it)) {
2221              return false;
2222            }
2223            ++class_def_method_index;
2224            it.Next();
2225          }
2226          DCHECK(!it.HasNext());
2227        }
2228      }
2229      if (UNLIKELY(!visitor->EndClass())) {
2230        return false;
2231      }
2232    }
2233  }
2234  return true;
2235}
2236
2237size_t OatWriter::InitOatHeader(InstructionSet instruction_set,
2238                                const InstructionSetFeatures* instruction_set_features,
2239                                uint32_t num_dex_files,
2240                                SafeMap<std::string, std::string>* key_value_store) {
2241  TimingLogger::ScopedTiming split("InitOatHeader", timings_);
2242  oat_header_.reset(OatHeader::Create(instruction_set,
2243                                      instruction_set_features,
2244                                      num_dex_files,
2245                                      key_value_store));
2246  size_oat_header_ += sizeof(OatHeader);
2247  size_oat_header_key_value_store_ += oat_header_->GetHeaderSize() - sizeof(OatHeader);
2248  return oat_header_->GetHeaderSize();
2249}
2250
2251size_t OatWriter::InitClassOffsets(size_t offset) {
2252  // Reserve space for class offsets in OAT and update class_offsets_offset_.
2253  for (OatDexFile& oat_dex_file : oat_dex_files_) {
2254    DCHECK_EQ(oat_dex_file.class_offsets_offset_, 0u);
2255    if (!oat_dex_file.class_offsets_.empty()) {
2256      // Class offsets are required to be 4 byte aligned.
2257      offset = RoundUp(offset, 4u);
2258      oat_dex_file.class_offsets_offset_ = offset;
2259      offset += oat_dex_file.GetClassOffsetsRawSize();
2260      DCHECK_ALIGNED(offset, 4u);
2261    }
2262  }
2263  return offset;
2264}
2265
2266size_t OatWriter::InitOatClasses(size_t offset) {
2267  // calculate the offsets within OatDexFiles to OatClasses
2268  InitOatClassesMethodVisitor visitor(this, offset);
2269  bool success = VisitDexMethods(&visitor);
2270  CHECK(success);
2271  offset = visitor.GetOffset();
2272
2273  // Update oat_dex_files_.
2274  auto oat_class_it = oat_class_headers_.begin();
2275  for (OatDexFile& oat_dex_file : oat_dex_files_) {
2276    for (uint32_t& class_offset : oat_dex_file.class_offsets_) {
2277      DCHECK(oat_class_it != oat_class_headers_.end());
2278      class_offset = oat_class_it->offset_;
2279      ++oat_class_it;
2280    }
2281  }
2282  CHECK(oat_class_it == oat_class_headers_.end());
2283
2284  return offset;
2285}
2286
2287size_t OatWriter::InitOatMaps(size_t offset) {
2288  if (!MayHaveCompiledMethods()) {
2289    return offset;
2290  }
2291  {
2292    InitMapMethodVisitor visitor(this, offset);
2293    bool success = VisitDexMethods(&visitor);
2294    DCHECK(success);
2295    offset = visitor.GetOffset();
2296  }
2297  {
2298    InitMethodInfoVisitor visitor(this, offset);
2299    bool success = VisitDexMethods(&visitor);
2300    DCHECK(success);
2301    offset = visitor.GetOffset();
2302  }
2303  return offset;
2304}
2305
2306template <typename GetBssOffset>
2307static size_t CalculateNumberOfIndexBssMappingEntries(size_t number_of_indexes,
2308                                                      size_t slot_size,
2309                                                      const BitVector& indexes,
2310                                                      GetBssOffset get_bss_offset) {
2311  IndexBssMappingEncoder encoder(number_of_indexes, slot_size);
2312  size_t number_of_entries = 0u;
2313  bool first_index = true;
2314  for (uint32_t index : indexes.Indexes()) {
2315    uint32_t bss_offset = get_bss_offset(index);
2316    if (first_index || !encoder.TryMerge(index, bss_offset)) {
2317      encoder.Reset(index, bss_offset);
2318      ++number_of_entries;
2319      first_index = false;
2320    }
2321  }
2322  DCHECK_NE(number_of_entries, 0u);
2323  return number_of_entries;
2324}
2325
2326template <typename GetBssOffset>
2327static size_t CalculateIndexBssMappingSize(size_t number_of_indexes,
2328                                           size_t slot_size,
2329                                           const BitVector& indexes,
2330                                           GetBssOffset get_bss_offset) {
2331  size_t number_of_entries = CalculateNumberOfIndexBssMappingEntries(number_of_indexes,
2332                                                                     slot_size,
2333                                                                     indexes,
2334                                                                     get_bss_offset);
2335  return IndexBssMapping::ComputeSize(number_of_entries);
2336}
2337
2338size_t OatWriter::InitIndexBssMappings(size_t offset) {
2339  if (bss_method_entry_references_.empty() &&
2340      bss_type_entry_references_.empty() &&
2341      bss_string_entry_references_.empty()) {
2342    return offset;
2343  }
2344  // If there are any classes, the class offsets allocation aligns the offset
2345  // and we cannot have any index bss mappings without class offsets.
2346  static_assert(alignof(IndexBssMapping) == 4u, "IndexBssMapping alignment check.");
2347  DCHECK_ALIGNED(offset, 4u);
2348
2349  size_t number_of_method_dex_files = 0u;
2350  size_t number_of_type_dex_files = 0u;
2351  size_t number_of_string_dex_files = 0u;
2352  PointerSize pointer_size = GetInstructionSetPointerSize(oat_header_->GetInstructionSet());
2353  for (size_t i = 0, size = dex_files_->size(); i != size; ++i) {
2354    const DexFile* dex_file = (*dex_files_)[i];
2355    auto method_it = bss_method_entry_references_.find(dex_file);
2356    if (method_it != bss_method_entry_references_.end()) {
2357      const BitVector& method_indexes = method_it->second;
2358      ++number_of_method_dex_files;
2359      oat_dex_files_[i].method_bss_mapping_offset_ = offset;
2360      offset += CalculateIndexBssMappingSize(
2361          dex_file->NumMethodIds(),
2362          static_cast<size_t>(pointer_size),
2363          method_indexes,
2364          [=](uint32_t index) {
2365            return bss_method_entries_.Get({dex_file, index});
2366          });
2367    }
2368
2369    auto type_it = bss_type_entry_references_.find(dex_file);
2370    if (type_it != bss_type_entry_references_.end()) {
2371      const BitVector& type_indexes = type_it->second;
2372      ++number_of_type_dex_files;
2373      oat_dex_files_[i].type_bss_mapping_offset_ = offset;
2374      offset += CalculateIndexBssMappingSize(
2375          dex_file->NumTypeIds(),
2376          sizeof(GcRoot<mirror::Class>),
2377          type_indexes,
2378          [=](uint32_t index) {
2379            return bss_type_entries_.Get({dex_file, dex::TypeIndex(index)});
2380          });
2381    }
2382
2383    auto string_it = bss_string_entry_references_.find(dex_file);
2384    if (string_it != bss_string_entry_references_.end()) {
2385      const BitVector& string_indexes = string_it->second;
2386      ++number_of_string_dex_files;
2387      oat_dex_files_[i].string_bss_mapping_offset_ = offset;
2388      offset += CalculateIndexBssMappingSize(
2389          dex_file->NumStringIds(),
2390          sizeof(GcRoot<mirror::String>),
2391          string_indexes,
2392          [=](uint32_t index) {
2393            return bss_string_entries_.Get({dex_file, dex::StringIndex(index)});
2394          });
2395    }
2396  }
2397  // Check that all dex files targeted by bss entries are in `*dex_files_`.
2398  CHECK_EQ(number_of_method_dex_files, bss_method_entry_references_.size());
2399  CHECK_EQ(number_of_type_dex_files, bss_type_entry_references_.size());
2400  CHECK_EQ(number_of_string_dex_files, bss_string_entry_references_.size());
2401  return offset;
2402}
2403
2404size_t OatWriter::InitOatDexFiles(size_t offset) {
2405  // Initialize offsets of oat dex files.
2406  for (OatDexFile& oat_dex_file : oat_dex_files_) {
2407    oat_dex_file.offset_ = offset;
2408    offset += oat_dex_file.SizeOf();
2409  }
2410  return offset;
2411}
2412
2413size_t OatWriter::InitOatCode(size_t offset) {
2414  // calculate the offsets within OatHeader to executable code
2415  size_t old_offset = offset;
2416  // required to be on a new page boundary
2417  offset = RoundUp(offset, kPageSize);
2418  oat_header_->SetExecutableOffset(offset);
2419  size_executable_offset_alignment_ = offset - old_offset;
2420  // TODO: Remove unused trampoline offsets from the OatHeader (requires oat version change).
2421  oat_header_->SetInterpreterToInterpreterBridgeOffset(0);
2422  oat_header_->SetInterpreterToCompiledCodeBridgeOffset(0);
2423  if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
2424    InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
2425    const bool generate_debug_info = compiler_driver_->GetCompilerOptions().GenerateAnyDebugInfo();
2426    size_t adjusted_offset = offset;
2427
2428    #define DO_TRAMPOLINE(field, fn_name)                                   \
2429      offset = CompiledCode::AlignCode(offset, instruction_set);            \
2430      adjusted_offset = offset + CompiledCode::CodeDelta(instruction_set);  \
2431      oat_header_->Set ## fn_name ## Offset(adjusted_offset);               \
2432      (field) = compiler_driver_->Create ## fn_name();                      \
2433      if (generate_debug_info) {                                            \
2434        debug::MethodDebugInfo info = {};                                   \
2435        info.custom_name = #fn_name;                                        \
2436        info.isa = instruction_set;                                         \
2437        info.is_code_address_text_relative = true;                          \
2438        /* Use the code offset rather than the `adjusted_offset`. */        \
2439        info.code_address = offset - oat_header_->GetExecutableOffset();    \
2440        info.code_size = (field)->size();                                   \
2441        method_info_.push_back(std::move(info));                            \
2442      }                                                                     \
2443      offset += (field)->size();
2444
2445    DO_TRAMPOLINE(jni_dlsym_lookup_, JniDlsymLookup);
2446    DO_TRAMPOLINE(quick_generic_jni_trampoline_, QuickGenericJniTrampoline);
2447    DO_TRAMPOLINE(quick_imt_conflict_trampoline_, QuickImtConflictTrampoline);
2448    DO_TRAMPOLINE(quick_resolution_trampoline_, QuickResolutionTrampoline);
2449    DO_TRAMPOLINE(quick_to_interpreter_bridge_, QuickToInterpreterBridge);
2450
2451    #undef DO_TRAMPOLINE
2452  } else {
2453    oat_header_->SetJniDlsymLookupOffset(0);
2454    oat_header_->SetQuickGenericJniTrampolineOffset(0);
2455    oat_header_->SetQuickImtConflictTrampolineOffset(0);
2456    oat_header_->SetQuickResolutionTrampolineOffset(0);
2457    oat_header_->SetQuickToInterpreterBridgeOffset(0);
2458  }
2459  return offset;
2460}
2461
2462size_t OatWriter::InitOatCodeDexFiles(size_t offset) {
2463  if (!compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) {
2464    if (kOatWriterDebugOatCodeLayout) {
2465      LOG(INFO) << "InitOatCodeDexFiles: OatWriter("
2466                << this << "), "
2467                << "compilation is disabled";
2468    }
2469
2470    return offset;
2471  }
2472  bool success = false;
2473
2474  {
2475    ScopedObjectAccess soa(Thread::Current());
2476
2477    LayoutCodeMethodVisitor layout_code_visitor(this, offset);
2478    success = VisitDexMethods(&layout_code_visitor);
2479    DCHECK(success);
2480
2481    LayoutReserveOffsetCodeMethodVisitor layout_reserve_code_visitor(
2482        this,
2483        offset,
2484        layout_code_visitor.ReleaseOrderedMethods());
2485    success = layout_reserve_code_visitor.Visit();
2486    DCHECK(success);
2487    offset = layout_reserve_code_visitor.GetOffset();
2488
2489    // Save the method order because the WriteCodeMethodVisitor will need this
2490    // order again.
2491    DCHECK(ordered_methods_ == nullptr);
2492    ordered_methods_.reset(
2493        new OrderedMethodList(
2494            layout_reserve_code_visitor.ReleaseOrderedMethods()));
2495
2496    if (kOatWriterDebugOatCodeLayout) {
2497      LOG(INFO) << "IniatOatCodeDexFiles: method order: ";
2498      for (const OrderedMethodData& ordered_method : *ordered_methods_) {
2499        std::string pretty_name = ordered_method.method_reference.PrettyMethod();
2500        LOG(INFO) << pretty_name
2501                  << "@ offset "
2502                  << relative_patcher_->GetOffset(ordered_method.method_reference)
2503                  << " X hotness "
2504                  << reinterpret_cast<void*>(ordered_method.method_hotness.GetFlags());
2505      }
2506    }
2507  }
2508
2509  if (HasImage()) {
2510    InitImageMethodVisitor image_visitor(this, offset, dex_files_);
2511    success = VisitDexMethods(&image_visitor);
2512    image_visitor.Postprocess();
2513    DCHECK(success);
2514    offset = image_visitor.GetOffset();
2515  }
2516
2517  return offset;
2518}
2519
2520void OatWriter::InitBssLayout(InstructionSet instruction_set) {
2521  {
2522    InitBssLayoutMethodVisitor visitor(this);
2523    bool success = VisitDexMethods(&visitor);
2524    DCHECK(success);
2525  }
2526
2527  DCHECK_EQ(bss_size_, 0u);
2528  if (HasBootImage()) {
2529    DCHECK(!map_boot_image_tables_to_bss_);
2530    DCHECK(bss_string_entries_.empty());
2531  }
2532  if (!map_boot_image_tables_to_bss_ &&
2533      bss_method_entries_.empty() &&
2534      bss_type_entries_.empty() &&
2535      bss_string_entries_.empty()) {
2536    // Nothing to put to the .bss section.
2537    return;
2538  }
2539
2540  // Allocate space for boot image tables in the .bss section.
2541  PointerSize pointer_size = GetInstructionSetPointerSize(instruction_set);
2542  if (map_boot_image_tables_to_bss_) {
2543    for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
2544      bss_size_ += space->GetImageHeader().GetBootImageConstantTablesSize();
2545    }
2546  }
2547
2548  bss_methods_offset_ = bss_size_;
2549
2550  // Prepare offsets for .bss ArtMethod entries.
2551  for (auto& entry : bss_method_entries_) {
2552    DCHECK_EQ(entry.second, 0u);
2553    entry.second = bss_size_;
2554    bss_size_ += static_cast<size_t>(pointer_size);
2555  }
2556
2557  bss_roots_offset_ = bss_size_;
2558
2559  // Prepare offsets for .bss Class entries.
2560  for (auto& entry : bss_type_entries_) {
2561    DCHECK_EQ(entry.second, 0u);
2562    entry.second = bss_size_;
2563    bss_size_ += sizeof(GcRoot<mirror::Class>);
2564  }
2565  // Prepare offsets for .bss String entries.
2566  for (auto& entry : bss_string_entries_) {
2567    DCHECK_EQ(entry.second, 0u);
2568    entry.second = bss_size_;
2569    bss_size_ += sizeof(GcRoot<mirror::String>);
2570  }
2571}
2572
2573bool OatWriter::WriteRodata(OutputStream* out) {
2574  CHECK(write_state_ == WriteState::kWriteRoData);
2575
2576  size_t file_offset = oat_data_offset_;
2577  off_t current_offset = out->Seek(0, kSeekCurrent);
2578  if (current_offset == static_cast<off_t>(-1)) {
2579    PLOG(ERROR) << "Failed to retrieve current position in " << out->GetLocation();
2580  }
2581  DCHECK_GE(static_cast<size_t>(current_offset), file_offset + oat_header_->GetHeaderSize());
2582  size_t relative_offset = current_offset - file_offset;
2583
2584  // Wrap out to update checksum with each write.
2585  ChecksumUpdatingOutputStream checksum_updating_out(out, oat_header_.get());
2586  out = &checksum_updating_out;
2587
2588  relative_offset = WriteClassOffsets(out, file_offset, relative_offset);
2589  if (relative_offset == 0) {
2590    PLOG(ERROR) << "Failed to write class offsets to " << out->GetLocation();
2591    return false;
2592  }
2593
2594  relative_offset = WriteClasses(out, file_offset, relative_offset);
2595  if (relative_offset == 0) {
2596    PLOG(ERROR) << "Failed to write classes to " << out->GetLocation();
2597    return false;
2598  }
2599
2600  relative_offset = WriteIndexBssMappings(out, file_offset, relative_offset);
2601  if (relative_offset == 0) {
2602    PLOG(ERROR) << "Failed to write method bss mappings to " << out->GetLocation();
2603    return false;
2604  }
2605
2606  relative_offset = WriteMaps(out, file_offset, relative_offset);
2607  if (relative_offset == 0) {
2608    PLOG(ERROR) << "Failed to write oat code to " << out->GetLocation();
2609    return false;
2610  }
2611
2612  relative_offset = WriteOatDexFiles(out, file_offset, relative_offset);
2613  if (relative_offset == 0) {
2614    PLOG(ERROR) << "Failed to write oat dex information to " << out->GetLocation();
2615    return false;
2616  }
2617
2618  // Write padding.
2619  off_t new_offset = out->Seek(size_executable_offset_alignment_, kSeekCurrent);
2620  relative_offset += size_executable_offset_alignment_;
2621  DCHECK_EQ(relative_offset, oat_header_->GetExecutableOffset());
2622  size_t expected_file_offset = file_offset + relative_offset;
2623  if (static_cast<uint32_t>(new_offset) != expected_file_offset) {
2624    PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset
2625                << " Expected: " << expected_file_offset << " File: " << out->GetLocation();
2626    return 0;
2627  }
2628  DCHECK_OFFSET();
2629
2630  write_state_ = WriteState::kWriteText;
2631  return true;
2632}
2633
2634class OatWriter::WriteQuickeningInfoMethodVisitor {
2635 public:
2636  WriteQuickeningInfoMethodVisitor(OatWriter* writer, OutputStream* out)
2637      : writer_(writer),
2638        out_(out) {}
2639
2640  bool VisitDexMethods(const std::vector<const DexFile*>& dex_files) {
2641    // Map of offsets for quicken info related to method indices.
2642    SafeMap<const uint8_t*, uint32_t> offset_map;
2643    // Use method index order to minimize the encoded size of the offset table.
2644    for (const DexFile* dex_file : dex_files) {
2645      std::vector<uint32_t>* const offsets =
2646          &quicken_info_offset_indices_.Put(dex_file, std::vector<uint32_t>())->second;
2647      for (uint32_t method_idx = 0; method_idx < dex_file->NumMethodIds(); ++method_idx) {
2648        uint32_t offset = 0u;
2649        MethodReference method_ref(dex_file, method_idx);
2650        CompiledMethod* compiled_method = writer_->compiler_driver_->GetCompiledMethod(method_ref);
2651        if (compiled_method != nullptr && HasQuickeningInfo(compiled_method)) {
2652          ArrayRef<const uint8_t> map = compiled_method->GetVmapTable();
2653
2654          // Record each index if required. written_bytes_ is the offset from the start of the
2655          // quicken info data.
2656          // May be already inserted for deduplicate items.
2657          // Add offset of one to make sure 0 represents unused.
2658          auto pair = offset_map.emplace(map.data(), written_bytes_ + 1);
2659          offset = pair.first->second;
2660          // Write out the map if it's not already written.
2661          if (pair.second) {
2662            const uint32_t length = map.size() * sizeof(map.front());
2663            if (!out_->WriteFully(map.data(), length)) {
2664              PLOG(ERROR) << "Failed to write quickening info for " << method_ref.PrettyMethod()
2665                          << " to " << out_->GetLocation();
2666              return false;
2667            }
2668            written_bytes_ += length;
2669          }
2670        }
2671        offsets->push_back(offset);
2672      }
2673    }
2674    return true;
2675  }
2676
2677  size_t GetNumberOfWrittenBytes() const {
2678    return written_bytes_;
2679  }
2680
2681  SafeMap<const DexFile*, std::vector<uint32_t>>& GetQuickenInfoOffsetIndicies() {
2682    return quicken_info_offset_indices_;
2683  }
2684
2685 private:
2686  OatWriter* const writer_;
2687  OutputStream* const out_;
2688  size_t written_bytes_ = 0u;
2689  SafeMap<const DexFile*, std::vector<uint32_t>> quicken_info_offset_indices_;
2690};
2691
2692class OatWriter::WriteQuickeningInfoOffsetsMethodVisitor {
2693 public:
2694  WriteQuickeningInfoOffsetsMethodVisitor(
2695      OutputStream* out,
2696      uint32_t start_offset,
2697      SafeMap<const DexFile*, std::vector<uint32_t>>* quicken_info_offset_indices,
2698      std::vector<uint32_t>* out_table_offsets)
2699      : out_(out),
2700        start_offset_(start_offset),
2701        quicken_info_offset_indices_(quicken_info_offset_indices),
2702        out_table_offsets_(out_table_offsets) {}
2703
2704  bool VisitDexMethods(const std::vector<const DexFile*>& dex_files) {
2705    for (const DexFile* dex_file : dex_files) {
2706      auto it = quicken_info_offset_indices_->find(dex_file);
2707      DCHECK(it != quicken_info_offset_indices_->end()) << "Failed to find dex file "
2708                                                        << dex_file->GetLocation();
2709      const std::vector<uint32_t>* const offsets = &it->second;
2710
2711      const uint32_t current_offset = start_offset_ + written_bytes_;
2712      CHECK_ALIGNED_PARAM(current_offset, CompactOffsetTable::kAlignment);
2713
2714      // Generate and write the data.
2715      std::vector<uint8_t> table_data;
2716      CompactOffsetTable::Build(*offsets, &table_data);
2717
2718      // Store the offset since we need to put those after the dex file. Table offsets are relative
2719      // to the start of the quicken info section.
2720      out_table_offsets_->push_back(current_offset);
2721
2722      const uint32_t length = table_data.size() * sizeof(table_data.front());
2723      if (!out_->WriteFully(table_data.data(), length)) {
2724        PLOG(ERROR) << "Failed to write quickening offset table for " << dex_file->GetLocation()
2725                    << " to " << out_->GetLocation();
2726        return false;
2727      }
2728      written_bytes_ += length;
2729    }
2730    return true;
2731  }
2732
2733  size_t GetNumberOfWrittenBytes() const {
2734    return written_bytes_;
2735  }
2736
2737 private:
2738  OutputStream* const out_;
2739  const uint32_t start_offset_;
2740  size_t written_bytes_ = 0u;
2741  // Maps containing the offsets for the tables.
2742  SafeMap<const DexFile*, std::vector<uint32_t>>* const quicken_info_offset_indices_;
2743  std::vector<uint32_t>* const out_table_offsets_;
2744};
2745
2746bool OatWriter::WriteQuickeningInfo(OutputStream* vdex_out) {
2747  if (!extract_dex_files_into_vdex_) {
2748    // Nothing to write. Leave `vdex_size_` untouched and unaligned.
2749    vdex_quickening_info_offset_ = vdex_size_;
2750    size_quickening_info_alignment_ = 0;
2751    return true;
2752  }
2753  size_t initial_offset = vdex_size_;
2754  // Make sure the table is properly aligned.
2755  size_t start_offset = RoundUp(initial_offset, 4u);
2756
2757  off_t actual_offset = vdex_out->Seek(start_offset, kSeekSet);
2758  if (actual_offset != static_cast<off_t>(start_offset)) {
2759    PLOG(ERROR) << "Failed to seek to quickening info section. Actual: " << actual_offset
2760                << " Expected: " << start_offset
2761                << " Output: " << vdex_out->GetLocation();
2762    return false;
2763  }
2764
2765  size_t current_offset = start_offset;
2766  if (compiler_driver_->GetCompilerOptions().IsQuickeningCompilationEnabled()) {
2767    std::vector<uint32_t> dex_files_indices;
2768    WriteQuickeningInfoMethodVisitor write_quicken_info_visitor(this, vdex_out);
2769    if (!write_quicken_info_visitor.VisitDexMethods(*dex_files_)) {
2770      PLOG(ERROR) << "Failed to write the vdex quickening info. File: " << vdex_out->GetLocation();
2771      return false;
2772    }
2773
2774    uint32_t quicken_info_offset = write_quicken_info_visitor.GetNumberOfWrittenBytes();
2775    current_offset = current_offset + quicken_info_offset;
2776    uint32_t before_offset = current_offset;
2777    current_offset = RoundUp(current_offset, CompactOffsetTable::kAlignment);
2778    const size_t extra_bytes = current_offset - before_offset;
2779    quicken_info_offset += extra_bytes;
2780    actual_offset = vdex_out->Seek(current_offset, kSeekSet);
2781    if (actual_offset != static_cast<off_t>(current_offset)) {
2782      PLOG(ERROR) << "Failed to seek to quickening offset table section. Actual: " << actual_offset
2783                  << " Expected: " << current_offset
2784                  << " Output: " << vdex_out->GetLocation();
2785      return false;
2786    }
2787
2788    std::vector<uint32_t> table_offsets;
2789    WriteQuickeningInfoOffsetsMethodVisitor table_visitor(
2790        vdex_out,
2791        quicken_info_offset,
2792        &write_quicken_info_visitor.GetQuickenInfoOffsetIndicies(),
2793        /*out*/ &table_offsets);
2794    if (!table_visitor.VisitDexMethods(*dex_files_)) {
2795      PLOG(ERROR) << "Failed to write the vdex quickening info. File: "
2796                  << vdex_out->GetLocation();
2797      return false;
2798    }
2799
2800    CHECK_EQ(table_offsets.size(), dex_files_->size());
2801
2802    current_offset += table_visitor.GetNumberOfWrittenBytes();
2803
2804    // Store the offset table offset as a preheader for each dex.
2805    size_t index = 0;
2806    for (const OatDexFile& oat_dex_file : oat_dex_files_) {
2807      const off_t desired_offset = oat_dex_file.dex_file_offset_ -
2808          sizeof(VdexFile::QuickeningTableOffsetType);
2809      actual_offset = vdex_out->Seek(desired_offset, kSeekSet);
2810      if (actual_offset != desired_offset) {
2811        PLOG(ERROR) << "Failed to seek to before dex file for writing offset table offset: "
2812                    << actual_offset << " Expected: " << desired_offset
2813                    << " Output: " << vdex_out->GetLocation();
2814        return false;
2815      }
2816      uint32_t offset = table_offsets[index];
2817      if (!vdex_out->WriteFully(reinterpret_cast<const uint8_t*>(&offset), sizeof(offset))) {
2818        PLOG(ERROR) << "Failed to write verifier deps."
2819                    << " File: " << vdex_out->GetLocation();
2820        return false;
2821      }
2822      ++index;
2823    }
2824    if (!vdex_out->Flush()) {
2825      PLOG(ERROR) << "Failed to flush stream after writing quickening info."
2826                  << " File: " << vdex_out->GetLocation();
2827      return false;
2828    }
2829    size_quickening_info_ = current_offset - start_offset;
2830  } else {
2831    // We know we did not quicken.
2832    size_quickening_info_ = 0;
2833  }
2834
2835  if (size_quickening_info_ == 0) {
2836    // Nothing was written. Leave `vdex_size_` untouched and unaligned.
2837    vdex_quickening_info_offset_ = initial_offset;
2838    size_quickening_info_alignment_ = 0;
2839  } else {
2840    vdex_size_ = start_offset + size_quickening_info_;
2841    vdex_quickening_info_offset_ = start_offset;
2842    size_quickening_info_alignment_ = start_offset - initial_offset;
2843  }
2844
2845  return true;
2846}
2847
2848bool OatWriter::WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps) {
2849  if (verifier_deps == nullptr) {
2850    // Nothing to write. Record the offset, but no need
2851    // for alignment.
2852    vdex_verifier_deps_offset_ = vdex_size_;
2853    return true;
2854  }
2855
2856  size_t initial_offset = vdex_size_;
2857  size_t start_offset = RoundUp(initial_offset, 4u);
2858
2859  vdex_size_ = start_offset;
2860  vdex_verifier_deps_offset_ = vdex_size_;
2861  size_verifier_deps_alignment_ = start_offset - initial_offset;
2862
2863  off_t actual_offset = vdex_out->Seek(start_offset, kSeekSet);
2864  if (actual_offset != static_cast<off_t>(start_offset)) {
2865    PLOG(ERROR) << "Failed to seek to verifier deps section. Actual: " << actual_offset
2866                << " Expected: " << start_offset
2867                << " Output: " << vdex_out->GetLocation();
2868    return false;
2869  }
2870
2871  std::vector<uint8_t> buffer;
2872  verifier_deps->Encode(*dex_files_, &buffer);
2873
2874  if (!vdex_out->WriteFully(buffer.data(), buffer.size())) {
2875    PLOG(ERROR) << "Failed to write verifier deps."
2876                << " File: " << vdex_out->GetLocation();
2877    return false;
2878  }
2879  if (!vdex_out->Flush()) {
2880    PLOG(ERROR) << "Failed to flush stream after writing verifier deps."
2881                << " File: " << vdex_out->GetLocation();
2882    return false;
2883  }
2884
2885  size_verifier_deps_ = buffer.size();
2886  vdex_size_ += size_verifier_deps_;
2887  return true;
2888}
2889
2890bool OatWriter::WriteCode(OutputStream* out) {
2891  CHECK(write_state_ == WriteState::kWriteText);
2892
2893  // Wrap out to update checksum with each write.
2894  ChecksumUpdatingOutputStream checksum_updating_out(out, oat_header_.get());
2895  out = &checksum_updating_out;
2896
2897  SetMultiOatRelativePatcherAdjustment();
2898
2899  const size_t file_offset = oat_data_offset_;
2900  size_t relative_offset = oat_header_->GetExecutableOffset();
2901  DCHECK_OFFSET();
2902
2903  relative_offset = WriteCode(out, file_offset, relative_offset);
2904  if (relative_offset == 0) {
2905    LOG(ERROR) << "Failed to write oat code to " << out->GetLocation();
2906    return false;
2907  }
2908
2909  relative_offset = WriteCodeDexFiles(out, file_offset, relative_offset);
2910  if (relative_offset == 0) {
2911    LOG(ERROR) << "Failed to write oat code for dex files to " << out->GetLocation();
2912    return false;
2913  }
2914
2915  const off_t oat_end_file_offset = out->Seek(0, kSeekCurrent);
2916  if (oat_end_file_offset == static_cast<off_t>(-1)) {
2917    LOG(ERROR) << "Failed to get oat end file offset in " << out->GetLocation();
2918    return false;
2919  }
2920
2921  if (kIsDebugBuild) {
2922    uint32_t size_total = 0;
2923    #define DO_STAT(x) \
2924      VLOG(compiler) << #x "=" << PrettySize(x) << " (" << (x) << "B)"; \
2925      size_total += (x);
2926
2927    DO_STAT(size_vdex_header_);
2928    DO_STAT(size_vdex_checksums_);
2929    DO_STAT(size_dex_file_alignment_);
2930    DO_STAT(size_executable_offset_alignment_);
2931    DO_STAT(size_oat_header_);
2932    DO_STAT(size_oat_header_key_value_store_);
2933    DO_STAT(size_dex_file_);
2934    DO_STAT(size_verifier_deps_);
2935    DO_STAT(size_verifier_deps_alignment_);
2936    DO_STAT(size_quickening_info_);
2937    DO_STAT(size_quickening_info_alignment_);
2938    DO_STAT(size_interpreter_to_interpreter_bridge_);
2939    DO_STAT(size_interpreter_to_compiled_code_bridge_);
2940    DO_STAT(size_jni_dlsym_lookup_);
2941    DO_STAT(size_quick_generic_jni_trampoline_);
2942    DO_STAT(size_quick_imt_conflict_trampoline_);
2943    DO_STAT(size_quick_resolution_trampoline_);
2944    DO_STAT(size_quick_to_interpreter_bridge_);
2945    DO_STAT(size_trampoline_alignment_);
2946    DO_STAT(size_method_header_);
2947    DO_STAT(size_code_);
2948    DO_STAT(size_code_alignment_);
2949    DO_STAT(size_relative_call_thunks_);
2950    DO_STAT(size_misc_thunks_);
2951    DO_STAT(size_vmap_table_);
2952    DO_STAT(size_method_info_);
2953    DO_STAT(size_oat_dex_file_location_size_);
2954    DO_STAT(size_oat_dex_file_location_data_);
2955    DO_STAT(size_oat_dex_file_location_checksum_);
2956    DO_STAT(size_oat_dex_file_offset_);
2957    DO_STAT(size_oat_dex_file_class_offsets_offset_);
2958    DO_STAT(size_oat_dex_file_lookup_table_offset_);
2959    DO_STAT(size_oat_dex_file_dex_layout_sections_offset_);
2960    DO_STAT(size_oat_dex_file_dex_layout_sections_);
2961    DO_STAT(size_oat_dex_file_dex_layout_sections_alignment_);
2962    DO_STAT(size_oat_dex_file_method_bss_mapping_offset_);
2963    DO_STAT(size_oat_dex_file_type_bss_mapping_offset_);
2964    DO_STAT(size_oat_dex_file_string_bss_mapping_offset_);
2965    DO_STAT(size_oat_lookup_table_alignment_);
2966    DO_STAT(size_oat_lookup_table_);
2967    DO_STAT(size_oat_class_offsets_alignment_);
2968    DO_STAT(size_oat_class_offsets_);
2969    DO_STAT(size_oat_class_type_);
2970    DO_STAT(size_oat_class_status_);
2971    DO_STAT(size_oat_class_method_bitmaps_);
2972    DO_STAT(size_oat_class_method_offsets_);
2973    DO_STAT(size_method_bss_mappings_);
2974    DO_STAT(size_type_bss_mappings_);
2975    DO_STAT(size_string_bss_mappings_);
2976    #undef DO_STAT
2977
2978    VLOG(compiler) << "size_total=" << PrettySize(size_total) << " (" << size_total << "B)";
2979
2980    CHECK_EQ(vdex_size_ + oat_size_, size_total);
2981    CHECK_EQ(file_offset + size_total - vdex_size_, static_cast<size_t>(oat_end_file_offset));
2982  }
2983
2984  CHECK_EQ(file_offset + oat_size_, static_cast<size_t>(oat_end_file_offset));
2985  CHECK_EQ(oat_size_, relative_offset);
2986
2987  write_state_ = WriteState::kWriteHeader;
2988  return true;
2989}
2990
2991bool OatWriter::WriteHeader(OutputStream* out,
2992                            uint32_t image_file_location_oat_checksum,
2993                            uintptr_t image_file_location_oat_begin,
2994                            int32_t image_patch_delta) {
2995  CHECK(write_state_ == WriteState::kWriteHeader);
2996
2997  oat_header_->SetImageFileLocationOatChecksum(image_file_location_oat_checksum);
2998  oat_header_->SetImageFileLocationOatDataBegin(image_file_location_oat_begin);
2999  if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
3000    CHECK_EQ(image_patch_delta, 0);
3001    CHECK_EQ(oat_header_->GetImagePatchDelta(), 0);
3002  } else {
3003    CHECK_ALIGNED(image_patch_delta, kPageSize);
3004    oat_header_->SetImagePatchDelta(image_patch_delta);
3005  }
3006  oat_header_->UpdateChecksumWithHeaderData();
3007
3008  const size_t file_offset = oat_data_offset_;
3009
3010  off_t current_offset = out->Seek(0, kSeekCurrent);
3011  if (current_offset == static_cast<off_t>(-1)) {
3012    PLOG(ERROR) << "Failed to get current offset from " << out->GetLocation();
3013    return false;
3014  }
3015  if (out->Seek(file_offset, kSeekSet) == static_cast<off_t>(-1)) {
3016    PLOG(ERROR) << "Failed to seek to oat header position in " << out->GetLocation();
3017    return false;
3018  }
3019  DCHECK_EQ(file_offset, static_cast<size_t>(out->Seek(0, kSeekCurrent)));
3020
3021  // Flush all other data before writing the header.
3022  if (!out->Flush()) {
3023    PLOG(ERROR) << "Failed to flush before writing oat header to " << out->GetLocation();
3024    return false;
3025  }
3026  // Write the header.
3027  size_t header_size = oat_header_->GetHeaderSize();
3028  if (!out->WriteFully(oat_header_.get(), header_size)) {
3029    PLOG(ERROR) << "Failed to write oat header to " << out->GetLocation();
3030    return false;
3031  }
3032  // Flush the header data.
3033  if (!out->Flush()) {
3034    PLOG(ERROR) << "Failed to flush after writing oat header to " << out->GetLocation();
3035    return false;
3036  }
3037
3038  if (out->Seek(current_offset, kSeekSet) == static_cast<off_t>(-1)) {
3039    PLOG(ERROR) << "Failed to seek back after writing oat header to " << out->GetLocation();
3040    return false;
3041  }
3042  DCHECK_EQ(current_offset, out->Seek(0, kSeekCurrent));
3043
3044  write_state_ = WriteState::kDone;
3045  return true;
3046}
3047
3048size_t OatWriter::WriteClassOffsets(OutputStream* out, size_t file_offset, size_t relative_offset) {
3049  for (OatDexFile& oat_dex_file : oat_dex_files_) {
3050    if (oat_dex_file.class_offsets_offset_ != 0u) {
3051      // Class offsets are required to be 4 byte aligned.
3052      if (UNLIKELY(!IsAligned<4u>(relative_offset))) {
3053        size_t padding_size =  RoundUp(relative_offset, 4u) - relative_offset;
3054        if (!WriteUpTo16BytesAlignment(out, padding_size, &size_oat_class_offsets_alignment_)) {
3055          return 0u;
3056        }
3057        relative_offset += padding_size;
3058      }
3059      DCHECK_OFFSET();
3060      if (!oat_dex_file.WriteClassOffsets(this, out)) {
3061        return 0u;
3062      }
3063      relative_offset += oat_dex_file.GetClassOffsetsRawSize();
3064    }
3065  }
3066  return relative_offset;
3067}
3068
3069size_t OatWriter::WriteClasses(OutputStream* out, size_t file_offset, size_t relative_offset) {
3070  const bool may_have_compiled = MayHaveCompiledMethods();
3071  if (may_have_compiled) {
3072    CHECK_EQ(oat_class_headers_.size(), oat_classes_.size());
3073  }
3074  for (size_t i = 0; i < oat_class_headers_.size(); ++i) {
3075    // If there are any classes, the class offsets allocation aligns the offset.
3076    DCHECK_ALIGNED(relative_offset, 4u);
3077    DCHECK_OFFSET();
3078    if (!oat_class_headers_[i].Write(this, out, oat_data_offset_)) {
3079      return 0u;
3080    }
3081    relative_offset += oat_class_headers_[i].SizeOf();
3082    if (may_have_compiled) {
3083      if (!oat_classes_[i].Write(this, out)) {
3084        return 0u;
3085      }
3086      relative_offset += oat_classes_[i].SizeOf();
3087    }
3088  }
3089  return relative_offset;
3090}
3091
3092size_t OatWriter::WriteMaps(OutputStream* out, size_t file_offset, size_t relative_offset) {
3093  {
3094    size_t vmap_tables_offset = relative_offset;
3095    WriteMapMethodVisitor visitor(this, out, file_offset, relative_offset);
3096    if (UNLIKELY(!VisitDexMethods(&visitor))) {
3097      return 0;
3098    }
3099    relative_offset = visitor.GetOffset();
3100    size_vmap_table_ = relative_offset - vmap_tables_offset;
3101  }
3102  {
3103    size_t method_infos_offset = relative_offset;
3104    WriteMethodInfoVisitor visitor(this, out, file_offset, relative_offset);
3105    if (UNLIKELY(!VisitDexMethods(&visitor))) {
3106      return 0;
3107    }
3108    relative_offset = visitor.GetOffset();
3109    size_method_info_ = relative_offset - method_infos_offset;
3110  }
3111
3112  return relative_offset;
3113}
3114
3115
3116template <typename GetBssOffset>
3117size_t WriteIndexBssMapping(OutputStream* out,
3118                            size_t number_of_indexes,
3119                            size_t slot_size,
3120                            const BitVector& indexes,
3121                            GetBssOffset get_bss_offset) {
3122  // Allocate the IndexBssMapping.
3123  size_t number_of_entries = CalculateNumberOfIndexBssMappingEntries(
3124      number_of_indexes, slot_size, indexes, get_bss_offset);
3125  size_t mappings_size = IndexBssMapping::ComputeSize(number_of_entries);
3126  DCHECK_ALIGNED(mappings_size, sizeof(uint32_t));
3127  std::unique_ptr<uint32_t[]> storage(new uint32_t[mappings_size / sizeof(uint32_t)]);
3128  IndexBssMapping* mappings = new(storage.get()) IndexBssMapping(number_of_entries);
3129  mappings->ClearPadding();
3130  // Encode the IndexBssMapping.
3131  IndexBssMappingEncoder encoder(number_of_indexes, slot_size);
3132  auto init_it = mappings->begin();
3133  bool first_index = true;
3134  for (uint32_t index : indexes.Indexes()) {
3135    size_t bss_offset = get_bss_offset(index);
3136    if (first_index) {
3137      first_index = false;
3138      encoder.Reset(index, bss_offset);
3139    } else if (!encoder.TryMerge(index, bss_offset)) {
3140      *init_it = encoder.GetEntry();
3141      ++init_it;
3142      encoder.Reset(index, bss_offset);
3143    }
3144  }
3145  // Store the last entry.
3146  *init_it = encoder.GetEntry();
3147  ++init_it;
3148  DCHECK(init_it == mappings->end());
3149
3150  if (!out->WriteFully(storage.get(), mappings_size)) {
3151    return 0u;
3152  }
3153  return mappings_size;
3154}
3155
3156size_t OatWriter::WriteIndexBssMappings(OutputStream* out,
3157                                        size_t file_offset,
3158                                        size_t relative_offset) {
3159  TimingLogger::ScopedTiming split("WriteMethodBssMappings", timings_);
3160  if (bss_method_entry_references_.empty() &&
3161      bss_type_entry_references_.empty() &&
3162      bss_string_entry_references_.empty()) {
3163    return relative_offset;
3164  }
3165  // If there are any classes, the class offsets allocation aligns the offset
3166  // and we cannot have method bss mappings without class offsets.
3167  static_assert(alignof(IndexBssMapping) == sizeof(uint32_t),
3168                "IndexBssMapping alignment check.");
3169  DCHECK_ALIGNED(relative_offset, sizeof(uint32_t));
3170
3171  PointerSize pointer_size = GetInstructionSetPointerSize(oat_header_->GetInstructionSet());
3172  for (size_t i = 0, size = dex_files_->size(); i != size; ++i) {
3173    const DexFile* dex_file = (*dex_files_)[i];
3174    OatDexFile* oat_dex_file = &oat_dex_files_[i];
3175    auto method_it = bss_method_entry_references_.find(dex_file);
3176    if (method_it != bss_method_entry_references_.end()) {
3177      const BitVector& method_indexes = method_it->second;
3178      DCHECK_EQ(relative_offset, oat_dex_file->method_bss_mapping_offset_);
3179      DCHECK_OFFSET();
3180      size_t method_mappings_size = WriteIndexBssMapping(
3181          out,
3182          dex_file->NumMethodIds(),
3183          static_cast<size_t>(pointer_size),
3184          method_indexes,
3185          [=](uint32_t index) {
3186            return bss_method_entries_.Get({dex_file, index});
3187          });
3188      if (method_mappings_size == 0u) {
3189        return 0u;
3190      }
3191      size_method_bss_mappings_ += method_mappings_size;
3192      relative_offset += method_mappings_size;
3193    } else {
3194      DCHECK_EQ(0u, oat_dex_file->method_bss_mapping_offset_);
3195    }
3196
3197    auto type_it = bss_type_entry_references_.find(dex_file);
3198    if (type_it != bss_type_entry_references_.end()) {
3199      const BitVector& type_indexes = type_it->second;
3200      DCHECK_EQ(relative_offset, oat_dex_file->type_bss_mapping_offset_);
3201      DCHECK_OFFSET();
3202      size_t type_mappings_size = WriteIndexBssMapping(
3203          out,
3204          dex_file->NumTypeIds(),
3205          sizeof(GcRoot<mirror::Class>),
3206          type_indexes,
3207          [=](uint32_t index) {
3208            return bss_type_entries_.Get({dex_file, dex::TypeIndex(index)});
3209          });
3210      if (type_mappings_size == 0u) {
3211        return 0u;
3212      }
3213      size_type_bss_mappings_ += type_mappings_size;
3214      relative_offset += type_mappings_size;
3215    } else {
3216      DCHECK_EQ(0u, oat_dex_file->type_bss_mapping_offset_);
3217    }
3218
3219    auto string_it = bss_string_entry_references_.find(dex_file);
3220    if (string_it != bss_string_entry_references_.end()) {
3221      const BitVector& string_indexes = string_it->second;
3222      DCHECK_EQ(relative_offset, oat_dex_file->string_bss_mapping_offset_);
3223      DCHECK_OFFSET();
3224      size_t string_mappings_size = WriteIndexBssMapping(
3225          out,
3226          dex_file->NumStringIds(),
3227          sizeof(GcRoot<mirror::String>),
3228          string_indexes,
3229          [=](uint32_t index) {
3230            return bss_string_entries_.Get({dex_file, dex::StringIndex(index)});
3231          });
3232      if (string_mappings_size == 0u) {
3233        return 0u;
3234      }
3235      size_string_bss_mappings_ += string_mappings_size;
3236      relative_offset += string_mappings_size;
3237    } else {
3238      DCHECK_EQ(0u, oat_dex_file->string_bss_mapping_offset_);
3239    }
3240  }
3241  return relative_offset;
3242}
3243
3244size_t OatWriter::WriteOatDexFiles(OutputStream* out, size_t file_offset, size_t relative_offset) {
3245  TimingLogger::ScopedTiming split("WriteOatDexFiles", timings_);
3246
3247  for (size_t i = 0, size = oat_dex_files_.size(); i != size; ++i) {
3248    OatDexFile* oat_dex_file = &oat_dex_files_[i];
3249    DCHECK_EQ(relative_offset, oat_dex_file->offset_);
3250    DCHECK_OFFSET();
3251
3252    // Write OatDexFile.
3253    if (!oat_dex_file->Write(this, out)) {
3254      return 0u;
3255    }
3256    relative_offset += oat_dex_file->SizeOf();
3257  }
3258
3259  return relative_offset;
3260}
3261
3262size_t OatWriter::WriteCode(OutputStream* out, size_t file_offset, size_t relative_offset) {
3263  if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
3264    InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
3265
3266    #define DO_TRAMPOLINE(field) \
3267      do { \
3268        uint32_t aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set); \
3269        uint32_t alignment_padding = aligned_offset - relative_offset; \
3270        out->Seek(alignment_padding, kSeekCurrent); \
3271        size_trampoline_alignment_ += alignment_padding; \
3272        if (!out->WriteFully((field)->data(), (field)->size())) { \
3273          PLOG(ERROR) << "Failed to write " # field " to " << out->GetLocation(); \
3274          return false; \
3275        } \
3276        size_ ## field += (field)->size(); \
3277        relative_offset += alignment_padding + (field)->size(); \
3278        DCHECK_OFFSET(); \
3279      } while (false)
3280
3281    DO_TRAMPOLINE(jni_dlsym_lookup_);
3282    DO_TRAMPOLINE(quick_generic_jni_trampoline_);
3283    DO_TRAMPOLINE(quick_imt_conflict_trampoline_);
3284    DO_TRAMPOLINE(quick_resolution_trampoline_);
3285    DO_TRAMPOLINE(quick_to_interpreter_bridge_);
3286    #undef DO_TRAMPOLINE
3287  }
3288  return relative_offset;
3289}
3290
3291size_t OatWriter::WriteCodeDexFiles(OutputStream* out,
3292                                    size_t file_offset,
3293                                    size_t relative_offset) {
3294  if (!compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) {
3295    // As with InitOatCodeDexFiles, also skip the writer if
3296    // compilation was disabled.
3297    if (kOatWriterDebugOatCodeLayout) {
3298      LOG(INFO) << "WriteCodeDexFiles: OatWriter("
3299                << this << "), "
3300                << "compilation is disabled";
3301    }
3302
3303    return relative_offset;
3304  }
3305  ScopedObjectAccess soa(Thread::Current());
3306  DCHECK(ordered_methods_ != nullptr);
3307  std::unique_ptr<OrderedMethodList> ordered_methods_ptr =
3308      std::move(ordered_methods_);
3309  WriteCodeMethodVisitor visitor(this,
3310                                 out,
3311                                 file_offset,
3312                                 relative_offset,
3313                                 std::move(*ordered_methods_ptr));
3314  if (UNLIKELY(!visitor.Visit())) {
3315    return 0;
3316  }
3317  relative_offset = visitor.GetOffset();
3318
3319  size_code_alignment_ += relative_patcher_->CodeAlignmentSize();
3320  size_relative_call_thunks_ += relative_patcher_->RelativeCallThunksSize();
3321  size_misc_thunks_ += relative_patcher_->MiscThunksSize();
3322
3323  return relative_offset;
3324}
3325
3326bool OatWriter::RecordOatDataOffset(OutputStream* out) {
3327  // Get the elf file offset of the oat file.
3328  const off_t raw_file_offset = out->Seek(0, kSeekCurrent);
3329  if (raw_file_offset == static_cast<off_t>(-1)) {
3330    LOG(ERROR) << "Failed to get file offset in " << out->GetLocation();
3331    return false;
3332  }
3333  oat_data_offset_ = static_cast<size_t>(raw_file_offset);
3334  return true;
3335}
3336
3337bool OatWriter::WriteDexFiles(OutputStream* out,
3338                              File* file,
3339                              bool update_input_vdex,
3340                              CopyOption copy_dex_files) {
3341  TimingLogger::ScopedTiming split("Write Dex files", timings_);
3342
3343  // If extraction is enabled, only do it if not all the dex files are aligned and uncompressed.
3344  if (copy_dex_files == CopyOption::kOnlyIfCompressed) {
3345    extract_dex_files_into_vdex_ = false;
3346    for (OatDexFile& oat_dex_file : oat_dex_files_) {
3347      if (!oat_dex_file.source_.IsZipEntry()) {
3348        extract_dex_files_into_vdex_ = true;
3349        break;
3350      }
3351      ZipEntry* entry = oat_dex_file.source_.GetZipEntry();
3352      if (!entry->IsUncompressed() || !entry->IsAlignedToDexHeader()) {
3353        extract_dex_files_into_vdex_ = true;
3354        break;
3355      }
3356    }
3357  } else if (copy_dex_files == CopyOption::kAlways) {
3358    extract_dex_files_into_vdex_ = true;
3359  } else {
3360    DCHECK(copy_dex_files == CopyOption::kNever);
3361    extract_dex_files_into_vdex_ = false;
3362  }
3363
3364  if (extract_dex_files_into_vdex_) {
3365    // Add the dex section header.
3366    vdex_size_ += sizeof(VdexFile::DexSectionHeader);
3367    vdex_dex_files_offset_ = vdex_size_;
3368    // Write dex files.
3369    for (OatDexFile& oat_dex_file : oat_dex_files_) {
3370      if (!WriteDexFile(out, file, &oat_dex_file, update_input_vdex)) {
3371        return false;
3372      }
3373    }
3374
3375    // Write shared dex file data section and fix up the dex file headers.
3376    vdex_dex_shared_data_offset_ = vdex_size_;
3377    uint32_t shared_data_size = 0u;
3378
3379    if (dex_container_ != nullptr) {
3380      CHECK(!update_input_vdex) << "Update input vdex should have empty dex container";
3381      DexContainer::Section* const section = dex_container_->GetDataSection();
3382      if (section->Size() > 0) {
3383        CHECK(compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone);
3384        const off_t existing_offset = out->Seek(0, kSeekCurrent);
3385        if (static_cast<uint32_t>(existing_offset) != vdex_dex_shared_data_offset_) {
3386          PLOG(ERROR) << "Expected offset " << vdex_dex_shared_data_offset_ << " but got "
3387                      << existing_offset;
3388          return false;
3389        }
3390        shared_data_size = section->Size();
3391        if (!out->WriteFully(section->Begin(), shared_data_size)) {
3392          PLOG(ERROR) << "Failed to write shared data!";
3393          return false;
3394        }
3395        if (!out->Flush()) {
3396          PLOG(ERROR) << "Failed to flush after writing shared dex section.";
3397          return false;
3398        }
3399        // Fix up the dex headers to have correct offsets to the data section.
3400        for (OatDexFile& oat_dex_file : oat_dex_files_) {
3401          // Overwrite the header by reading it, updating the offset, and writing it back out.
3402          DexFile::Header header;
3403          if (!file->PreadFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) {
3404            PLOG(ERROR) << "Failed to read dex header for updating";
3405            return false;
3406          }
3407          if (!CompactDexFile::IsMagicValid(header.magic_)) {
3408            // Non-compact dex file, probably failed to convert due to duplicate methods.
3409            continue;
3410          }
3411          CHECK_GT(vdex_dex_shared_data_offset_, oat_dex_file.dex_file_offset_);
3412          // Offset is from the dex file base.
3413          header.data_off_ = vdex_dex_shared_data_offset_ - oat_dex_file.dex_file_offset_;
3414          // The size should already be what part of the data buffer may be used by the dex.
3415          CHECK_LE(header.data_size_, shared_data_size);
3416          if (!file->PwriteFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) {
3417            PLOG(ERROR) << "Failed to write dex header for updating";
3418            return false;
3419          }
3420        }
3421        section->Clear();
3422      }
3423      dex_container_.reset();
3424    } else {
3425      const uint8_t* data_begin = nullptr;
3426      for (OatDexFile& oat_dex_file : oat_dex_files_) {
3427        DexFile::Header header;
3428        if (!file->PreadFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) {
3429          PLOG(ERROR) << "Failed to read dex header";
3430          return false;
3431        }
3432        if (!CompactDexFile::IsMagicValid(header.magic_)) {
3433          // Non compact dex does not have shared data section.
3434          continue;
3435        }
3436        const uint32_t expected_data_off = vdex_dex_shared_data_offset_ -
3437            oat_dex_file.dex_file_offset_;
3438        if (header.data_off_ != expected_data_off) {
3439          PLOG(ERROR) << "Shared data section offset " << header.data_off_
3440                      << " does not match expected value " << expected_data_off;
3441          return false;
3442        }
3443        if (oat_dex_file.source_.IsRawData()) {
3444          // Figure out the start of the shared data section so we can copy it below.
3445          const uint8_t* cur_data_begin = oat_dex_file.source_.GetRawData() + header.data_off_;
3446          if (data_begin != nullptr) {
3447            CHECK_EQ(data_begin, cur_data_begin);
3448          }
3449          data_begin = cur_data_begin;
3450        }
3451        // The different dex files currently can have different data sizes since
3452        // the dex writer writes them one at a time into the shared section.:w
3453        shared_data_size = std::max(shared_data_size, header.data_size_);
3454      }
3455      // If we are not updating the input vdex, write out the shared data section.
3456      if (!update_input_vdex) {
3457        const off_t existing_offset = out->Seek(0, kSeekCurrent);
3458        if (static_cast<uint32_t>(existing_offset) != vdex_dex_shared_data_offset_) {
3459          PLOG(ERROR) << "Expected offset " << vdex_dex_shared_data_offset_ << " but got "
3460                      << existing_offset;
3461          return false;
3462        }
3463        if (!out->WriteFully(data_begin, shared_data_size)) {
3464          PLOG(ERROR) << "Failed to write shared data!";
3465          return false;
3466        }
3467        if (!out->Flush()) {
3468          PLOG(ERROR) << "Failed to flush after writing shared dex section.";
3469          return false;
3470        }
3471      }
3472    }
3473    vdex_size_ += shared_data_size;
3474    size_dex_file_ += shared_data_size;
3475  } else {
3476    vdex_dex_shared_data_offset_ = vdex_size_;
3477  }
3478
3479  return true;
3480}
3481
3482void OatWriter::CloseSources() {
3483  for (OatDexFile& oat_dex_file : oat_dex_files_) {
3484    oat_dex_file.source_.Clear();  // Get rid of the reference, it's about to be invalidated.
3485  }
3486  zipped_dex_files_.clear();
3487  zip_archives_.clear();
3488  raw_dex_files_.clear();
3489}
3490
3491bool OatWriter::WriteDexFile(OutputStream* out,
3492                             File* file,
3493                             OatDexFile* oat_dex_file,
3494                             bool update_input_vdex) {
3495  if (!SeekToDexFile(out, file, oat_dex_file)) {
3496    return false;
3497  }
3498  // update_input_vdex disables compact dex and layout.
3499  if (profile_compilation_info_ != nullptr ||
3500      compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone) {
3501    CHECK(!update_input_vdex)
3502        << "We should never update the input vdex when doing dexlayout or compact dex";
3503    if (!LayoutAndWriteDexFile(out, oat_dex_file)) {
3504      return false;
3505    }
3506  } else if (oat_dex_file->source_.IsZipEntry()) {
3507    DCHECK(!update_input_vdex);
3508    if (!WriteDexFile(out, file, oat_dex_file, oat_dex_file->source_.GetZipEntry())) {
3509      return false;
3510    }
3511  } else if (oat_dex_file->source_.IsRawFile()) {
3512    DCHECK(!update_input_vdex);
3513    if (!WriteDexFile(out, file, oat_dex_file, oat_dex_file->source_.GetRawFile())) {
3514      return false;
3515    }
3516  } else {
3517    DCHECK(oat_dex_file->source_.IsRawData());
3518    if (!WriteDexFile(out, oat_dex_file, oat_dex_file->source_.GetRawData(), update_input_vdex)) {
3519      return false;
3520    }
3521  }
3522
3523  // Update current size and account for the written data.
3524  DCHECK_EQ(vdex_size_, oat_dex_file->dex_file_offset_);
3525  vdex_size_ += oat_dex_file->dex_file_size_;
3526  size_dex_file_ += oat_dex_file->dex_file_size_;
3527  return true;
3528}
3529
3530bool OatWriter::SeekToDexFile(OutputStream* out, File* file, OatDexFile* oat_dex_file) {
3531  // Dex files are required to be 4 byte aligned.
3532  size_t initial_offset = vdex_size_;
3533  size_t start_offset = RoundUp(initial_offset, 4);
3534  size_dex_file_alignment_ += start_offset - initial_offset;
3535
3536  // Leave extra room for the quicken offset table offset.
3537  start_offset += sizeof(VdexFile::QuickeningTableOffsetType);
3538  // TODO: Not count the offset as part of alignment.
3539  size_dex_file_alignment_ += sizeof(VdexFile::QuickeningTableOffsetType);
3540
3541  size_t file_offset = start_offset;
3542
3543  // Seek to the start of the dex file and flush any pending operations in the stream.
3544  // Verify that, after flushing the stream, the file is at the same offset as the stream.
3545  off_t actual_offset = out->Seek(file_offset, kSeekSet);
3546  if (actual_offset != static_cast<off_t>(file_offset)) {
3547    PLOG(ERROR) << "Failed to seek to dex file section. Actual: " << actual_offset
3548                << " Expected: " << file_offset
3549                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3550    return false;
3551  }
3552  if (!out->Flush()) {
3553    PLOG(ERROR) << "Failed to flush before writing dex file."
3554                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3555    return false;
3556  }
3557  actual_offset = lseek(file->Fd(), 0, SEEK_CUR);
3558  if (actual_offset != static_cast<off_t>(file_offset)) {
3559    PLOG(ERROR) << "Stream/file position mismatch! Actual: " << actual_offset
3560                << " Expected: " << file_offset
3561                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3562    return false;
3563  }
3564
3565  vdex_size_ = start_offset;
3566  oat_dex_file->dex_file_offset_ = start_offset;
3567  return true;
3568}
3569
3570bool OatWriter::LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_file) {
3571  // Open dex files and write them into `out`.
3572  // Note that we only verify dex files which do not belong to the boot class path.
3573  // This is because those have been processed by `hiddenapi` and would not pass
3574  // some of the checks. No guarantees are lost, however, as `hiddenapi` verifies
3575  // the dex files prior to processing.
3576  TimingLogger::ScopedTiming split("Dex Layout", timings_);
3577  std::string error_msg;
3578  std::string location(oat_dex_file->GetLocation());
3579  std::unique_ptr<const DexFile> dex_file;
3580  const ArtDexFileLoader dex_file_loader;
3581  if (oat_dex_file->source_.IsZipEntry()) {
3582    ZipEntry* zip_entry = oat_dex_file->source_.GetZipEntry();
3583    std::unique_ptr<MemMap> mem_map(
3584        zip_entry->ExtractToMemMap(location.c_str(), "classes.dex", &error_msg));
3585    if (mem_map == nullptr) {
3586      LOG(ERROR) << "Failed to extract dex file to mem map for layout: " << error_msg;
3587      return false;
3588    }
3589    dex_file = dex_file_loader.Open(location,
3590                               zip_entry->GetCrc32(),
3591                               std::move(mem_map),
3592                               /* verify */ !compiling_boot_image_,
3593                               /* verify_checksum */ true,
3594                               &error_msg);
3595  } else if (oat_dex_file->source_.IsRawFile()) {
3596    File* raw_file = oat_dex_file->source_.GetRawFile();
3597    int dup_fd = dup(raw_file->Fd());
3598    if (dup_fd < 0) {
3599      PLOG(ERROR) << "Failed to dup dex file descriptor (" << raw_file->Fd() << ") at " << location;
3600      return false;
3601    }
3602    dex_file = dex_file_loader.OpenDex(dup_fd, location,
3603                                       /* verify */ !compiling_boot_image_,
3604                                       /* verify_checksum */ true,
3605                                       /* mmap_shared */ false,
3606                                       &error_msg);
3607  } else {
3608    // The source data is a vdex file.
3609    CHECK(oat_dex_file->source_.IsRawData())
3610        << static_cast<size_t>(oat_dex_file->source_.GetType());
3611    const uint8_t* raw_dex_file = oat_dex_file->source_.GetRawData();
3612    // Note: The raw data has already been checked to contain the header
3613    // and all the data that the header specifies as the file size.
3614    DCHECK(raw_dex_file != nullptr);
3615    DCHECK(ValidateDexFileHeader(raw_dex_file, oat_dex_file->GetLocation()));
3616    const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_dex_file);
3617    // Since the source may have had its layout changed, or may be quickened, don't verify it.
3618    dex_file = dex_file_loader.Open(raw_dex_file,
3619                                    header->file_size_,
3620                                    location,
3621                                    oat_dex_file->dex_file_location_checksum_,
3622                                    nullptr,
3623                                    /* verify */ false,
3624                                    /* verify_checksum */ false,
3625                                    &error_msg);
3626  }
3627  if (dex_file == nullptr) {
3628    LOG(ERROR) << "Failed to open dex file for layout: " << error_msg;
3629    return false;
3630  }
3631  Options options;
3632  options.compact_dex_level_ = compact_dex_level_;
3633  options.update_checksum_ = true;
3634  DexLayout dex_layout(options, profile_compilation_info_, /*file*/ nullptr, /*header*/ nullptr);
3635  const uint8_t* dex_src = nullptr;
3636  if (dex_layout.ProcessDexFile(location.c_str(), dex_file.get(), 0, &dex_container_, &error_msg)) {
3637    oat_dex_file->dex_sections_layout_ = dex_layout.GetSections();
3638    // Dex layout can affect the size of the dex file, so we update here what we have set
3639    // when adding the dex file as a source.
3640    const UnalignedDexFileHeader* header =
3641        AsUnalignedDexFileHeader(dex_container_->GetMainSection()->Begin());
3642    oat_dex_file->dex_file_size_ = header->file_size_;
3643    dex_src = dex_container_->GetMainSection()->Begin();
3644  } else {
3645    LOG(WARNING) << "Failed to run dex layout, reason:" << error_msg;
3646    // Since we failed to convert the dex, just copy the input dex.
3647    dex_src = dex_file->Begin();
3648  }
3649  if (!WriteDexFile(out, oat_dex_file, dex_src, /* update_input_vdex */ false)) {
3650    return false;
3651  }
3652  if (dex_container_ != nullptr) {
3653    // Clear the main section in case we write more data into the container.
3654    dex_container_->GetMainSection()->Clear();
3655  }
3656  CHECK_EQ(oat_dex_file->dex_file_location_checksum_, dex_file->GetLocationChecksum());
3657  return true;
3658}
3659
3660bool OatWriter::WriteDexFile(OutputStream* out,
3661                             File* file,
3662                             OatDexFile* oat_dex_file,
3663                             ZipEntry* dex_file) {
3664  size_t start_offset = vdex_size_;
3665  DCHECK_EQ(static_cast<off_t>(start_offset), out->Seek(0, kSeekCurrent));
3666
3667  // Extract the dex file and get the extracted size.
3668  std::string error_msg;
3669  if (!dex_file->ExtractToFile(*file, &error_msg)) {
3670    LOG(ERROR) << "Failed to extract dex file from ZIP entry: " << error_msg
3671               << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3672    return false;
3673  }
3674  if (file->Flush() != 0) {
3675    PLOG(ERROR) << "Failed to flush dex file from ZIP entry."
3676                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3677    return false;
3678  }
3679  off_t extracted_end = lseek(file->Fd(), 0, SEEK_CUR);
3680  if (extracted_end == static_cast<off_t>(-1)) {
3681    PLOG(ERROR) << "Failed get end offset after writing dex file from ZIP entry."
3682                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3683    return false;
3684  }
3685  if (extracted_end < static_cast<off_t>(start_offset)) {
3686    LOG(ERROR) << "Dex file end position is before start position! End: " << extracted_end
3687               << " Start: " << start_offset
3688               << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3689    return false;
3690  }
3691  uint64_t extracted_size = static_cast<uint64_t>(extracted_end - start_offset);
3692  if (extracted_size < sizeof(DexFile::Header)) {
3693    LOG(ERROR) << "Extracted dex file is shorter than dex file header. size: "
3694               << extracted_size << " File: " << oat_dex_file->GetLocation();
3695    return false;
3696  }
3697
3698  // Read the dex file header and extract required data to OatDexFile.
3699  off_t actual_offset = lseek(file->Fd(), start_offset, SEEK_SET);
3700  if (actual_offset != static_cast<off_t>(start_offset)) {
3701    PLOG(ERROR) << "Failed to seek back to dex file header. Actual: " << actual_offset
3702                << " Expected: " << start_offset
3703                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3704    return false;
3705  }
3706  if (extracted_size < oat_dex_file->dex_file_size_) {
3707    LOG(ERROR) << "Extracted truncated dex file. Extracted size: " << extracted_size
3708               << " file size from header: " << oat_dex_file->dex_file_size_
3709               << " File: " << oat_dex_file->GetLocation();
3710    return false;
3711  }
3712
3713  // Seek both file and stream to the end offset.
3714  size_t end_offset = start_offset + oat_dex_file->dex_file_size_;
3715  actual_offset = lseek(file->Fd(), end_offset, SEEK_SET);
3716  if (actual_offset != static_cast<off_t>(end_offset)) {
3717    PLOG(ERROR) << "Failed to seek to end of dex file. Actual: " << actual_offset
3718                << " Expected: " << end_offset
3719                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3720    return false;
3721  }
3722  actual_offset = out->Seek(end_offset, kSeekSet);
3723  if (actual_offset != static_cast<off_t>(end_offset)) {
3724    PLOG(ERROR) << "Failed to seek stream to end of dex file. Actual: " << actual_offset
3725                << " Expected: " << end_offset << " File: " << oat_dex_file->GetLocation();
3726    return false;
3727  }
3728  if (!out->Flush()) {
3729    PLOG(ERROR) << "Failed to flush stream after seeking over dex file."
3730                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3731    return false;
3732  }
3733
3734  // If we extracted more than the size specified in the header, truncate the file.
3735  if (extracted_size > oat_dex_file->dex_file_size_) {
3736    if (file->SetLength(end_offset) != 0) {
3737      PLOG(ERROR) << "Failed to truncate excessive dex file length."
3738                  << " File: " << oat_dex_file->GetLocation()
3739                  << " Output: " << file->GetPath();
3740      return false;
3741    }
3742  }
3743
3744  return true;
3745}
3746
3747bool OatWriter::WriteDexFile(OutputStream* out,
3748                             File* file,
3749                             OatDexFile* oat_dex_file,
3750                             File* dex_file) {
3751  size_t start_offset = vdex_size_;
3752  DCHECK_EQ(static_cast<off_t>(start_offset), out->Seek(0, kSeekCurrent));
3753
3754  off_t input_offset = lseek(dex_file->Fd(), 0, SEEK_SET);
3755  if (input_offset != static_cast<off_t>(0)) {
3756    PLOG(ERROR) << "Failed to seek to dex file header. Actual: " << input_offset
3757                << " Expected: 0"
3758                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3759    return false;
3760  }
3761
3762  // Copy the input dex file using sendfile().
3763  if (!file->Copy(dex_file, 0, oat_dex_file->dex_file_size_)) {
3764    PLOG(ERROR) << "Failed to copy dex file to oat file."
3765                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3766    return false;
3767  }
3768  if (file->Flush() != 0) {
3769    PLOG(ERROR) << "Failed to flush dex file."
3770                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3771    return false;
3772  }
3773
3774  // Check file position and seek the stream to the end offset.
3775  size_t end_offset = start_offset + oat_dex_file->dex_file_size_;
3776  off_t actual_offset = lseek(file->Fd(), 0, SEEK_CUR);
3777  if (actual_offset != static_cast<off_t>(end_offset)) {
3778    PLOG(ERROR) << "Unexpected file position after copying dex file. Actual: " << actual_offset
3779                << " Expected: " << end_offset
3780                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3781    return false;
3782  }
3783  actual_offset = out->Seek(end_offset, kSeekSet);
3784  if (actual_offset != static_cast<off_t>(end_offset)) {
3785    PLOG(ERROR) << "Failed to seek stream to end of dex file. Actual: " << actual_offset
3786                << " Expected: " << end_offset << " File: " << oat_dex_file->GetLocation();
3787    return false;
3788  }
3789  if (!out->Flush()) {
3790    PLOG(ERROR) << "Failed to flush stream after seeking over dex file."
3791                << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath();
3792    return false;
3793  }
3794
3795  return true;
3796}
3797
3798bool OatWriter::WriteDexFile(OutputStream* out,
3799                             OatDexFile* oat_dex_file,
3800                             const uint8_t* dex_file,
3801                             bool update_input_vdex) {
3802  // Note: The raw data has already been checked to contain the header
3803  // and all the data that the header specifies as the file size.
3804  DCHECK(dex_file != nullptr);
3805  DCHECK(ValidateDexFileHeader(dex_file, oat_dex_file->GetLocation()));
3806  const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(dex_file);
3807
3808  if (update_input_vdex) {
3809    // The vdex already contains the dex code, no need to write it again.
3810  } else {
3811    if (!out->WriteFully(dex_file, header->file_size_)) {
3812      PLOG(ERROR) << "Failed to write dex file " << oat_dex_file->GetLocation()
3813                  << " to " << out->GetLocation();
3814      return false;
3815    }
3816    if (!out->Flush()) {
3817      PLOG(ERROR) << "Failed to flush stream after writing dex file."
3818                  << " File: " << oat_dex_file->GetLocation();
3819      return false;
3820    }
3821  }
3822  return true;
3823}
3824
3825bool OatWriter::OpenDexFiles(
3826    File* file,
3827    bool verify,
3828    /*out*/ std::vector<std::unique_ptr<MemMap>>* opened_dex_files_map,
3829    /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) {
3830  TimingLogger::ScopedTiming split("OpenDexFiles", timings_);
3831
3832  if (oat_dex_files_.empty()) {
3833    // Nothing to do.
3834    return true;
3835  }
3836
3837  if (!extract_dex_files_into_vdex_) {
3838    std::vector<std::unique_ptr<const DexFile>> dex_files;
3839    std::vector<std::unique_ptr<MemMap>> maps;
3840    for (OatDexFile& oat_dex_file : oat_dex_files_) {
3841      std::string error_msg;
3842      MemMap* map = oat_dex_file.source_.GetZipEntry()->MapDirectlyOrExtract(
3843          oat_dex_file.dex_file_location_data_, "zipped dex", &error_msg);
3844      if (map == nullptr) {
3845        LOG(ERROR) << error_msg;
3846        return false;
3847      }
3848      maps.emplace_back(map);
3849      // Now, open the dex file.
3850      const ArtDexFileLoader dex_file_loader;
3851      dex_files.emplace_back(dex_file_loader.Open(map->Begin(),
3852                                                  map->Size(),
3853                                                  oat_dex_file.GetLocation(),
3854                                                  oat_dex_file.dex_file_location_checksum_,
3855                                                  /* oat_dex_file */ nullptr,
3856                                                  verify,
3857                                                  verify,
3858                                                  &error_msg));
3859      if (dex_files.back() == nullptr) {
3860        LOG(ERROR) << "Failed to open dex file from oat file. File: " << oat_dex_file.GetLocation()
3861                   << " Error: " << error_msg;
3862        return false;
3863      }
3864      oat_dex_file.class_offsets_.resize(dex_files.back()->GetHeader().class_defs_size_);
3865    }
3866    *opened_dex_files_map = std::move(maps);
3867    *opened_dex_files = std::move(dex_files);
3868    CloseSources();
3869    return true;
3870  }
3871  // We could have closed the sources at the point of writing the dex files, but to
3872  // make it consistent with the case we're not writing the dex files, we close them now.
3873  CloseSources();
3874
3875  size_t map_offset = oat_dex_files_[0].dex_file_offset_;
3876  size_t length = vdex_size_ - map_offset;
3877
3878  std::string error_msg;
3879  std::unique_ptr<MemMap> dex_files_map(MemMap::MapFile(
3880      length,
3881      PROT_READ | PROT_WRITE,
3882      MAP_SHARED,
3883      file->Fd(),
3884      map_offset,
3885      /* low_4gb */ false,
3886      file->GetPath().c_str(),
3887      &error_msg));
3888  if (dex_files_map == nullptr) {
3889    LOG(ERROR) << "Failed to mmap() dex files from oat file. File: " << file->GetPath()
3890               << " error: " << error_msg;
3891    return false;
3892  }
3893  const ArtDexFileLoader dex_file_loader;
3894  std::vector<std::unique_ptr<const DexFile>> dex_files;
3895  for (OatDexFile& oat_dex_file : oat_dex_files_) {
3896    const uint8_t* raw_dex_file =
3897        dex_files_map->Begin() + oat_dex_file.dex_file_offset_ - map_offset;
3898
3899    if (kIsDebugBuild) {
3900      // Sanity check our input files.
3901      // Note that ValidateDexFileHeader() logs error messages.
3902      CHECK(ValidateDexFileHeader(raw_dex_file, oat_dex_file.GetLocation()))
3903          << "Failed to verify written dex file header!"
3904          << " Output: " << file->GetPath() << " ~ " << std::hex << map_offset
3905          << " ~ " << static_cast<const void*>(raw_dex_file);
3906
3907      const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_dex_file);
3908      CHECK_EQ(header->file_size_, oat_dex_file.dex_file_size_)
3909          << "File size mismatch in written dex file header! Expected: "
3910          << oat_dex_file.dex_file_size_ << " Actual: " << header->file_size_
3911          << " Output: " << file->GetPath();
3912    }
3913
3914    // Now, open the dex file.
3915    dex_files.emplace_back(dex_file_loader.Open(raw_dex_file,
3916                                                oat_dex_file.dex_file_size_,
3917                                                oat_dex_file.GetLocation(),
3918                                                oat_dex_file.dex_file_location_checksum_,
3919                                                /* oat_dex_file */ nullptr,
3920                                                verify,
3921                                                verify,
3922                                                &error_msg));
3923    if (dex_files.back() == nullptr) {
3924      LOG(ERROR) << "Failed to open dex file from oat file. File: " << oat_dex_file.GetLocation()
3925                 << " Error: " << error_msg;
3926      return false;
3927    }
3928
3929    // Set the class_offsets size now that we have easy access to the DexFile and
3930    // it has been verified in dex_file_loader.Open.
3931    oat_dex_file.class_offsets_.resize(dex_files.back()->GetHeader().class_defs_size_);
3932  }
3933
3934  opened_dex_files_map->push_back(std::move(dex_files_map));
3935  *opened_dex_files = std::move(dex_files);
3936  return true;
3937}
3938
3939bool OatWriter::WriteTypeLookupTables(
3940    OutputStream* oat_rodata,
3941    const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files) {
3942  TimingLogger::ScopedTiming split("WriteTypeLookupTables", timings_);
3943
3944  uint32_t expected_offset = oat_data_offset_ + oat_size_;
3945  off_t actual_offset = oat_rodata->Seek(expected_offset, kSeekSet);
3946  if (static_cast<uint32_t>(actual_offset) != expected_offset) {
3947    PLOG(ERROR) << "Failed to seek to TypeLookupTable section. Actual: " << actual_offset
3948                << " Expected: " << expected_offset << " File: " << oat_rodata->GetLocation();
3949    return false;
3950  }
3951
3952  DCHECK_EQ(opened_dex_files.size(), oat_dex_files_.size());
3953  for (size_t i = 0, size = opened_dex_files.size(); i != size; ++i) {
3954    OatDexFile* oat_dex_file = &oat_dex_files_[i];
3955    DCHECK_EQ(oat_dex_file->lookup_table_offset_, 0u);
3956
3957    if (oat_dex_file->create_type_lookup_table_ != CreateTypeLookupTable::kCreate ||
3958        oat_dex_file->class_offsets_.empty()) {
3959      continue;
3960    }
3961
3962    size_t table_size = TypeLookupTable::RawDataLength(oat_dex_file->class_offsets_.size());
3963    if (table_size == 0u) {
3964      continue;
3965    }
3966
3967    // Create the lookup table. When `nullptr` is given as the storage buffer,
3968    // TypeLookupTable allocates its own and OatDexFile takes ownership.
3969    const DexFile& dex_file = *opened_dex_files[i];
3970    {
3971      std::unique_ptr<TypeLookupTable> type_lookup_table =
3972          TypeLookupTable::Create(dex_file, /* storage */ nullptr);
3973      type_lookup_table_oat_dex_files_.push_back(
3974          std::make_unique<art::OatDexFile>(std::move(type_lookup_table)));
3975      dex_file.SetOatDexFile(type_lookup_table_oat_dex_files_.back().get());
3976    }
3977    TypeLookupTable* const table = type_lookup_table_oat_dex_files_.back()->GetTypeLookupTable();
3978
3979    // Type tables are required to be 4 byte aligned.
3980    size_t initial_offset = oat_size_;
3981    size_t rodata_offset = RoundUp(initial_offset, 4);
3982    size_t padding_size = rodata_offset - initial_offset;
3983
3984    if (padding_size != 0u) {
3985      std::vector<uint8_t> buffer(padding_size, 0u);
3986      if (!oat_rodata->WriteFully(buffer.data(), padding_size)) {
3987        PLOG(ERROR) << "Failed to write lookup table alignment padding."
3988                    << " File: " << oat_dex_file->GetLocation()
3989                    << " Output: " << oat_rodata->GetLocation();
3990        return false;
3991      }
3992    }
3993
3994    DCHECK_EQ(oat_data_offset_ + rodata_offset,
3995              static_cast<size_t>(oat_rodata->Seek(0u, kSeekCurrent)));
3996    DCHECK_EQ(table_size, table->RawDataLength());
3997
3998    if (!oat_rodata->WriteFully(table->RawData(), table_size)) {
3999      PLOG(ERROR) << "Failed to write lookup table."
4000                  << " File: " << oat_dex_file->GetLocation()
4001                  << " Output: " << oat_rodata->GetLocation();
4002      return false;
4003    }
4004
4005    oat_dex_file->lookup_table_offset_ = rodata_offset;
4006
4007    oat_size_ += padding_size + table_size;
4008    size_oat_lookup_table_ += table_size;
4009    size_oat_lookup_table_alignment_ += padding_size;
4010  }
4011
4012  if (!oat_rodata->Flush()) {
4013    PLOG(ERROR) << "Failed to flush stream after writing type lookup tables."
4014                << " File: " << oat_rodata->GetLocation();
4015    return false;
4016  }
4017
4018  return true;
4019}
4020
4021bool OatWriter::WriteDexLayoutSections(
4022    OutputStream* oat_rodata,
4023    const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files) {
4024  TimingLogger::ScopedTiming split(__FUNCTION__, timings_);
4025
4026  if (!kWriteDexLayoutInfo) {
4027    return true;;
4028  }
4029
4030  uint32_t expected_offset = oat_data_offset_ + oat_size_;
4031  off_t actual_offset = oat_rodata->Seek(expected_offset, kSeekSet);
4032  if (static_cast<uint32_t>(actual_offset) != expected_offset) {
4033    PLOG(ERROR) << "Failed to seek to dex layout section offset section. Actual: " << actual_offset
4034                << " Expected: " << expected_offset << " File: " << oat_rodata->GetLocation();
4035    return false;
4036  }
4037
4038  DCHECK_EQ(opened_dex_files.size(), oat_dex_files_.size());
4039  size_t rodata_offset = oat_size_;
4040  for (size_t i = 0, size = opened_dex_files.size(); i != size; ++i) {
4041    OatDexFile* oat_dex_file = &oat_dex_files_[i];
4042    DCHECK_EQ(oat_dex_file->dex_sections_layout_offset_, 0u);
4043
4044    // Write dex layout section alignment bytes.
4045    const size_t padding_size =
4046        RoundUp(rodata_offset, alignof(DexLayoutSections)) - rodata_offset;
4047    if (padding_size != 0u) {
4048      std::vector<uint8_t> buffer(padding_size, 0u);
4049      if (!oat_rodata->WriteFully(buffer.data(), padding_size)) {
4050        PLOG(ERROR) << "Failed to write lookup table alignment padding."
4051                    << " File: " << oat_dex_file->GetLocation()
4052                    << " Output: " << oat_rodata->GetLocation();
4053        return false;
4054      }
4055      size_oat_dex_file_dex_layout_sections_alignment_ += padding_size;
4056      rodata_offset += padding_size;
4057    }
4058
4059    DCHECK_ALIGNED(rodata_offset, alignof(DexLayoutSections));
4060    DCHECK_EQ(oat_data_offset_ + rodata_offset,
4061              static_cast<size_t>(oat_rodata->Seek(0u, kSeekCurrent)));
4062    DCHECK(oat_dex_file != nullptr);
4063    if (!oat_rodata->WriteFully(&oat_dex_file->dex_sections_layout_,
4064                                sizeof(oat_dex_file->dex_sections_layout_))) {
4065      PLOG(ERROR) << "Failed to write dex layout sections."
4066                  << " File: " << oat_dex_file->GetLocation()
4067                  << " Output: " << oat_rodata->GetLocation();
4068      return false;
4069    }
4070    oat_dex_file->dex_sections_layout_offset_ = rodata_offset;
4071    size_oat_dex_file_dex_layout_sections_ += sizeof(oat_dex_file->dex_sections_layout_);
4072    rodata_offset += sizeof(oat_dex_file->dex_sections_layout_);
4073  }
4074  oat_size_ = rodata_offset;
4075
4076  if (!oat_rodata->Flush()) {
4077    PLOG(ERROR) << "Failed to flush stream after writing type dex layout sections."
4078                << " File: " << oat_rodata->GetLocation();
4079    return false;
4080  }
4081
4082  return true;
4083}
4084
4085bool OatWriter::WriteChecksumsAndVdexHeader(OutputStream* vdex_out) {
4086  // Write checksums
4087  off_t checksums_offset = sizeof(VdexFile::VerifierDepsHeader);
4088  off_t actual_offset = vdex_out->Seek(checksums_offset, kSeekSet);
4089  if (actual_offset != checksums_offset) {
4090    PLOG(ERROR) << "Failed to seek to the checksum location of vdex file. Actual: " << actual_offset
4091                << " File: " << vdex_out->GetLocation();
4092    return false;
4093  }
4094
4095  for (size_t i = 0, size = oat_dex_files_.size(); i != size; ++i) {
4096    OatDexFile* oat_dex_file = &oat_dex_files_[i];
4097    if (!vdex_out->WriteFully(
4098            &oat_dex_file->dex_file_location_checksum_, sizeof(VdexFile::VdexChecksum))) {
4099      PLOG(ERROR) << "Failed to write dex file location checksum. File: "
4100                  << vdex_out->GetLocation();
4101      return false;
4102    }
4103    size_vdex_checksums_ += sizeof(VdexFile::VdexChecksum);
4104  }
4105
4106  // Maybe write dex section header.
4107  DCHECK_NE(vdex_verifier_deps_offset_, 0u);
4108  DCHECK_NE(vdex_quickening_info_offset_, 0u);
4109
4110  bool has_dex_section = extract_dex_files_into_vdex_;
4111  if (has_dex_section) {
4112    DCHECK_NE(vdex_dex_files_offset_, 0u);
4113    size_t dex_section_size = vdex_dex_shared_data_offset_ - vdex_dex_files_offset_;
4114    size_t dex_shared_data_size = vdex_verifier_deps_offset_ - vdex_dex_shared_data_offset_;
4115    size_t quickening_info_section_size = vdex_size_ - vdex_quickening_info_offset_;
4116
4117    VdexFile::DexSectionHeader dex_section_header(dex_section_size,
4118                                                  dex_shared_data_size,
4119                                                  quickening_info_section_size);
4120    if (!vdex_out->WriteFully(&dex_section_header, sizeof(VdexFile::DexSectionHeader))) {
4121      PLOG(ERROR) << "Failed to write vdex header. File: " << vdex_out->GetLocation();
4122      return false;
4123    }
4124    size_vdex_header_ += sizeof(VdexFile::DexSectionHeader);
4125  }
4126
4127  // Write header.
4128  actual_offset = vdex_out->Seek(0, kSeekSet);
4129  if (actual_offset != 0) {
4130    PLOG(ERROR) << "Failed to seek to the beginning of vdex file. Actual: " << actual_offset
4131                << " File: " << vdex_out->GetLocation();
4132    return false;
4133  }
4134
4135  size_t verifier_deps_section_size = vdex_quickening_info_offset_ - vdex_verifier_deps_offset_;
4136
4137  VdexFile::VerifierDepsHeader deps_header(
4138      oat_dex_files_.size(), verifier_deps_section_size, has_dex_section);
4139  if (!vdex_out->WriteFully(&deps_header, sizeof(VdexFile::VerifierDepsHeader))) {
4140    PLOG(ERROR) << "Failed to write vdex header. File: " << vdex_out->GetLocation();
4141    return false;
4142  }
4143  size_vdex_header_ += sizeof(VdexFile::VerifierDepsHeader);
4144
4145  if (!vdex_out->Flush()) {
4146    PLOG(ERROR) << "Failed to flush stream after writing to vdex file."
4147                << " File: " << vdex_out->GetLocation();
4148    return false;
4149  }
4150
4151  return true;
4152}
4153
4154bool OatWriter::WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta) {
4155  return WriteUpTo16BytesAlignment(out, aligned_code_delta, &size_code_alignment_);
4156}
4157
4158bool OatWriter::WriteUpTo16BytesAlignment(OutputStream* out, uint32_t size, uint32_t* stat) {
4159  static const uint8_t kPadding[] = {
4160      0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u
4161  };
4162  DCHECK_LE(size, sizeof(kPadding));
4163  if (UNLIKELY(!out->WriteFully(kPadding, size))) {
4164    return false;
4165  }
4166  *stat += size;
4167  return true;
4168}
4169
4170void OatWriter::SetMultiOatRelativePatcherAdjustment() {
4171  DCHECK(dex_files_ != nullptr);
4172  DCHECK(relative_patcher_ != nullptr);
4173  DCHECK_NE(oat_data_offset_, 0u);
4174  if (image_writer_ != nullptr && !dex_files_->empty()) {
4175    // The oat data begin may not be initialized yet but the oat file offset is ready.
4176    size_t oat_index = image_writer_->GetOatIndexForDexFile(dex_files_->front());
4177    size_t elf_file_offset = image_writer_->GetOatFileOffset(oat_index);
4178    relative_patcher_->StartOatFile(elf_file_offset + oat_data_offset_);
4179  }
4180}
4181
4182OatWriter::OatDexFile::OatDexFile(const char* dex_file_location,
4183                                  DexFileSource source,
4184                                  CreateTypeLookupTable create_type_lookup_table,
4185                                  uint32_t dex_file_location_checksum,
4186                                  size_t dex_file_size)
4187    : source_(source),
4188      create_type_lookup_table_(create_type_lookup_table),
4189      dex_file_size_(dex_file_size),
4190      offset_(0),
4191      dex_file_location_size_(strlen(dex_file_location)),
4192      dex_file_location_data_(dex_file_location),
4193      dex_file_location_checksum_(dex_file_location_checksum),
4194      dex_file_offset_(0u),
4195      lookup_table_offset_(0u),
4196      class_offsets_offset_(0u),
4197      method_bss_mapping_offset_(0u),
4198      type_bss_mapping_offset_(0u),
4199      string_bss_mapping_offset_(0u),
4200      dex_sections_layout_offset_(0u),
4201      class_offsets_() {
4202}
4203
4204size_t OatWriter::OatDexFile::SizeOf() const {
4205  return sizeof(dex_file_location_size_)
4206          + dex_file_location_size_
4207          + sizeof(dex_file_location_checksum_)
4208          + sizeof(dex_file_offset_)
4209          + sizeof(class_offsets_offset_)
4210          + sizeof(lookup_table_offset_)
4211          + sizeof(method_bss_mapping_offset_)
4212          + sizeof(type_bss_mapping_offset_)
4213          + sizeof(string_bss_mapping_offset_)
4214          + sizeof(dex_sections_layout_offset_);
4215}
4216
4217bool OatWriter::OatDexFile::Write(OatWriter* oat_writer, OutputStream* out) const {
4218  const size_t file_offset = oat_writer->oat_data_offset_;
4219  DCHECK_OFFSET_();
4220
4221  if (!out->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) {
4222    PLOG(ERROR) << "Failed to write dex file location length to " << out->GetLocation();
4223    return false;
4224  }
4225  oat_writer->size_oat_dex_file_location_size_ += sizeof(dex_file_location_size_);
4226
4227  if (!out->WriteFully(dex_file_location_data_, dex_file_location_size_)) {
4228    PLOG(ERROR) << "Failed to write dex file location data to " << out->GetLocation();
4229    return false;
4230  }
4231  oat_writer->size_oat_dex_file_location_data_ += dex_file_location_size_;
4232
4233  if (!out->WriteFully(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_))) {
4234    PLOG(ERROR) << "Failed to write dex file location checksum to " << out->GetLocation();
4235    return false;
4236  }
4237  oat_writer->size_oat_dex_file_location_checksum_ += sizeof(dex_file_location_checksum_);
4238
4239  if (!out->WriteFully(&dex_file_offset_, sizeof(dex_file_offset_))) {
4240    PLOG(ERROR) << "Failed to write dex file offset to " << out->GetLocation();
4241    return false;
4242  }
4243  oat_writer->size_oat_dex_file_offset_ += sizeof(dex_file_offset_);
4244
4245  if (!out->WriteFully(&class_offsets_offset_, sizeof(class_offsets_offset_))) {
4246    PLOG(ERROR) << "Failed to write class offsets offset to " << out->GetLocation();
4247    return false;
4248  }
4249  oat_writer->size_oat_dex_file_class_offsets_offset_ += sizeof(class_offsets_offset_);
4250
4251  if (!out->WriteFully(&lookup_table_offset_, sizeof(lookup_table_offset_))) {
4252    PLOG(ERROR) << "Failed to write lookup table offset to " << out->GetLocation();
4253    return false;
4254  }
4255  oat_writer->size_oat_dex_file_lookup_table_offset_ += sizeof(lookup_table_offset_);
4256
4257  if (!out->WriteFully(&dex_sections_layout_offset_, sizeof(dex_sections_layout_offset_))) {
4258    PLOG(ERROR) << "Failed to write dex section layout info to " << out->GetLocation();
4259    return false;
4260  }
4261  oat_writer->size_oat_dex_file_dex_layout_sections_offset_ += sizeof(dex_sections_layout_offset_);
4262
4263  if (!out->WriteFully(&method_bss_mapping_offset_, sizeof(method_bss_mapping_offset_))) {
4264    PLOG(ERROR) << "Failed to write method bss mapping offset to " << out->GetLocation();
4265    return false;
4266  }
4267  oat_writer->size_oat_dex_file_method_bss_mapping_offset_ += sizeof(method_bss_mapping_offset_);
4268
4269  if (!out->WriteFully(&type_bss_mapping_offset_, sizeof(type_bss_mapping_offset_))) {
4270    PLOG(ERROR) << "Failed to write type bss mapping offset to " << out->GetLocation();
4271    return false;
4272  }
4273  oat_writer->size_oat_dex_file_type_bss_mapping_offset_ += sizeof(type_bss_mapping_offset_);
4274
4275  if (!out->WriteFully(&string_bss_mapping_offset_, sizeof(string_bss_mapping_offset_))) {
4276    PLOG(ERROR) << "Failed to write string bss mapping offset to " << out->GetLocation();
4277    return false;
4278  }
4279  oat_writer->size_oat_dex_file_string_bss_mapping_offset_ += sizeof(string_bss_mapping_offset_);
4280
4281  return true;
4282}
4283
4284bool OatWriter::OatDexFile::WriteClassOffsets(OatWriter* oat_writer, OutputStream* out) {
4285  if (!out->WriteFully(class_offsets_.data(), GetClassOffsetsRawSize())) {
4286    PLOG(ERROR) << "Failed to write oat class offsets for " << GetLocation()
4287                << " to " << out->GetLocation();
4288    return false;
4289  }
4290  oat_writer->size_oat_class_offsets_ += GetClassOffsetsRawSize();
4291  return true;
4292}
4293
4294OatWriter::OatClass::OatClass(const dchecked_vector<CompiledMethod*>& compiled_methods,
4295                              uint32_t compiled_methods_with_code,
4296                              uint16_t oat_class_type)
4297    : compiled_methods_(compiled_methods) {
4298  const uint32_t num_methods = compiled_methods.size();
4299  CHECK_LE(compiled_methods_with_code, num_methods);
4300
4301  oat_method_offsets_offsets_from_oat_class_.resize(num_methods);
4302
4303  method_offsets_.resize(compiled_methods_with_code);
4304  method_headers_.resize(compiled_methods_with_code);
4305
4306  uint32_t oat_method_offsets_offset_from_oat_class = OatClassHeader::SizeOf();
4307  // We only create this instance if there are at least some compiled.
4308  if (oat_class_type == kOatClassSomeCompiled) {
4309    method_bitmap_.reset(new BitVector(num_methods, false, Allocator::GetMallocAllocator()));
4310    method_bitmap_size_ = method_bitmap_->GetSizeOf();
4311    oat_method_offsets_offset_from_oat_class += sizeof(method_bitmap_size_);
4312    oat_method_offsets_offset_from_oat_class += method_bitmap_size_;
4313  } else {
4314    method_bitmap_ = nullptr;
4315    method_bitmap_size_ = 0;
4316  }
4317
4318  for (size_t i = 0; i < num_methods; i++) {
4319    CompiledMethod* compiled_method = compiled_methods_[i];
4320    if (HasCompiledCode(compiled_method)) {
4321      oat_method_offsets_offsets_from_oat_class_[i] = oat_method_offsets_offset_from_oat_class;
4322      oat_method_offsets_offset_from_oat_class += sizeof(OatMethodOffsets);
4323      if (oat_class_type == kOatClassSomeCompiled) {
4324        method_bitmap_->SetBit(i);
4325      }
4326    } else {
4327      oat_method_offsets_offsets_from_oat_class_[i] = 0;
4328    }
4329  }
4330}
4331
4332size_t OatWriter::OatClass::SizeOf() const {
4333  return ((method_bitmap_size_ == 0) ? 0 : sizeof(method_bitmap_size_))
4334          + method_bitmap_size_
4335          + (sizeof(method_offsets_[0]) * method_offsets_.size());
4336}
4337
4338bool OatWriter::OatClassHeader::Write(OatWriter* oat_writer,
4339                                      OutputStream* out,
4340                                      const size_t file_offset) const {
4341  DCHECK_OFFSET_();
4342  if (!out->WriteFully(&status_, sizeof(status_))) {
4343    PLOG(ERROR) << "Failed to write class status to " << out->GetLocation();
4344    return false;
4345  }
4346  oat_writer->size_oat_class_status_ += sizeof(status_);
4347
4348  if (!out->WriteFully(&type_, sizeof(type_))) {
4349    PLOG(ERROR) << "Failed to write oat class type to " << out->GetLocation();
4350    return false;
4351  }
4352  oat_writer->size_oat_class_type_ += sizeof(type_);
4353  return true;
4354}
4355
4356bool OatWriter::OatClass::Write(OatWriter* oat_writer, OutputStream* out) const {
4357  if (method_bitmap_size_ != 0) {
4358    if (!out->WriteFully(&method_bitmap_size_, sizeof(method_bitmap_size_))) {
4359      PLOG(ERROR) << "Failed to write method bitmap size to " << out->GetLocation();
4360      return false;
4361    }
4362    oat_writer->size_oat_class_method_bitmaps_ += sizeof(method_bitmap_size_);
4363
4364    if (!out->WriteFully(method_bitmap_->GetRawStorage(), method_bitmap_size_)) {
4365      PLOG(ERROR) << "Failed to write method bitmap to " << out->GetLocation();
4366      return false;
4367    }
4368    oat_writer->size_oat_class_method_bitmaps_ += method_bitmap_size_;
4369  }
4370
4371  if (!out->WriteFully(method_offsets_.data(), GetMethodOffsetsRawSize())) {
4372    PLOG(ERROR) << "Failed to write method offsets to " << out->GetLocation();
4373    return false;
4374  }
4375  oat_writer->size_oat_class_method_offsets_ += GetMethodOffsetsRawSize();
4376  return true;
4377}
4378
4379const uint8_t* OatWriter::LookupBootImageInternTableSlot(const DexFile& dex_file,
4380                                                         dex::StringIndex string_idx)
4381    NO_THREAD_SAFETY_ANALYSIS {  // Single-threaded OatWriter can avoid locking.
4382  uint32_t utf16_length;
4383  const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
4384  DCHECK_EQ(utf16_length, CountModifiedUtf8Chars(utf8_data));
4385  InternTable::Utf8String string(utf16_length,
4386                                 utf8_data,
4387                                 ComputeUtf16HashFromModifiedUtf8(utf8_data, utf16_length));
4388  const InternTable* intern_table = Runtime::Current()->GetClassLinker()->intern_table_;
4389  for (const InternTable::Table::UnorderedSet& table : intern_table->strong_interns_.tables_) {
4390    auto it = table.Find(string);
4391    if (it != table.end()) {
4392      return reinterpret_cast<const uint8_t*>(std::addressof(*it));
4393    }
4394  }
4395  LOG(FATAL) << "Did not find boot image string " << utf8_data;
4396  UNREACHABLE();
4397}
4398
4399const uint8_t* OatWriter::LookupBootImageClassTableSlot(const DexFile& dex_file,
4400                                                        dex::TypeIndex type_idx)
4401    NO_THREAD_SAFETY_ANALYSIS {  // Single-threaded OatWriter can avoid locking.
4402  const char* descriptor = dex_file.StringByTypeIdx(type_idx);
4403  ClassTable::DescriptorHashPair pair(descriptor, ComputeModifiedUtf8Hash(descriptor));
4404  ClassTable* table = Runtime::Current()->GetClassLinker()->boot_class_table_.get();
4405  for (const ClassTable::ClassSet& class_set : table->classes_) {
4406    auto it = class_set.Find(pair);
4407    if (it != class_set.end()) {
4408      return reinterpret_cast<const uint8_t*>(std::addressof(*it));
4409    }
4410  }
4411  LOG(FATAL) << "Did not find boot image class " << descriptor;
4412  UNREACHABLE();
4413}
4414
4415debug::DebugInfo OatWriter::GetDebugInfo() const {
4416  debug::DebugInfo debug_info{};
4417  debug_info.compiled_methods = ArrayRef<const debug::MethodDebugInfo>(method_info_);
4418  if (VdexWillContainDexFiles()) {
4419    DCHECK_EQ(dex_files_->size(), oat_dex_files_.size());
4420    for (size_t i = 0, size = dex_files_->size(); i != size; ++i) {
4421      const DexFile* dex_file = (*dex_files_)[i];
4422      const OatDexFile& oat_dex_file = oat_dex_files_[i];
4423      uint32_t dex_file_offset = oat_dex_file.dex_file_offset_;
4424      if (dex_file_offset != 0) {
4425        debug_info.dex_files.emplace(dex_file_offset, dex_file);
4426      }
4427    }
4428  }
4429  return debug_info;
4430}
4431
4432}  // namespace linker
4433}  // namespace art
4434