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