Home | History | Annotate | Download | only in compiler
      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 "android-base/stringprintf.h"
     18 
     19 #include "arch/instruction_set_features.h"
     20 #include "art_method-inl.h"
     21 #include "base/enums.h"
     22 #include "base/unix_file/fd_file.h"
     23 #include "class_linker.h"
     24 #include "common_compiler_test.h"
     25 #include "compiled_method.h"
     26 #include "compiler.h"
     27 #include "debug/method_debug_info.h"
     28 #include "dex/quick_compiler_callbacks.h"
     29 #include "dex/verification_results.h"
     30 #include "driver/compiler_driver.h"
     31 #include "driver/compiler_options.h"
     32 #include "elf_writer.h"
     33 #include "elf_writer_quick.h"
     34 #include "entrypoints/quick/quick_entrypoints.h"
     35 #include "linker/buffered_output_stream.h"
     36 #include "linker/file_output_stream.h"
     37 #include "linker/multi_oat_relative_patcher.h"
     38 #include "linker/vector_output_stream.h"
     39 #include "mirror/class-inl.h"
     40 #include "mirror/object-inl.h"
     41 #include "mirror/object_array-inl.h"
     42 #include "oat_file-inl.h"
     43 #include "oat_writer.h"
     44 #include "scoped_thread_state_change-inl.h"
     45 #include "utils/test_dex_file_builder.h"
     46 
     47 namespace art {
     48 
     49 NO_RETURN static void Usage(const char* fmt, ...) {
     50   va_list ap;
     51   va_start(ap, fmt);
     52   std::string error;
     53   android::base::StringAppendV(&error, fmt, ap);
     54   LOG(FATAL) << error;
     55   va_end(ap);
     56   UNREACHABLE();
     57 }
     58 
     59 class OatTest : public CommonCompilerTest {
     60  protected:
     61   static const bool kCompile = false;  // DISABLED_ due to the time to compile libcore
     62 
     63   void CheckMethod(ArtMethod* method,
     64                    const OatFile::OatMethod& oat_method,
     65                    const DexFile& dex_file)
     66       REQUIRES_SHARED(Locks::mutator_lock_) {
     67     const CompiledMethod* compiled_method =
     68         compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
     69                                                             method->GetDexMethodIndex()));
     70 
     71     if (compiled_method == nullptr) {
     72       EXPECT_TRUE(oat_method.GetQuickCode() == nullptr) << method->PrettyMethod() << " "
     73                                                         << oat_method.GetQuickCode();
     74       EXPECT_EQ(oat_method.GetFrameSizeInBytes(), 0U);
     75       EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
     76       EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
     77     } else {
     78       const void* quick_oat_code = oat_method.GetQuickCode();
     79       EXPECT_TRUE(quick_oat_code != nullptr) << method->PrettyMethod();
     80       EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
     81       EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
     82       EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
     83       uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(quick_oat_code), 2);
     84       quick_oat_code = reinterpret_cast<const void*>(oat_code_aligned);
     85       ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode();
     86       EXPECT_FALSE(quick_code.empty());
     87       size_t code_size = quick_code.size() * sizeof(quick_code[0]);
     88       EXPECT_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size))
     89           << method->PrettyMethod() << " " << code_size;
     90       CHECK_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size));
     91     }
     92   }
     93 
     94   void SetupCompiler(Compiler::Kind compiler_kind,
     95                      InstructionSet insn_set,
     96                      const std::vector<std::string>& compiler_options,
     97                      /*out*/std::string* error_msg) {
     98     ASSERT_TRUE(error_msg != nullptr);
     99     insn_features_ = InstructionSetFeatures::FromVariant(insn_set, "default", error_msg);
    100     ASSERT_TRUE(insn_features_ != nullptr) << error_msg;
    101     compiler_options_.reset(new CompilerOptions);
    102     for (const std::string& option : compiler_options) {
    103       compiler_options_->ParseCompilerOption(option, Usage);
    104     }
    105     verification_results_.reset(new VerificationResults(compiler_options_.get()));
    106     callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(),
    107                                                 CompilerCallbacks::CallbackMode::kCompileApp));
    108     Runtime::Current()->SetCompilerCallbacks(callbacks_.get());
    109     timer_.reset(new CumulativeLogger("Compilation times"));
    110     compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
    111                                               verification_results_.get(),
    112                                               compiler_kind,
    113                                               insn_set,
    114                                               insn_features_.get(),
    115                                               /* image_classes */ nullptr,
    116                                               /* compiled_classes */ nullptr,
    117                                               /* compiled_methods */ nullptr,
    118                                               /* thread_count */ 2,
    119                                               /* dump_stats */ true,
    120                                               /* dump_passes */ true,
    121                                               timer_.get(),
    122                                               /* swap_fd */ -1,
    123                                               /* profile_compilation_info */ nullptr));
    124   }
    125 
    126   bool WriteElf(File* vdex_file,
    127                 File* oat_file,
    128                 const std::vector<const DexFile*>& dex_files,
    129                 SafeMap<std::string, std::string>& key_value_store,
    130                 bool verify) {
    131     TimingLogger timings("WriteElf", false, false);
    132     OatWriter oat_writer(/*compiling_boot_image*/false,
    133                          &timings,
    134                          /*profile_compilation_info*/nullptr);
    135     for (const DexFile* dex_file : dex_files) {
    136       ArrayRef<const uint8_t> raw_dex_file(
    137           reinterpret_cast<const uint8_t*>(&dex_file->GetHeader()),
    138           dex_file->GetHeader().file_size_);
    139       if (!oat_writer.AddRawDexFileSource(raw_dex_file,
    140                                           dex_file->GetLocation().c_str(),
    141                                           dex_file->GetLocationChecksum())) {
    142         return false;
    143       }
    144     }
    145     return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify);
    146   }
    147 
    148   bool WriteElf(File* vdex_file,
    149                 File* oat_file,
    150                 const std::vector<const char*>& dex_filenames,
    151                 SafeMap<std::string, std::string>& key_value_store,
    152                 bool verify,
    153                 ProfileCompilationInfo* profile_compilation_info) {
    154     TimingLogger timings("WriteElf", false, false);
    155     OatWriter oat_writer(/*compiling_boot_image*/false, &timings, profile_compilation_info);
    156     for (const char* dex_filename : dex_filenames) {
    157       if (!oat_writer.AddDexFileSource(dex_filename, dex_filename)) {
    158         return false;
    159       }
    160     }
    161     return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify);
    162   }
    163 
    164   bool WriteElf(File* vdex_file,
    165                 File* oat_file,
    166                 File&& zip_fd,
    167                 const char* location,
    168                 SafeMap<std::string, std::string>& key_value_store,
    169                 bool verify) {
    170     TimingLogger timings("WriteElf", false, false);
    171     OatWriter oat_writer(/*compiling_boot_image*/false,
    172                          &timings,
    173                          /*profile_compilation_info*/nullptr);
    174     if (!oat_writer.AddZippedDexFilesSource(std::move(zip_fd), location)) {
    175       return false;
    176     }
    177     return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify);
    178   }
    179 
    180   bool DoWriteElf(File* vdex_file,
    181                   File* oat_file,
    182                   OatWriter& oat_writer,
    183                   SafeMap<std::string, std::string>& key_value_store,
    184                   bool verify) {
    185     std::unique_ptr<ElfWriter> elf_writer = CreateElfWriterQuick(
    186         compiler_driver_->GetInstructionSet(),
    187         compiler_driver_->GetInstructionSetFeatures(),
    188         &compiler_driver_->GetCompilerOptions(),
    189         oat_file);
    190     elf_writer->Start();
    191     OutputStream* oat_rodata = elf_writer->StartRoData();
    192     std::unique_ptr<MemMap> opened_dex_files_map;
    193     std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
    194     if (!oat_writer.WriteAndOpenDexFiles(kIsVdexEnabled ? vdex_file : oat_file,
    195                                          oat_rodata,
    196                                          compiler_driver_->GetInstructionSet(),
    197                                          compiler_driver_->GetInstructionSetFeatures(),
    198                                          &key_value_store,
    199                                          verify,
    200                                          /* update_input_vdex */ false,
    201                                          &opened_dex_files_map,
    202                                          &opened_dex_files)) {
    203       return false;
    204     }
    205 
    206     Runtime* runtime = Runtime::Current();
    207     ClassLinker* const class_linker = runtime->GetClassLinker();
    208     std::vector<const DexFile*> dex_files;
    209     for (const std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
    210       dex_files.push_back(dex_file.get());
    211       ScopedObjectAccess soa(Thread::Current());
    212       class_linker->RegisterDexFile(*dex_file, nullptr);
    213     }
    214     linker::MultiOatRelativePatcher patcher(compiler_driver_->GetInstructionSet(),
    215                                             instruction_set_features_.get());
    216     oat_writer.Initialize(compiler_driver_.get(), nullptr, dex_files);
    217     oat_writer.PrepareLayout(&patcher);
    218     size_t rodata_size = oat_writer.GetOatHeader().GetExecutableOffset();
    219     size_t text_size = oat_writer.GetOatSize() - rodata_size;
    220     elf_writer->PrepareDynamicSection(rodata_size,
    221                                       text_size,
    222                                       oat_writer.GetBssSize(),
    223                                       oat_writer.GetBssRootsOffset());
    224 
    225     if (kIsVdexEnabled) {
    226       std::unique_ptr<BufferedOutputStream> vdex_out(
    227             MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(vdex_file)));
    228       if (!oat_writer.WriteVerifierDeps(vdex_out.get(), nullptr)) {
    229         return false;
    230       }
    231       if (!oat_writer.WriteChecksumsAndVdexHeader(vdex_out.get())) {
    232         return false;
    233       }
    234     }
    235 
    236     if (!oat_writer.WriteRodata(oat_rodata)) {
    237       return false;
    238     }
    239     elf_writer->EndRoData(oat_rodata);
    240 
    241     OutputStream* text = elf_writer->StartText();
    242     if (!oat_writer.WriteCode(text)) {
    243       return false;
    244     }
    245     elf_writer->EndText(text);
    246 
    247     if (!oat_writer.WriteHeader(elf_writer->GetStream(), 42U, 4096U, 0)) {
    248       return false;
    249     }
    250 
    251     elf_writer->WriteDynamicSection();
    252     elf_writer->WriteDebugInfo(oat_writer.GetMethodDebugInfo());
    253 
    254     if (!elf_writer->End()) {
    255       return false;
    256     }
    257 
    258     opened_dex_files_maps_.emplace_back(std::move(opened_dex_files_map));
    259     for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
    260       opened_dex_files_.emplace_back(dex_file.release());
    261     }
    262     return true;
    263   }
    264 
    265   void TestDexFileInput(bool verify, bool low_4gb, bool use_profile);
    266   void TestZipFileInput(bool verify);
    267   void TestZipFileInputWithEmptyDex();
    268 
    269   std::unique_ptr<const InstructionSetFeatures> insn_features_;
    270   std::unique_ptr<QuickCompilerCallbacks> callbacks_;
    271 
    272   std::vector<std::unique_ptr<MemMap>> opened_dex_files_maps_;
    273   std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
    274 };
    275 
    276 class ZipBuilder {
    277  public:
    278   explicit ZipBuilder(File* zip_file) : zip_file_(zip_file) { }
    279 
    280   bool AddFile(const char* location, const void* data, size_t size) {
    281     off_t offset = lseek(zip_file_->Fd(), 0, SEEK_CUR);
    282     if (offset == static_cast<off_t>(-1)) {
    283       return false;
    284     }
    285 
    286     ZipFileHeader file_header;
    287     file_header.crc32 = crc32(0u, reinterpret_cast<const Bytef*>(data), size);
    288     file_header.compressed_size = size;
    289     file_header.uncompressed_size = size;
    290     file_header.filename_length = strlen(location);
    291 
    292     if (!zip_file_->WriteFully(&file_header, sizeof(file_header)) ||
    293         !zip_file_->WriteFully(location, file_header.filename_length) ||
    294         !zip_file_->WriteFully(data, size)) {
    295       return false;
    296     }
    297 
    298     CentralDirectoryFileHeader cdfh;
    299     cdfh.crc32 = file_header.crc32;
    300     cdfh.compressed_size = size;
    301     cdfh.uncompressed_size = size;
    302     cdfh.filename_length = file_header.filename_length;
    303     cdfh.relative_offset_of_local_file_header = offset;
    304     file_data_.push_back(FileData { cdfh, location });
    305     return true;
    306   }
    307 
    308   bool Finish() {
    309     off_t offset = lseek(zip_file_->Fd(), 0, SEEK_CUR);
    310     if (offset == static_cast<off_t>(-1)) {
    311       return false;
    312     }
    313 
    314     size_t central_directory_size = 0u;
    315     for (const FileData& file_data : file_data_) {
    316       if (!zip_file_->WriteFully(&file_data.cdfh, sizeof(file_data.cdfh)) ||
    317           !zip_file_->WriteFully(file_data.location, file_data.cdfh.filename_length)) {
    318         return false;
    319       }
    320       central_directory_size += sizeof(file_data.cdfh) + file_data.cdfh.filename_length;
    321     }
    322     EndOfCentralDirectoryRecord eocd_record;
    323     eocd_record.number_of_central_directory_records_on_this_disk = file_data_.size();
    324     eocd_record.total_number_of_central_directory_records = file_data_.size();
    325     eocd_record.size_of_central_directory = central_directory_size;
    326     eocd_record.offset_of_start_of_central_directory = offset;
    327     return
    328         zip_file_->WriteFully(&eocd_record, sizeof(eocd_record)) &&
    329         zip_file_->Flush() == 0;
    330   }
    331 
    332  private:
    333   struct PACKED(1) ZipFileHeader {
    334     uint32_t signature = 0x04034b50;
    335     uint16_t version_needed_to_extract = 10;
    336     uint16_t general_purpose_bit_flag = 0;
    337     uint16_t compression_method = 0;            // 0 = store only.
    338     uint16_t file_last_modification_time = 0u;
    339     uint16_t file_last_modification_date = 0u;
    340     uint32_t crc32;
    341     uint32_t compressed_size;
    342     uint32_t uncompressed_size;
    343     uint16_t filename_length;
    344     uint16_t extra_field_length = 0u;           // No extra fields.
    345   };
    346 
    347   struct PACKED(1) CentralDirectoryFileHeader {
    348     uint32_t signature = 0x02014b50;
    349     uint16_t version_made_by = 10;
    350     uint16_t version_needed_to_extract = 10;
    351     uint16_t general_purpose_bit_flag = 0;
    352     uint16_t compression_method = 0;            // 0 = store only.
    353     uint16_t file_last_modification_time = 0u;
    354     uint16_t file_last_modification_date = 0u;
    355     uint32_t crc32;
    356     uint32_t compressed_size;
    357     uint32_t uncompressed_size;
    358     uint16_t filename_length;
    359     uint16_t extra_field_length = 0u;           // No extra fields.
    360     uint16_t file_comment_length = 0u;          // No file comment.
    361     uint16_t disk_number_where_file_starts = 0u;
    362     uint16_t internal_file_attributes = 0u;
    363     uint32_t external_file_attributes = 0u;
    364     uint32_t relative_offset_of_local_file_header;
    365   };
    366 
    367   struct PACKED(1) EndOfCentralDirectoryRecord {
    368     uint32_t signature = 0x06054b50;
    369     uint16_t number_of_this_disk = 0u;
    370     uint16_t disk_where_central_directory_starts = 0u;
    371     uint16_t number_of_central_directory_records_on_this_disk;
    372     uint16_t total_number_of_central_directory_records;
    373     uint32_t size_of_central_directory;
    374     uint32_t offset_of_start_of_central_directory;
    375     uint16_t comment_length = 0u;               // No file comment.
    376   };
    377 
    378   struct FileData {
    379     CentralDirectoryFileHeader cdfh;
    380     const char* location;
    381   };
    382 
    383   File* zip_file_;
    384   std::vector<FileData> file_data_;
    385 };
    386 
    387 TEST_F(OatTest, WriteRead) {
    388   TimingLogger timings("OatTest::WriteRead", false, false);
    389   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    390 
    391   // TODO: make selectable.
    392   Compiler::Kind compiler_kind = Compiler::kQuick;
    393   InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86;
    394   std::string error_msg;
    395   SetupCompiler(compiler_kind, insn_set, std::vector<std::string>(), /*out*/ &error_msg);
    396 
    397   jobject class_loader = nullptr;
    398   if (kCompile) {
    399     TimingLogger timings2("OatTest::WriteRead", false, false);
    400     compiler_driver_->SetDexFilesForOatFile(class_linker->GetBootClassPath());
    401     compiler_driver_->CompileAll(
    402         class_loader, class_linker->GetBootClassPath(), /* verifier_deps */ nullptr, &timings2);
    403   }
    404 
    405   ScratchFile tmp_oat, tmp_vdex(tmp_oat, ".vdex");
    406   SafeMap<std::string, std::string> key_value_store;
    407   key_value_store.Put(OatHeader::kImageLocationKey, "lue.art");
    408   bool success = WriteElf(tmp_vdex.GetFile(),
    409                           tmp_oat.GetFile(),
    410                           class_linker->GetBootClassPath(),
    411                           key_value_store,
    412                           false);
    413   ASSERT_TRUE(success);
    414 
    415   if (kCompile) {  // OatWriter strips the code, regenerate to compare
    416     compiler_driver_->CompileAll(
    417         class_loader, class_linker->GetBootClassPath(), /* verifier_deps */ nullptr, &timings);
    418   }
    419   std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp_oat.GetFilename(),
    420                                                   tmp_oat.GetFilename(),
    421                                                   nullptr,
    422                                                   nullptr,
    423                                                   false,
    424                                                   /*low_4gb*/true,
    425                                                   nullptr,
    426                                                   &error_msg));
    427   ASSERT_TRUE(oat_file.get() != nullptr) << error_msg;
    428   const OatHeader& oat_header = oat_file->GetOatHeader();
    429   ASSERT_TRUE(oat_header.IsValid());
    430   ASSERT_EQ(class_linker->GetBootClassPath().size(), oat_header.GetDexFileCount());  // core
    431   ASSERT_EQ(42U, oat_header.GetImageFileLocationOatChecksum());
    432   ASSERT_EQ(4096U, oat_header.GetImageFileLocationOatDataBegin());
    433   ASSERT_EQ("lue.art", std::string(oat_header.GetStoreValueByKey(OatHeader::kImageLocationKey)));
    434 
    435   ASSERT_TRUE(java_lang_dex_file_ != nullptr);
    436   const DexFile& dex_file = *java_lang_dex_file_;
    437   uint32_t dex_file_checksum = dex_file.GetLocationChecksum();
    438   const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation().c_str(),
    439                                                                     &dex_file_checksum);
    440   ASSERT_TRUE(oat_dex_file != nullptr);
    441   CHECK_EQ(dex_file.GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
    442   ScopedObjectAccess soa(Thread::Current());
    443   auto pointer_size = class_linker->GetImagePointerSize();
    444   for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
    445     const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
    446     const uint8_t* class_data = dex_file.GetClassData(class_def);
    447 
    448     size_t num_virtual_methods = 0;
    449     if (class_data != nullptr) {
    450       ClassDataItemIterator it(dex_file, class_data);
    451       num_virtual_methods = it.NumVirtualMethods();
    452     }
    453 
    454     const char* descriptor = dex_file.GetClassDescriptor(class_def);
    455     mirror::Class* klass = class_linker->FindClass(soa.Self(),
    456                                                    descriptor,
    457                                                    ScopedNullHandle<mirror::ClassLoader>());
    458 
    459     const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(i);
    460     CHECK_EQ(mirror::Class::Status::kStatusNotReady, oat_class.GetStatus()) << descriptor;
    461     CHECK_EQ(kCompile ? OatClassType::kOatClassAllCompiled : OatClassType::kOatClassNoneCompiled,
    462              oat_class.GetType()) << descriptor;
    463 
    464     size_t method_index = 0;
    465     for (auto& m : klass->GetDirectMethods(pointer_size)) {
    466       CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file);
    467       ++method_index;
    468     }
    469     size_t visited_virtuals = 0;
    470     // TODO We should also check copied methods in this test.
    471     for (auto& m : klass->GetDeclaredVirtualMethods(pointer_size)) {
    472       if (!klass->IsInterface()) {
    473         EXPECT_FALSE(m.IsCopied());
    474       }
    475       CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file);
    476       ++method_index;
    477       ++visited_virtuals;
    478     }
    479     EXPECT_EQ(visited_virtuals, num_virtual_methods);
    480   }
    481 }
    482 
    483 TEST_F(OatTest, OatHeaderSizeCheck) {
    484   // If this test is failing and you have to update these constants,
    485   // it is time to update OatHeader::kOatVersion
    486   EXPECT_EQ(72U, sizeof(OatHeader));
    487   EXPECT_EQ(4U, sizeof(OatMethodOffsets));
    488   EXPECT_EQ(24U, sizeof(OatQuickMethodHeader));
    489   EXPECT_EQ(161 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)),
    490             sizeof(QuickEntryPoints));
    491 }
    492 
    493 TEST_F(OatTest, OatHeaderIsValid) {
    494   InstructionSet insn_set = kX86;
    495   std::string error_msg;
    496   std::unique_ptr<const InstructionSetFeatures> insn_features(
    497     InstructionSetFeatures::FromVariant(insn_set, "default", &error_msg));
    498   ASSERT_TRUE(insn_features.get() != nullptr) << error_msg;
    499   std::unique_ptr<OatHeader> oat_header(OatHeader::Create(insn_set,
    500                                                           insn_features.get(),
    501                                                           0u,
    502                                                           nullptr));
    503   ASSERT_NE(oat_header.get(), nullptr);
    504   ASSERT_TRUE(oat_header->IsValid());
    505 
    506   char* magic = const_cast<char*>(oat_header->GetMagic());
    507   strcpy(magic, "");  // bad magic
    508   ASSERT_FALSE(oat_header->IsValid());
    509   strcpy(magic, "oat\n000");  // bad version
    510   ASSERT_FALSE(oat_header->IsValid());
    511 }
    512 
    513 TEST_F(OatTest, EmptyTextSection) {
    514   TimingLogger timings("OatTest::EmptyTextSection", false, false);
    515 
    516   // TODO: make selectable.
    517   Compiler::Kind compiler_kind = Compiler::kQuick;
    518   InstructionSet insn_set = kRuntimeISA;
    519   if (insn_set == kArm) insn_set = kThumb2;
    520   std::string error_msg;
    521   std::vector<std::string> compiler_options;
    522   compiler_options.push_back("--compiler-filter=extract");
    523   SetupCompiler(compiler_kind, insn_set, compiler_options, /*out*/ &error_msg);
    524 
    525   jobject class_loader;
    526   {
    527     ScopedObjectAccess soa(Thread::Current());
    528     class_loader = LoadDex("Main");
    529   }
    530   ASSERT_TRUE(class_loader != nullptr);
    531   std::vector<const DexFile*> dex_files = GetDexFiles(class_loader);
    532   ASSERT_TRUE(!dex_files.empty());
    533 
    534   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
    535   for (const DexFile* dex_file : dex_files) {
    536     ScopedObjectAccess soa(Thread::Current());
    537     class_linker->RegisterDexFile(*dex_file,
    538                                   soa.Decode<mirror::ClassLoader>(class_loader).Ptr());
    539   }
    540   compiler_driver_->SetDexFilesForOatFile(dex_files);
    541   compiler_driver_->CompileAll(class_loader, dex_files, /* verifier_deps */ nullptr, &timings);
    542 
    543   ScratchFile tmp_oat, tmp_vdex(tmp_oat, ".vdex");
    544   SafeMap<std::string, std::string> key_value_store;
    545   key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
    546   bool success = WriteElf(tmp_vdex.GetFile(), tmp_oat.GetFile(), dex_files, key_value_store, false);
    547   ASSERT_TRUE(success);
    548 
    549   std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp_oat.GetFilename(),
    550                                                   tmp_oat.GetFilename(),
    551                                                   nullptr,
    552                                                   nullptr,
    553                                                   false,
    554                                                   /*low_4gb*/false,
    555                                                   nullptr,
    556                                                   &error_msg));
    557   ASSERT_TRUE(oat_file != nullptr);
    558   EXPECT_LT(static_cast<size_t>(oat_file->Size()),
    559             static_cast<size_t>(tmp_oat.GetFile()->GetLength()));
    560 }
    561 
    562 static void MaybeModifyDexFileToFail(bool verify, std::unique_ptr<const DexFile>& data) {
    563   // If in verify mode (= fail the verifier mode), make sure we fail early. We'll fail already
    564   // because of the missing map, but that may lead to out of bounds reads.
    565   if (verify) {
    566     const_cast<DexFile::Header*>(&data->GetHeader())->checksum_++;
    567   }
    568 }
    569 
    570 void OatTest::TestDexFileInput(bool verify, bool low_4gb, bool use_profile) {
    571   TimingLogger timings("OatTest::DexFileInput", false, false);
    572 
    573   std::vector<const char*> input_filenames;
    574 
    575   ScratchFile dex_file1;
    576   TestDexFileBuilder builder1;
    577   builder1.AddField("Lsome.TestClass;", "int", "someField");
    578   builder1.AddMethod("Lsome.TestClass;", "()I", "foo");
    579   std::unique_ptr<const DexFile> dex_file1_data = builder1.Build(dex_file1.GetFilename());
    580 
    581   MaybeModifyDexFileToFail(verify, dex_file1_data);
    582 
    583   bool success = dex_file1.GetFile()->WriteFully(&dex_file1_data->GetHeader(),
    584                                                  dex_file1_data->GetHeader().file_size_);
    585   ASSERT_TRUE(success);
    586   success = dex_file1.GetFile()->Flush() == 0;
    587   ASSERT_TRUE(success);
    588   input_filenames.push_back(dex_file1.GetFilename().c_str());
    589 
    590   ScratchFile dex_file2;
    591   TestDexFileBuilder builder2;
    592   builder2.AddField("Land.AnotherTestClass;", "boolean", "someOtherField");
    593   builder2.AddMethod("Land.AnotherTestClass;", "()J", "bar");
    594   std::unique_ptr<const DexFile> dex_file2_data = builder2.Build(dex_file2.GetFilename());
    595 
    596   MaybeModifyDexFileToFail(verify, dex_file2_data);
    597 
    598   success = dex_file2.GetFile()->WriteFully(&dex_file2_data->GetHeader(),
    599                                             dex_file2_data->GetHeader().file_size_);
    600   ASSERT_TRUE(success);
    601   success = dex_file2.GetFile()->Flush() == 0;
    602   ASSERT_TRUE(success);
    603   input_filenames.push_back(dex_file2.GetFilename().c_str());
    604 
    605   ScratchFile oat_file, vdex_file(oat_file, ".vdex");
    606   SafeMap<std::string, std::string> key_value_store;
    607   key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
    608   std::unique_ptr<ProfileCompilationInfo>
    609       profile_compilation_info(use_profile ? new ProfileCompilationInfo() : nullptr);
    610   success = WriteElf(vdex_file.GetFile(),
    611                      oat_file.GetFile(),
    612                      input_filenames,
    613                      key_value_store,
    614                      verify,
    615                      profile_compilation_info.get());
    616 
    617   // In verify mode, we expect failure.
    618   if (verify) {
    619     ASSERT_FALSE(success);
    620     return;
    621   }
    622 
    623   ASSERT_TRUE(success);
    624 
    625   std::string error_msg;
    626   std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(oat_file.GetFilename(),
    627                                                          oat_file.GetFilename(),
    628                                                          nullptr,
    629                                                          nullptr,
    630                                                          false,
    631                                                          low_4gb,
    632                                                          nullptr,
    633                                                          &error_msg));
    634   if (low_4gb) {
    635     uintptr_t begin = reinterpret_cast<uintptr_t>(opened_oat_file->Begin());
    636     EXPECT_EQ(begin, static_cast<uint32_t>(begin));
    637   }
    638   ASSERT_TRUE(opened_oat_file != nullptr);
    639   ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size());
    640   std::unique_ptr<const DexFile> opened_dex_file1 =
    641       opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg);
    642   std::unique_ptr<const DexFile> opened_dex_file2 =
    643       opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg);
    644 
    645   ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_);
    646   ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(),
    647                       &opened_dex_file1->GetHeader(),
    648                       dex_file1_data->GetHeader().file_size_));
    649   ASSERT_EQ(dex_file1_data->GetLocation(), opened_dex_file1->GetLocation());
    650 
    651   ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_);
    652   ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(),
    653                       &opened_dex_file2->GetHeader(),
    654                       dex_file2_data->GetHeader().file_size_));
    655   ASSERT_EQ(dex_file2_data->GetLocation(), opened_dex_file2->GetLocation());
    656 }
    657 
    658 TEST_F(OatTest, DexFileInputCheckOutput) {
    659   TestDexFileInput(/*verify*/false, /*low_4gb*/false, /*use_profile*/false);
    660 }
    661 
    662 TEST_F(OatTest, DexFileInputCheckOutputLow4GB) {
    663   TestDexFileInput(/*verify*/false, /*low_4gb*/true, /*use_profile*/false);
    664 }
    665 
    666 TEST_F(OatTest, DexFileInputCheckVerifier) {
    667   TestDexFileInput(/*verify*/true, /*low_4gb*/false, /*use_profile*/false);
    668 }
    669 
    670 TEST_F(OatTest, DexFileFailsVerifierWithLayout) {
    671   TestDexFileInput(/*verify*/true, /*low_4gb*/false, /*use_profile*/true);
    672 }
    673 
    674 void OatTest::TestZipFileInput(bool verify) {
    675   TimingLogger timings("OatTest::DexFileInput", false, false);
    676 
    677   ScratchFile zip_file;
    678   ZipBuilder zip_builder(zip_file.GetFile());
    679 
    680   ScratchFile dex_file1;
    681   TestDexFileBuilder builder1;
    682   builder1.AddField("Lsome.TestClass;", "long", "someField");
    683   builder1.AddMethod("Lsome.TestClass;", "()D", "foo");
    684   std::unique_ptr<const DexFile> dex_file1_data = builder1.Build(dex_file1.GetFilename());
    685 
    686   MaybeModifyDexFileToFail(verify, dex_file1_data);
    687 
    688   bool success = dex_file1.GetFile()->WriteFully(&dex_file1_data->GetHeader(),
    689                                                  dex_file1_data->GetHeader().file_size_);
    690   ASSERT_TRUE(success);
    691   success = dex_file1.GetFile()->Flush() == 0;
    692   ASSERT_TRUE(success);
    693   success = zip_builder.AddFile("classes.dex",
    694                                 &dex_file1_data->GetHeader(),
    695                                 dex_file1_data->GetHeader().file_size_);
    696   ASSERT_TRUE(success);
    697 
    698   ScratchFile dex_file2;
    699   TestDexFileBuilder builder2;
    700   builder2.AddField("Land.AnotherTestClass;", "boolean", "someOtherField");
    701   builder2.AddMethod("Land.AnotherTestClass;", "()J", "bar");
    702   std::unique_ptr<const DexFile> dex_file2_data = builder2.Build(dex_file2.GetFilename());
    703 
    704   MaybeModifyDexFileToFail(verify, dex_file2_data);
    705 
    706   success = dex_file2.GetFile()->WriteFully(&dex_file2_data->GetHeader(),
    707                                             dex_file2_data->GetHeader().file_size_);
    708   ASSERT_TRUE(success);
    709   success = dex_file2.GetFile()->Flush() == 0;
    710   ASSERT_TRUE(success);
    711   success = zip_builder.AddFile("classes2.dex",
    712                                 &dex_file2_data->GetHeader(),
    713                                 dex_file2_data->GetHeader().file_size_);
    714   ASSERT_TRUE(success);
    715 
    716   success = zip_builder.Finish();
    717   ASSERT_TRUE(success) << strerror(errno);
    718 
    719   SafeMap<std::string, std::string> key_value_store;
    720   key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
    721   {
    722     // Test using the AddDexFileSource() interface with the zip file.
    723     std::vector<const char*> input_filenames { zip_file.GetFilename().c_str() };  // NOLINT [readability/braces] [4]
    724 
    725     ScratchFile oat_file, vdex_file(oat_file, ".vdex");
    726     success = WriteElf(vdex_file.GetFile(), oat_file.GetFile(), input_filenames,
    727                        key_value_store, verify, /*profile_compilation_info*/nullptr);
    728 
    729     if (verify) {
    730       ASSERT_FALSE(success);
    731     } else {
    732       ASSERT_TRUE(success);
    733 
    734       std::string error_msg;
    735       std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(oat_file.GetFilename(),
    736                                                              oat_file.GetFilename(),
    737                                                              nullptr,
    738                                                              nullptr,
    739                                                              false,
    740                                                              /*low_4gb*/false,
    741                                                              nullptr,
    742                                                              &error_msg));
    743       ASSERT_TRUE(opened_oat_file != nullptr);
    744       ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size());
    745       std::unique_ptr<const DexFile> opened_dex_file1 =
    746           opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg);
    747       std::unique_ptr<const DexFile> opened_dex_file2 =
    748           opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg);
    749 
    750       ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_);
    751       ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(),
    752                           &opened_dex_file1->GetHeader(),
    753                           dex_file1_data->GetHeader().file_size_));
    754       ASSERT_EQ(DexFile::GetMultiDexLocation(0, zip_file.GetFilename().c_str()),
    755                 opened_dex_file1->GetLocation());
    756 
    757       ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_);
    758       ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(),
    759                           &opened_dex_file2->GetHeader(),
    760                           dex_file2_data->GetHeader().file_size_));
    761       ASSERT_EQ(DexFile::GetMultiDexLocation(1, zip_file.GetFilename().c_str()),
    762                 opened_dex_file2->GetLocation());
    763     }
    764   }
    765 
    766   {
    767     // Test using the AddZipDexFileSource() interface with the zip file handle.
    768     File zip_fd(dup(zip_file.GetFd()), /* check_usage */ false);
    769     ASSERT_NE(-1, zip_fd.Fd());
    770 
    771     ScratchFile oat_file, vdex_file(oat_file, ".vdex");
    772     success = WriteElf(vdex_file.GetFile(),
    773                        oat_file.GetFile(),
    774                        std::move(zip_fd),
    775                        zip_file.GetFilename().c_str(),
    776                        key_value_store,
    777                        verify);
    778     if (verify) {
    779       ASSERT_FALSE(success);
    780     } else {
    781       ASSERT_TRUE(success);
    782 
    783       std::string error_msg;
    784       std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(oat_file.GetFilename(),
    785                                                              oat_file.GetFilename(),
    786                                                              nullptr,
    787                                                              nullptr,
    788                                                              false,
    789                                                              /*low_4gb*/false,
    790                                                              nullptr,
    791                                                              &error_msg));
    792       ASSERT_TRUE(opened_oat_file != nullptr);
    793       ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size());
    794       std::unique_ptr<const DexFile> opened_dex_file1 =
    795           opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg);
    796       std::unique_ptr<const DexFile> opened_dex_file2 =
    797           opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg);
    798 
    799       ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_);
    800       ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(),
    801                           &opened_dex_file1->GetHeader(),
    802                           dex_file1_data->GetHeader().file_size_));
    803       ASSERT_EQ(DexFile::GetMultiDexLocation(0, zip_file.GetFilename().c_str()),
    804                 opened_dex_file1->GetLocation());
    805 
    806       ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_);
    807       ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(),
    808                           &opened_dex_file2->GetHeader(),
    809                           dex_file2_data->GetHeader().file_size_));
    810       ASSERT_EQ(DexFile::GetMultiDexLocation(1, zip_file.GetFilename().c_str()),
    811                 opened_dex_file2->GetLocation());
    812     }
    813   }
    814 }
    815 
    816 TEST_F(OatTest, ZipFileInputCheckOutput) {
    817   TestZipFileInput(false);
    818 }
    819 
    820 TEST_F(OatTest, ZipFileInputCheckVerifier) {
    821   TestZipFileInput(true);
    822 }
    823 
    824 void OatTest::TestZipFileInputWithEmptyDex() {
    825   ScratchFile zip_file;
    826   ZipBuilder zip_builder(zip_file.GetFile());
    827   bool success = zip_builder.AddFile("classes.dex", nullptr, 0);
    828   ASSERT_TRUE(success);
    829   success = zip_builder.Finish();
    830   ASSERT_TRUE(success) << strerror(errno);
    831 
    832   SafeMap<std::string, std::string> key_value_store;
    833   key_value_store.Put(OatHeader::kImageLocationKey, "test.art");
    834   std::vector<const char*> input_filenames { zip_file.GetFilename().c_str() };  // NOLINT [readability/braces] [4]
    835   ScratchFile oat_file, vdex_file(oat_file, ".vdex");
    836   std::unique_ptr<ProfileCompilationInfo> profile_compilation_info(new ProfileCompilationInfo());
    837   success = WriteElf(vdex_file.GetFile(), oat_file.GetFile(), input_filenames,
    838                      key_value_store, /*verify*/false, profile_compilation_info.get());
    839   ASSERT_FALSE(success);
    840 }
    841 
    842 TEST_F(OatTest, ZipFileInputWithEmptyDex) {
    843   TestZipFileInputWithEmptyDex();
    844 }
    845 
    846 TEST_F(OatTest, UpdateChecksum) {
    847   InstructionSet insn_set = kX86;
    848   std::string error_msg;
    849   std::unique_ptr<const InstructionSetFeatures> insn_features(
    850     InstructionSetFeatures::FromVariant(insn_set, "default", &error_msg));
    851   ASSERT_TRUE(insn_features.get() != nullptr) << error_msg;
    852   std::unique_ptr<OatHeader> oat_header(OatHeader::Create(insn_set,
    853                                                           insn_features.get(),
    854                                                           0u,
    855                                                           nullptr));
    856   // The starting adler32 value is 1.
    857   EXPECT_EQ(1U, oat_header->GetChecksum());
    858 
    859   oat_header->UpdateChecksum(OatHeader::kOatMagic, sizeof(OatHeader::kOatMagic));
    860   EXPECT_EQ(64291151U, oat_header->GetChecksum());
    861 
    862   // Make sure that null data does not reset the checksum.
    863   oat_header->UpdateChecksum(nullptr, 0);
    864   EXPECT_EQ(64291151U, oat_header->GetChecksum());
    865 
    866   oat_header->UpdateChecksum(OatHeader::kOatMagic, sizeof(OatHeader::kOatMagic));
    867   EXPECT_EQ(216138397U, oat_header->GetChecksum());
    868 }
    869 
    870 }  // namespace art
    871