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