12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 16e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 17d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arch/instruction_set_features.h" 18e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h" 1907ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier#include "base/unix_file/fd_file.h" 2053c913bb71b218714823c8c87a1f92830c336f61Andreas Gampe#include "class_linker.h" 21a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstrom#include "common_compiler_test.h" 2220f85597828194c12be10d3a927999def066555eVladimir Marko#include "compiled_method.h" 23e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "compiler.h" 244fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "debug/method_debug_info.h" 25e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "dex/quick/dex_file_to_method_inliner_map.h" 26e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "dex/quick_compiler_callbacks.h" 275bdab12d8b48ca4c395d9d2c506ebff0df01b734Mathieu Chartier#include "dex/verification_results.h" 2820f85597828194c12be10d3a927999def066555eVladimir Marko#include "driver/compiler_driver.h" 2920f85597828194c12be10d3a927999def066555eVladimir Marko#include "driver/compiler_options.h" 3010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko#include "elf_writer.h" 3110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko#include "elf_writer_quick.h" 327624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko#include "entrypoints/quick/quick_entrypoints.h" 33944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko#include "linker/multi_oat_relative_patcher.h" 34131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko#include "linker/vector_output_stream.h" 352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h" 36e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "mirror/object-inl.h" 374fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "mirror/object_array-inl.h" 387624d25dad2d1ba25969ae704fccf68649103ae5Vladimir Marko#include "oat_file-inl.h" 39e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "oat_writer.h" 40e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "scoped_thread_state_change.h" 419bdf108885a27ba05fae8501725649574d7c491bVladimir Marko#include "utils/test_dex_file_builder.h" 42e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 43e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art { 44e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 4507ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu ChartierNO_RETURN static void Usage(const char* fmt, ...) { 4607ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier va_list ap; 4707ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier va_start(ap, fmt); 4807ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier std::string error; 4907ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier StringAppendV(&error, fmt, ap); 5007ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier LOG(FATAL) << error; 5107ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier va_end(ap); 5207ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier UNREACHABLE(); 5307ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier} 5407ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier 55a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstromclass OatTest : public CommonCompilerTest { 56eeb7edf786abf6dbcfc37964af8854caafda6b0bLogan Chien protected: 57ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom static const bool kCompile = false; // DISABLED_ due to the time to compile libcore 58ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom 59e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier void CheckMethod(ArtMethod* method, 60eeb7edf786abf6dbcfc37964af8854caafda6b0bLogan Chien const OatFile::OatMethod& oat_method, 61fbef44de596d298dc6430f482dffc933a046dd28Richard Uhler const DexFile& dex_file) 6290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 63eeb7edf786abf6dbcfc37964af8854caafda6b0bLogan Chien const CompiledMethod* compiled_method = 64fbef44de596d298dc6430f482dffc933a046dd28Richard Uhler compiler_driver_->GetCompiledMethod(MethodReference(&dex_file, 6551c2467e8771b56e25ae4f17f66522f979f57a7eBrian Carlstrom method->GetDexMethodIndex())); 66eeb7edf786abf6dbcfc37964af8854caafda6b0bLogan Chien 67d4c4d953035d4418126d36517e402f411d6a87f3Ian Rogers if (compiled_method == nullptr) { 68d4c4d953035d4418126d36517e402f411d6a87f3Ian Rogers EXPECT_TRUE(oat_method.GetQuickCode() == nullptr) << PrettyMethod(method) << " " 69d4c4d953035d4418126d36517e402f411d6a87f3Ian Rogers << oat_method.GetQuickCode(); 70ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers EXPECT_EQ(oat_method.GetFrameSizeInBytes(), 0U); 71eeb7edf786abf6dbcfc37964af8854caafda6b0bLogan Chien EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U); 72eeb7edf786abf6dbcfc37964af8854caafda6b0bLogan Chien EXPECT_EQ(oat_method.GetFpSpillMask(), 0U); 73eeb7edf786abf6dbcfc37964af8854caafda6b0bLogan Chien } else { 74ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const void* quick_oat_code = oat_method.GetQuickCode(); 75956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes EXPECT_TRUE(quick_oat_code != nullptr) << PrettyMethod(method); 76956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes()); 77956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask()); 78956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask()); 79956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(quick_oat_code), 2); 80956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes quick_oat_code = reinterpret_cast<const void*>(oat_code_aligned); 8135831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode(); 8235831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko EXPECT_FALSE(quick_code.empty()); 8335831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko size_t code_size = quick_code.size() * sizeof(quick_code[0]); 84956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes EXPECT_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size)) 85956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes << PrettyMethod(method) << " " << code_size; 86956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes CHECK_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size)); 87eeb7edf786abf6dbcfc37964af8854caafda6b0bLogan Chien } 88eeb7edf786abf6dbcfc37964af8854caafda6b0bLogan Chien } 8907ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier 9007ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier void SetupCompiler(Compiler::Kind compiler_kind, 9107ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier InstructionSet insn_set, 9207ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier const std::vector<std::string>& compiler_options, 9307ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier /*out*/std::string* error_msg) { 9407ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier ASSERT_TRUE(error_msg != nullptr); 9507ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier insn_features_.reset(InstructionSetFeatures::FromVariant(insn_set, "default", error_msg)); 9607ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier ASSERT_TRUE(insn_features_ != nullptr) << error_msg; 9707ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier compiler_options_.reset(new CompilerOptions); 9807ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier for (const std::string& option : compiler_options) { 9907ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier compiler_options_->ParseCompilerOption(option, Usage); 10007ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier } 10107ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier verification_results_.reset(new VerificationResults(compiler_options_.get())); 10207ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier method_inliner_map_.reset(new DexFileToMethodInlinerMap); 10307ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(), 10407ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier method_inliner_map_.get(), 10507ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier CompilerCallbacks::CallbackMode::kCompileApp)); 10607ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier Runtime::Current()->SetCompilerCallbacks(callbacks_.get()); 10707ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier timer_.reset(new CumulativeLogger("Compilation times")); 10807ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier compiler_driver_.reset(new CompilerDriver(compiler_options_.get(), 10907ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier verification_results_.get(), 11007ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier method_inliner_map_.get(), 11107ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier compiler_kind, 11207ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier insn_set, 11307ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier insn_features_.get(), 114944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko /* boot_image */ false, 115cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier /* app_image */ false, 116944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko /* image_classes */ nullptr, 117944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko /* compiled_classes */ nullptr, 118944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko /* compiled_methods */ nullptr, 119944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko /* thread_count */ 2, 120944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko /* dump_stats */ true, 121944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko /* dump_passes */ true, 12207ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier timer_.get(), 123944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko /* swap_fd */ -1, 124944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko /* profile_compilation_info */ nullptr)); 12507ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier } 12607ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier 12707ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier bool WriteElf(File* file, 12807ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier const std::vector<const DexFile*>& dex_files, 1293a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe SafeMap<std::string, std::string>& key_value_store, 1303a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe bool verify) { 13107ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier TimingLogger timings("WriteElf", false, false); 1329bdf108885a27ba05fae8501725649574d7c491bVladimir Marko OatWriter oat_writer(/*compiling_boot_image*/false, &timings); 1339bdf108885a27ba05fae8501725649574d7c491bVladimir Marko for (const DexFile* dex_file : dex_files) { 1349bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ArrayRef<const uint8_t> raw_dex_file( 1359bdf108885a27ba05fae8501725649574d7c491bVladimir Marko reinterpret_cast<const uint8_t*>(&dex_file->GetHeader()), 1369bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file->GetHeader().file_size_); 1379bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (!oat_writer.AddRawDexFileSource(raw_dex_file, 1389bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file->GetLocation().c_str(), 1399bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file->GetLocationChecksum())) { 1409bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 1419bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 1429bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 1433a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe return DoWriteElf(file, oat_writer, key_value_store, verify); 1449bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 1459bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 1469bdf108885a27ba05fae8501725649574d7c491bVladimir Marko bool WriteElf(File* file, 1479bdf108885a27ba05fae8501725649574d7c491bVladimir Marko const std::vector<const char*>& dex_filenames, 1483a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe SafeMap<std::string, std::string>& key_value_store, 1493a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe bool verify) { 1509bdf108885a27ba05fae8501725649574d7c491bVladimir Marko TimingLogger timings("WriteElf", false, false); 1519bdf108885a27ba05fae8501725649574d7c491bVladimir Marko OatWriter oat_writer(/*compiling_boot_image*/false, &timings); 1529bdf108885a27ba05fae8501725649574d7c491bVladimir Marko for (const char* dex_filename : dex_filenames) { 1539bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (!oat_writer.AddDexFileSource(dex_filename, dex_filename)) { 1549bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 1559bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 1569bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 1573a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe return DoWriteElf(file, oat_writer, key_value_store, verify); 1589bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 1599bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 1609bdf108885a27ba05fae8501725649574d7c491bVladimir Marko bool WriteElf(File* file, 1619bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ScopedFd&& zip_fd, 1629bdf108885a27ba05fae8501725649574d7c491bVladimir Marko const char* location, 1633a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe SafeMap<std::string, std::string>& key_value_store, 1643a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe bool verify) { 1659bdf108885a27ba05fae8501725649574d7c491bVladimir Marko TimingLogger timings("WriteElf", false, false); 1669bdf108885a27ba05fae8501725649574d7c491bVladimir Marko OatWriter oat_writer(/*compiling_boot_image*/false, &timings); 1679bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (!oat_writer.AddZippedDexFilesSource(std::move(zip_fd), location)) { 1689bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 1699bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 1703a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe return DoWriteElf(file, oat_writer, key_value_store, verify); 1719bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 1729bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 1739bdf108885a27ba05fae8501725649574d7c491bVladimir Marko bool DoWriteElf(File* file, 1749bdf108885a27ba05fae8501725649574d7c491bVladimir Marko OatWriter& oat_writer, 1753a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe SafeMap<std::string, std::string>& key_value_store, 1763a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe bool verify) { 17710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko std::unique_ptr<ElfWriter> elf_writer = CreateElfWriterQuick( 17810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko compiler_driver_->GetInstructionSet(), 1795d8112029d0e085c5a0099257daa4c7e29c12310David Srbecky compiler_driver_->GetInstructionSetFeatures(), 18010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko &compiler_driver_->GetCompilerOptions(), 18110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko file); 18210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko elf_writer->Start(); 18310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko OutputStream* rodata = elf_writer->StartRoData(); 1849bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::unique_ptr<MemMap> opened_dex_files_map; 1859bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::vector<std::unique_ptr<const DexFile>> opened_dex_files; 1869bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (!oat_writer.WriteAndOpenDexFiles(rodata, 1879bdf108885a27ba05fae8501725649574d7c491bVladimir Marko file, 1889bdf108885a27ba05fae8501725649574d7c491bVladimir Marko compiler_driver_->GetInstructionSet(), 1899bdf108885a27ba05fae8501725649574d7c491bVladimir Marko compiler_driver_->GetInstructionSetFeatures(), 1909bdf108885a27ba05fae8501725649574d7c491bVladimir Marko &key_value_store, 1913a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe verify, 1929bdf108885a27ba05fae8501725649574d7c491bVladimir Marko &opened_dex_files_map, 1939bdf108885a27ba05fae8501725649574d7c491bVladimir Marko &opened_dex_files)) { 1949bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 1959bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 1969bdf108885a27ba05fae8501725649574d7c491bVladimir Marko Runtime* runtime = Runtime::Current(); 1979bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ClassLinker* const class_linker = runtime->GetClassLinker(); 1989bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::vector<const DexFile*> dex_files; 1999bdf108885a27ba05fae8501725649574d7c491bVladimir Marko for (const std::unique_ptr<const DexFile>& dex_file : opened_dex_files) { 2009bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_files.push_back(dex_file.get()); 2019bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ScopedObjectAccess soa(Thread::Current()); 202c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier class_linker->RegisterDexFile(*dex_file, nullptr); 2039bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 204944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko linker::MultiOatRelativePatcher patcher(compiler_driver_->GetInstructionSet(), 205944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko instruction_set_features_.get()); 206944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko oat_writer.PrepareLayout(compiler_driver_.get(), nullptr, dex_files, &patcher); 207944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko size_t rodata_size = oat_writer.GetOatHeader().GetExecutableOffset(); 208944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko size_t text_size = oat_writer.GetSize() - rodata_size; 209944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko elf_writer->SetLoadedSectionSizes(rodata_size, text_size, oat_writer.GetBssSize()); 210944da603cde59a4277f3bbc31d860a90842a1a2aVladimir Marko 21110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko if (!oat_writer.WriteRodata(rodata)) { 21210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko return false; 21310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko } 21410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko elf_writer->EndRoData(rodata); 21510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko 21610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko OutputStream* text = elf_writer->StartText(); 21710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko if (!oat_writer.WriteCode(text)) { 21810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko return false; 21910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko } 22010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko elf_writer->EndText(text); 22110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko 2229bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (!oat_writer.WriteHeader(elf_writer->GetStream(), 42U, 4096U, 0)) { 2239bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 2249bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 2259bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 22610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko elf_writer->WriteDynamicSection(); 22749b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko elf_writer->WriteDebugInfo(oat_writer.GetMethodDebugInfo()); 22849b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko elf_writer->WritePatchLocations(oat_writer.GetAbsolutePatchLocations()); 22910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko 23010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko return elf_writer->End(); 23107ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier } 23207ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier 2330b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier void TestDexFileInput(bool verify, bool low_4gb); 2343a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe void TestZipFileInput(bool verify); 2353a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 23607ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier std::unique_ptr<const InstructionSetFeatures> insn_features_; 23707ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier std::unique_ptr<QuickCompilerCallbacks> callbacks_; 238eeb7edf786abf6dbcfc37964af8854caafda6b0bLogan Chien}; 239e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 2409bdf108885a27ba05fae8501725649574d7c491bVladimir Markoclass ZipBuilder { 2419bdf108885a27ba05fae8501725649574d7c491bVladimir Marko public: 2429bdf108885a27ba05fae8501725649574d7c491bVladimir Marko explicit ZipBuilder(File* zip_file) : zip_file_(zip_file) { } 2439bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 2449bdf108885a27ba05fae8501725649574d7c491bVladimir Marko bool AddFile(const char* location, const void* data, size_t size) { 2459bdf108885a27ba05fae8501725649574d7c491bVladimir Marko off_t offset = lseek(zip_file_->Fd(), 0, SEEK_CUR); 2469bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (offset == static_cast<off_t>(-1)) { 2479bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 2489bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 2499bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 2509bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ZipFileHeader file_header; 2519bdf108885a27ba05fae8501725649574d7c491bVladimir Marko file_header.crc32 = crc32(0u, reinterpret_cast<const Bytef*>(data), size); 2529bdf108885a27ba05fae8501725649574d7c491bVladimir Marko file_header.compressed_size = size; 2539bdf108885a27ba05fae8501725649574d7c491bVladimir Marko file_header.uncompressed_size = size; 2549bdf108885a27ba05fae8501725649574d7c491bVladimir Marko file_header.filename_length = strlen(location); 2559bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 2569bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (!zip_file_->WriteFully(&file_header, sizeof(file_header)) || 2579bdf108885a27ba05fae8501725649574d7c491bVladimir Marko !zip_file_->WriteFully(location, file_header.filename_length) || 2589bdf108885a27ba05fae8501725649574d7c491bVladimir Marko !zip_file_->WriteFully(data, size)) { 2599bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 2609bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 2619bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 2629bdf108885a27ba05fae8501725649574d7c491bVladimir Marko CentralDirectoryFileHeader cdfh; 2639bdf108885a27ba05fae8501725649574d7c491bVladimir Marko cdfh.crc32 = file_header.crc32; 2649bdf108885a27ba05fae8501725649574d7c491bVladimir Marko cdfh.compressed_size = size; 2659bdf108885a27ba05fae8501725649574d7c491bVladimir Marko cdfh.uncompressed_size = size; 2669bdf108885a27ba05fae8501725649574d7c491bVladimir Marko cdfh.filename_length = file_header.filename_length; 2679bdf108885a27ba05fae8501725649574d7c491bVladimir Marko cdfh.relative_offset_of_local_file_header = offset; 2689bdf108885a27ba05fae8501725649574d7c491bVladimir Marko file_data_.push_back(FileData { cdfh, location }); 2699bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return true; 2709bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 2719bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 2729bdf108885a27ba05fae8501725649574d7c491bVladimir Marko bool Finish() { 2739bdf108885a27ba05fae8501725649574d7c491bVladimir Marko off_t offset = lseek(zip_file_->Fd(), 0, SEEK_CUR); 2749bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (offset == static_cast<off_t>(-1)) { 2759bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 2769bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 2779bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 2789bdf108885a27ba05fae8501725649574d7c491bVladimir Marko size_t central_directory_size = 0u; 2799bdf108885a27ba05fae8501725649574d7c491bVladimir Marko for (const FileData& file_data : file_data_) { 2809bdf108885a27ba05fae8501725649574d7c491bVladimir Marko if (!zip_file_->WriteFully(&file_data.cdfh, sizeof(file_data.cdfh)) || 2819bdf108885a27ba05fae8501725649574d7c491bVladimir Marko !zip_file_->WriteFully(file_data.location, file_data.cdfh.filename_length)) { 2829bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return false; 2839bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 2849bdf108885a27ba05fae8501725649574d7c491bVladimir Marko central_directory_size += sizeof(file_data.cdfh) + file_data.cdfh.filename_length; 2859bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 2869bdf108885a27ba05fae8501725649574d7c491bVladimir Marko EndOfCentralDirectoryRecord eocd_record; 2879bdf108885a27ba05fae8501725649574d7c491bVladimir Marko eocd_record.number_of_central_directory_records_on_this_disk = file_data_.size(); 2889bdf108885a27ba05fae8501725649574d7c491bVladimir Marko eocd_record.total_number_of_central_directory_records = file_data_.size(); 2899bdf108885a27ba05fae8501725649574d7c491bVladimir Marko eocd_record.size_of_central_directory = central_directory_size; 2909bdf108885a27ba05fae8501725649574d7c491bVladimir Marko eocd_record.offset_of_start_of_central_directory = offset; 2919bdf108885a27ba05fae8501725649574d7c491bVladimir Marko return 2929bdf108885a27ba05fae8501725649574d7c491bVladimir Marko zip_file_->WriteFully(&eocd_record, sizeof(eocd_record)) && 2939bdf108885a27ba05fae8501725649574d7c491bVladimir Marko zip_file_->Flush() == 0; 2949bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 2959bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 2969bdf108885a27ba05fae8501725649574d7c491bVladimir Marko private: 2979bdf108885a27ba05fae8501725649574d7c491bVladimir Marko struct PACKED(1) ZipFileHeader { 2989bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t signature = 0x04034b50; 2999bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t version_needed_to_extract = 10; 3009bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t general_purpose_bit_flag = 0; 3019bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t compression_method = 0; // 0 = store only. 3029bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t file_last_modification_time = 0u; 3039bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t file_last_modification_date = 0u; 3049bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t crc32; 3059bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t compressed_size; 3069bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t uncompressed_size; 3079bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t filename_length; 3089bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t extra_field_length = 0u; // No extra fields. 3099bdf108885a27ba05fae8501725649574d7c491bVladimir Marko }; 3109bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 3119bdf108885a27ba05fae8501725649574d7c491bVladimir Marko struct PACKED(1) CentralDirectoryFileHeader { 3129bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t signature = 0x02014b50; 3139bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t version_made_by = 10; 3149bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t version_needed_to_extract = 10; 3159bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t general_purpose_bit_flag = 0; 3169bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t compression_method = 0; // 0 = store only. 3179bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t file_last_modification_time = 0u; 3189bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t file_last_modification_date = 0u; 3199bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t crc32; 3209bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t compressed_size; 3219bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t uncompressed_size; 3229bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t filename_length; 3239bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t extra_field_length = 0u; // No extra fields. 3249bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t file_comment_length = 0u; // No file comment. 3259bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t disk_number_where_file_starts = 0u; 3269bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t internal_file_attributes = 0u; 3279bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t external_file_attributes = 0u; 3289bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t relative_offset_of_local_file_header; 3299bdf108885a27ba05fae8501725649574d7c491bVladimir Marko }; 3309bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 3319bdf108885a27ba05fae8501725649574d7c491bVladimir Marko struct PACKED(1) EndOfCentralDirectoryRecord { 3329bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t signature = 0x06054b50; 3339bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t number_of_this_disk = 0u; 3349bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t disk_where_central_directory_starts = 0u; 3359bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t number_of_central_directory_records_on_this_disk; 3369bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t total_number_of_central_directory_records; 3379bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t size_of_central_directory; 3389bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint32_t offset_of_start_of_central_directory; 3399bdf108885a27ba05fae8501725649574d7c491bVladimir Marko uint16_t comment_length = 0u; // No file comment. 3409bdf108885a27ba05fae8501725649574d7c491bVladimir Marko }; 3419bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 3429bdf108885a27ba05fae8501725649574d7c491bVladimir Marko struct FileData { 3439bdf108885a27ba05fae8501725649574d7c491bVladimir Marko CentralDirectoryFileHeader cdfh; 3449bdf108885a27ba05fae8501725649574d7c491bVladimir Marko const char* location; 3459bdf108885a27ba05fae8501725649574d7c491bVladimir Marko }; 3469bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 3479bdf108885a27ba05fae8501725649574d7c491bVladimir Marko File* zip_file_; 3489bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::vector<FileData> file_data_; 3499bdf108885a27ba05fae8501725649574d7c491bVladimir Marko}; 3509bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 351e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromTEST_F(OatTest, WriteRead) { 352a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstrom TimingLogger timings("OatTest::WriteRead", false, false); 353254db0ff7ea6509a1c2914b1d9532e2041a0c4c4Jesse Wilson ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 354e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 355ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers // TODO: make selectable. 356956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes Compiler::Kind compiler_kind = Compiler::kQuick; 357a073c67b8a0041c36bde419c509d1fd3864b7d6bIan Rogers InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86; 3586f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers std::string error_msg; 35907ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier SetupCompiler(compiler_kind, insn_set, std::vector<std::string>(), /*out*/ &error_msg); 36007ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier 361d4c4d953035d4418126d36517e402f411d6a87f3Ian Rogers jobject class_loader = nullptr; 362ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (kCompile) { 363277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe TimingLogger timings2("OatTest::WriteRead", false, false); 364d1eaf0dc9abc42dbcbbd9c4b98bf930ae5f394f3Vladimir Marko compiler_driver_->SetDexFilesForOatFile(class_linker->GetBootClassPath()); 365277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), &timings2); 366e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 367e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 368e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom ScratchFile tmp; 36922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe SafeMap<std::string, std::string> key_value_store; 37022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe key_value_store.Put(OatHeader::kImageLocationKey, "lue.art"); 3713a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe bool success = WriteElf(tmp.GetFile(), class_linker->GetBootClassPath(), key_value_store, false); 372c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom ASSERT_TRUE(success); 373e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 374ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom if (kCompile) { // OatWriter strips the code, regenerate to compare 3753d504075f7c1204d581923460754bf6d3714b13fIan Rogers compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), &timings); 376e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 3770b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), 3780b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier tmp.GetFilename(), 3790b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier nullptr, 3800b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier nullptr, 3810b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier false, 3820b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier /*low_4gb*/true, 3830b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier nullptr, 3840b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier &error_msg)); 3858d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers ASSERT_TRUE(oat_file.get() != nullptr) << error_msg; 386e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const OatHeader& oat_header = oat_file->GetOatHeader(); 387f852fb2921128d3b71a76e6b17c78d10fb7085e2Brian Carlstrom ASSERT_TRUE(oat_header.IsValid()); 3889515b51c6ae1ad9c8b0a9d07334ef62af16cec6aYi Kong ASSERT_EQ(class_linker->GetBootClassPath().size(), oat_header.GetDexFileCount()); // core 38928db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom ASSERT_EQ(42U, oat_header.GetImageFileLocationOatChecksum()); 390700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom ASSERT_EQ(4096U, oat_header.GetImageFileLocationOatDataBegin()); 39122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe ASSERT_EQ("lue.art", std::string(oat_header.GetStoreValueByKey(OatHeader::kImageLocationKey))); 392e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 393fbef44de596d298dc6430f482dffc933a046dd28Richard Uhler ASSERT_TRUE(java_lang_dex_file_ != nullptr); 394fbef44de596d298dc6430f482dffc933a046dd28Richard Uhler const DexFile& dex_file = *java_lang_dex_file_; 395fbef44de596d298dc6430f482dffc933a046dd28Richard Uhler uint32_t dex_file_checksum = dex_file.GetLocationChecksum(); 396fbef44de596d298dc6430f482dffc933a046dd28Richard Uhler const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation().c_str(), 397756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom &dex_file_checksum); 3988d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers ASSERT_TRUE(oat_dex_file != nullptr); 399fbef44de596d298dc6430f482dffc933a046dd28Richard Uhler CHECK_EQ(dex_file.GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum()); 400f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko ScopedObjectAccess soa(Thread::Current()); 401e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier auto pointer_size = class_linker->GetImagePointerSize(); 402fbef44de596d298dc6430f482dffc933a046dd28Richard Uhler for (size_t i = 0; i < dex_file.NumClassDefs(); i++) { 403fbef44de596d298dc6430f482dffc933a046dd28Richard Uhler const DexFile::ClassDef& class_def = dex_file.GetClassDef(i); 404fbef44de596d298dc6430f482dffc933a046dd28Richard Uhler const uint8_t* class_data = dex_file.GetClassData(class_def); 405e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier 406ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom size_t num_virtual_methods = 0; 407d4c4d953035d4418126d36517e402f411d6a87f3Ian Rogers if (class_data != nullptr) { 408fbef44de596d298dc6430f482dffc933a046dd28Richard Uhler ClassDataItemIterator it(dex_file, class_data); 4090571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers num_virtual_methods = it.NumVirtualMethods(); 4100571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers } 411e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier 412fbef44de596d298dc6430f482dffc933a046dd28Richard Uhler const char* descriptor = dex_file.GetClassDescriptor(class_def); 4139865bde5d822f56c4732214c2005dfcaa41f94cfMathieu Chartier mirror::Class* klass = class_linker->FindClass(soa.Self(), 4149865bde5d822f56c4732214c2005dfcaa41f94cfMathieu Chartier descriptor, 4159865bde5d822f56c4732214c2005dfcaa41f94cfMathieu Chartier ScopedNullHandle<mirror::ClassLoader>()); 416e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 417d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(i); 418d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko CHECK_EQ(mirror::Class::Status::kStatusNotReady, oat_class.GetStatus()) << descriptor; 419ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom CHECK_EQ(kCompile ? OatClassType::kOatClassAllCompiled : OatClassType::kOatClassNoneCompiled, 420d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko oat_class.GetType()) << descriptor; 421e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 422e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t method_index = 0; 423e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier for (auto& m : klass->GetDirectMethods(pointer_size)) { 424e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file); 425e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ++method_index; 426e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 427e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier size_t visited_virtuals = 0; 428e64300b8488716056775ecbfa2915dd1b4ce7e08Alex Light // TODO We should also check copied methods in this test. 429e64300b8488716056775ecbfa2915dd1b4ce7e08Alex Light for (auto& m : klass->GetDeclaredVirtualMethods(pointer_size)) { 430fcea56f9cc51957161fe7a6e35e895fd8c4c4a7fAlex Light if (!klass->IsInterface()) { 4313612149aee482ab7a17da68b0ef5fef3879729a2Alex Light EXPECT_FALSE(m.IsCopied()); 432fcea56f9cc51957161fe7a6e35e895fd8c4c4a7fAlex Light } 433e64300b8488716056775ecbfa2915dd1b4ce7e08Alex Light CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file); 434e64300b8488716056775ecbfa2915dd1b4ce7e08Alex Light ++method_index; 435e64300b8488716056775ecbfa2915dd1b4ce7e08Alex Light ++visited_virtuals; 436e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 437e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier EXPECT_EQ(visited_virtuals, num_virtual_methods); 438e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 439e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 440e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 441341df94dbfed27aaa5436b3a0a96a35f9b746338Brian CarlstromTEST_F(OatTest, OatHeaderSizeCheck) { 442341df94dbfed27aaa5436b3a0a96a35f9b746338Brian Carlstrom // If this test is failing and you have to update these constants, 443341df94dbfed27aaa5436b3a0a96a35f9b746338Brian Carlstrom // it is time to update OatHeader::kOatVersion 444956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes EXPECT_EQ(72U, sizeof(OatHeader)); 445957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier EXPECT_EQ(4U, sizeof(OatMethodOffsets)); 4469d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko EXPECT_EQ(20U, sizeof(OatQuickMethodHeader)); 4477c1559a06041c9c299d5ab514d54b2102f204a84Roland Levillain EXPECT_EQ(132 * GetInstructionSetPointerSize(kRuntimeISA), sizeof(QuickEntryPoints)); 448341df94dbfed27aaa5436b3a0a96a35f9b746338Brian Carlstrom} 449341df94dbfed27aaa5436b3a0a96a35f9b746338Brian Carlstrom 450f852fb2921128d3b71a76e6b17c78d10fb7085e2Brian CarlstromTEST_F(OatTest, OatHeaderIsValid) { 4512c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao InstructionSet insn_set = kX86; 4522c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao std::string error_msg; 4532c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao std::unique_ptr<const InstructionSetFeatures> insn_features( 4542c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao InstructionSetFeatures::FromVariant(insn_set, "default", &error_msg)); 4552c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao ASSERT_TRUE(insn_features.get() != nullptr) << error_msg; 4562c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao std::unique_ptr<OatHeader> oat_header(OatHeader::Create(insn_set, 4572c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao insn_features.get(), 4582c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao 0u, 4592c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao nullptr)); 4602c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao ASSERT_NE(oat_header.get(), nullptr); 4612c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao ASSERT_TRUE(oat_header->IsValid()); 4622c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao 4632c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao char* magic = const_cast<char*>(oat_header->GetMagic()); 4642c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao strcpy(magic, ""); // bad magic 4652c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao ASSERT_FALSE(oat_header->IsValid()); 4662c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao strcpy(magic, "oat\n000"); // bad version 4672c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao ASSERT_FALSE(oat_header->IsValid()); 468f852fb2921128d3b71a76e6b17c78d10fb7085e2Brian Carlstrom} 469f852fb2921128d3b71a76e6b17c78d10fb7085e2Brian Carlstrom 47007ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu ChartierTEST_F(OatTest, EmptyTextSection) { 47107ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier TimingLogger timings("OatTest::EmptyTextSection", false, false); 47207ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier 47307ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier // TODO: make selectable. 47407ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier Compiler::Kind compiler_kind = Compiler::kQuick; 47507ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier InstructionSet insn_set = kRuntimeISA; 47607ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier if (insn_set == kArm) insn_set = kThumb2; 47707ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier std::string error_msg; 47807ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier std::vector<std::string> compiler_options; 47907ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier compiler_options.push_back("--compiler-filter=verify-at-runtime"); 48007ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier SetupCompiler(compiler_kind, insn_set, compiler_options, /*out*/ &error_msg); 48107ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier 48207ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier jobject class_loader; 48307ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier { 48407ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier ScopedObjectAccess soa(Thread::Current()); 48507ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier class_loader = LoadDex("Main"); 48607ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier } 48707ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier ASSERT_TRUE(class_loader != nullptr); 48807ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier std::vector<const DexFile*> dex_files = GetDexFiles(class_loader); 48907ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier ASSERT_TRUE(!dex_files.empty()); 49007ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier 49107ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); 49207ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier for (const DexFile* dex_file : dex_files) { 49307ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier ScopedObjectAccess soa(Thread::Current()); 494c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier class_linker->RegisterDexFile(*dex_file, soa.Decode<mirror::ClassLoader*>(class_loader)); 49507ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier } 49607ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier compiler_driver_->SetDexFilesForOatFile(dex_files); 49707ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier compiler_driver_->CompileAll(class_loader, dex_files, &timings); 49807ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier 49907ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier ScratchFile tmp; 50007ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier SafeMap<std::string, std::string> key_value_store; 50107ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier key_value_store.Put(OatHeader::kImageLocationKey, "test.art"); 5023a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe bool success = WriteElf(tmp.GetFile(), dex_files, key_value_store, false); 50307ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier ASSERT_TRUE(success); 50407ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier 50507ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), 50607ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier tmp.GetFilename(), 50707ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier nullptr, 50807ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier nullptr, 50907ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier false, 5100b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier /*low_4gb*/false, 51107ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier nullptr, 51207ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier &error_msg)); 51307ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier ASSERT_TRUE(oat_file != nullptr); 51407ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier EXPECT_LT(static_cast<size_t>(oat_file->Size()), static_cast<size_t>(tmp.GetFile()->GetLength())); 51507ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier} 51607ddb6f713f8c919e6da7c4b473cfb3bacb7cf10Mathieu Chartier 5173a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampestatic void MaybeModifyDexFileToFail(bool verify, std::unique_ptr<const DexFile>& data) { 5183a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe // If in verify mode (= fail the verifier mode), make sure we fail early. We'll fail already 5193a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe // because of the missing map, but that may lead to out of bounds reads. 5203a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe if (verify) { 5213a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe const_cast<DexFile::Header*>(&data->GetHeader())->checksum_++; 5223a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe } 5233a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe} 5243a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 5250b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartiervoid OatTest::TestDexFileInput(bool verify, bool low_4gb) { 5269bdf108885a27ba05fae8501725649574d7c491bVladimir Marko TimingLogger timings("OatTest::DexFileInput", false, false); 5279bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 5289bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::vector<const char*> input_filenames; 5299bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 5309bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ScratchFile dex_file1; 5319bdf108885a27ba05fae8501725649574d7c491bVladimir Marko TestDexFileBuilder builder1; 5329bdf108885a27ba05fae8501725649574d7c491bVladimir Marko builder1.AddField("Lsome.TestClass;", "int", "someField"); 5339bdf108885a27ba05fae8501725649574d7c491bVladimir Marko builder1.AddMethod("Lsome.TestClass;", "()I", "foo"); 5349bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::unique_ptr<const DexFile> dex_file1_data = builder1.Build(dex_file1.GetFilename()); 5353a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 5363a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe MaybeModifyDexFileToFail(verify, dex_file1_data); 5373a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 5389bdf108885a27ba05fae8501725649574d7c491bVladimir Marko bool success = dex_file1.GetFile()->WriteFully(&dex_file1_data->GetHeader(), 5399bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file1_data->GetHeader().file_size_); 5409bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(success); 5419bdf108885a27ba05fae8501725649574d7c491bVladimir Marko success = dex_file1.GetFile()->Flush() == 0; 5429bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(success); 5439bdf108885a27ba05fae8501725649574d7c491bVladimir Marko input_filenames.push_back(dex_file1.GetFilename().c_str()); 5449bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 5459bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ScratchFile dex_file2; 5469bdf108885a27ba05fae8501725649574d7c491bVladimir Marko TestDexFileBuilder builder2; 5479bdf108885a27ba05fae8501725649574d7c491bVladimir Marko builder2.AddField("Land.AnotherTestClass;", "boolean", "someOtherField"); 5489bdf108885a27ba05fae8501725649574d7c491bVladimir Marko builder2.AddMethod("Land.AnotherTestClass;", "()J", "bar"); 5499bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::unique_ptr<const DexFile> dex_file2_data = builder2.Build(dex_file2.GetFilename()); 5503a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 5513a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe MaybeModifyDexFileToFail(verify, dex_file2_data); 5523a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 5539bdf108885a27ba05fae8501725649574d7c491bVladimir Marko success = dex_file2.GetFile()->WriteFully(&dex_file2_data->GetHeader(), 5549bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file2_data->GetHeader().file_size_); 5559bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(success); 5569bdf108885a27ba05fae8501725649574d7c491bVladimir Marko success = dex_file2.GetFile()->Flush() == 0; 5579bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(success); 5589bdf108885a27ba05fae8501725649574d7c491bVladimir Marko input_filenames.push_back(dex_file2.GetFilename().c_str()); 5599bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 5609bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ScratchFile oat_file; 5619bdf108885a27ba05fae8501725649574d7c491bVladimir Marko SafeMap<std::string, std::string> key_value_store; 5629bdf108885a27ba05fae8501725649574d7c491bVladimir Marko key_value_store.Put(OatHeader::kImageLocationKey, "test.art"); 5633a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe success = WriteElf(oat_file.GetFile(), input_filenames, key_value_store, verify); 5643a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 5653a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe // In verify mode, we expect failure. 5663a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe if (verify) { 5673a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_FALSE(success); 5683a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe return; 5693a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe } 5703a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 5719bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(success); 5729bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 5739bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::string error_msg; 5749bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(oat_file.GetFilename(), 5759bdf108885a27ba05fae8501725649574d7c491bVladimir Marko oat_file.GetFilename(), 5769bdf108885a27ba05fae8501725649574d7c491bVladimir Marko nullptr, 5779bdf108885a27ba05fae8501725649574d7c491bVladimir Marko nullptr, 5789bdf108885a27ba05fae8501725649574d7c491bVladimir Marko false, 5790b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier low_4gb, 5809bdf108885a27ba05fae8501725649574d7c491bVladimir Marko nullptr, 5819bdf108885a27ba05fae8501725649574d7c491bVladimir Marko &error_msg)); 5820b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier if (low_4gb) { 5830b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier uintptr_t begin = reinterpret_cast<uintptr_t>(opened_oat_file->Begin()); 5840b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier EXPECT_EQ(begin, static_cast<uint32_t>(begin)); 5850b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier } 5869bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(opened_oat_file != nullptr); 5879bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size()); 5889bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::unique_ptr<const DexFile> opened_dex_file1 = 5899bdf108885a27ba05fae8501725649574d7c491bVladimir Marko opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg); 5909bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::unique_ptr<const DexFile> opened_dex_file2 = 5919bdf108885a27ba05fae8501725649574d7c491bVladimir Marko opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg); 5929bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 5939bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_); 5949bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(), 5959bdf108885a27ba05fae8501725649574d7c491bVladimir Marko &opened_dex_file1->GetHeader(), 5969bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file1_data->GetHeader().file_size_)); 5979bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_EQ(dex_file1_data->GetLocation(), opened_dex_file1->GetLocation()); 5989bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 5999bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_); 6009bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(), 6019bdf108885a27ba05fae8501725649574d7c491bVladimir Marko &opened_dex_file2->GetHeader(), 6029bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file2_data->GetHeader().file_size_)); 6039bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_EQ(dex_file2_data->GetLocation(), opened_dex_file2->GetLocation()); 6049bdf108885a27ba05fae8501725649574d7c491bVladimir Marko} 6059bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 6063a2bd29d274f60fdcfabebb052078edef0190164Andreas GampeTEST_F(OatTest, DexFileInputCheckOutput) { 6070b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier TestDexFileInput(false, /*low_4gb*/false); 6080b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier} 6090b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier 6100b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu ChartierTEST_F(OatTest, DexFileInputCheckOutputLow4GB) { 6110b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier TestDexFileInput(false, /*low_4gb*/true); 6123a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe} 6133a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 6143a2bd29d274f60fdcfabebb052078edef0190164Andreas GampeTEST_F(OatTest, DexFileInputCheckVerifier) { 6150b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier TestDexFileInput(true, /*low_4gb*/false); 6163a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe} 6173a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 6183a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampevoid OatTest::TestZipFileInput(bool verify) { 6199bdf108885a27ba05fae8501725649574d7c491bVladimir Marko TimingLogger timings("OatTest::DexFileInput", false, false); 6209bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 6219bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ScratchFile zip_file; 6229bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ZipBuilder zip_builder(zip_file.GetFile()); 6239bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 6249bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ScratchFile dex_file1; 6259bdf108885a27ba05fae8501725649574d7c491bVladimir Marko TestDexFileBuilder builder1; 6269bdf108885a27ba05fae8501725649574d7c491bVladimir Marko builder1.AddField("Lsome.TestClass;", "long", "someField"); 6279bdf108885a27ba05fae8501725649574d7c491bVladimir Marko builder1.AddMethod("Lsome.TestClass;", "()D", "foo"); 6289bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::unique_ptr<const DexFile> dex_file1_data = builder1.Build(dex_file1.GetFilename()); 6293a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 6303a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe MaybeModifyDexFileToFail(verify, dex_file1_data); 6313a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 6329bdf108885a27ba05fae8501725649574d7c491bVladimir Marko bool success = dex_file1.GetFile()->WriteFully(&dex_file1_data->GetHeader(), 6339bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file1_data->GetHeader().file_size_); 6349bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(success); 6359bdf108885a27ba05fae8501725649574d7c491bVladimir Marko success = dex_file1.GetFile()->Flush() == 0; 6369bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(success); 6379bdf108885a27ba05fae8501725649574d7c491bVladimir Marko success = zip_builder.AddFile("classes.dex", 6389bdf108885a27ba05fae8501725649574d7c491bVladimir Marko &dex_file1_data->GetHeader(), 6399bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file1_data->GetHeader().file_size_); 6409bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(success); 6419bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 6429bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ScratchFile dex_file2; 6439bdf108885a27ba05fae8501725649574d7c491bVladimir Marko TestDexFileBuilder builder2; 6449bdf108885a27ba05fae8501725649574d7c491bVladimir Marko builder2.AddField("Land.AnotherTestClass;", "boolean", "someOtherField"); 6459bdf108885a27ba05fae8501725649574d7c491bVladimir Marko builder2.AddMethod("Land.AnotherTestClass;", "()J", "bar"); 6469bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::unique_ptr<const DexFile> dex_file2_data = builder2.Build(dex_file2.GetFilename()); 6473a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 6483a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe MaybeModifyDexFileToFail(verify, dex_file2_data); 6493a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 6509bdf108885a27ba05fae8501725649574d7c491bVladimir Marko success = dex_file2.GetFile()->WriteFully(&dex_file2_data->GetHeader(), 6519bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file2_data->GetHeader().file_size_); 6529bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(success); 6539bdf108885a27ba05fae8501725649574d7c491bVladimir Marko success = dex_file2.GetFile()->Flush() == 0; 6549bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(success); 6559bdf108885a27ba05fae8501725649574d7c491bVladimir Marko success = zip_builder.AddFile("classes2.dex", 6569bdf108885a27ba05fae8501725649574d7c491bVladimir Marko &dex_file2_data->GetHeader(), 6579bdf108885a27ba05fae8501725649574d7c491bVladimir Marko dex_file2_data->GetHeader().file_size_); 6589bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(success); 6599bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 6609bdf108885a27ba05fae8501725649574d7c491bVladimir Marko success = zip_builder.Finish(); 6619bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_TRUE(success) << strerror(errno); 6629bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 6639bdf108885a27ba05fae8501725649574d7c491bVladimir Marko SafeMap<std::string, std::string> key_value_store; 6649bdf108885a27ba05fae8501725649574d7c491bVladimir Marko key_value_store.Put(OatHeader::kImageLocationKey, "test.art"); 6659bdf108885a27ba05fae8501725649574d7c491bVladimir Marko { 6669bdf108885a27ba05fae8501725649574d7c491bVladimir Marko // Test using the AddDexFileSource() interface with the zip file. 6679bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::vector<const char*> input_filenames { zip_file.GetFilename().c_str() }; // NOLINT [readability/braces] [4] 6689bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 6699bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ScratchFile oat_file; 6703a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe success = WriteElf(oat_file.GetFile(), input_filenames, key_value_store, verify); 6719bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 6723a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe if (verify) { 6733a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_FALSE(success); 6743a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe } else { 6753a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_TRUE(success); 6763a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 6773a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe std::string error_msg; 6783a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(oat_file.GetFilename(), 6793a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe oat_file.GetFilename(), 6803a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe nullptr, 6813a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe nullptr, 6823a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe false, 6830b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier /*low_4gb*/false, 6843a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe nullptr, 6853a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe &error_msg)); 6863a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_TRUE(opened_oat_file != nullptr); 6873a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size()); 6883a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe std::unique_ptr<const DexFile> opened_dex_file1 = 6893a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg); 6903a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe std::unique_ptr<const DexFile> opened_dex_file2 = 6913a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg); 6923a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 6933a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_); 6943a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(), 6953a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe &opened_dex_file1->GetHeader(), 6963a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe dex_file1_data->GetHeader().file_size_)); 6973a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(DexFile::GetMultiDexLocation(0, zip_file.GetFilename().c_str()), 6983a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe opened_dex_file1->GetLocation()); 6993a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 7003a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_); 7013a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(), 7023a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe &opened_dex_file2->GetHeader(), 7033a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe dex_file2_data->GetHeader().file_size_)); 7043a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(DexFile::GetMultiDexLocation(1, zip_file.GetFilename().c_str()), 7053a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe opened_dex_file2->GetLocation()); 7063a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe } 7079bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 7089bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 7099bdf108885a27ba05fae8501725649574d7c491bVladimir Marko { 7109bdf108885a27ba05fae8501725649574d7c491bVladimir Marko // Test using the AddZipDexFileSource() interface with the zip file handle. 7119bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ScopedFd zip_fd(dup(zip_file.GetFd())); 7129bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ASSERT_NE(-1, zip_fd.get()); 7139bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 7149bdf108885a27ba05fae8501725649574d7c491bVladimir Marko ScratchFile oat_file; 7159bdf108885a27ba05fae8501725649574d7c491bVladimir Marko success = WriteElf(oat_file.GetFile(), 7169bdf108885a27ba05fae8501725649574d7c491bVladimir Marko std::move(zip_fd), 7179bdf108885a27ba05fae8501725649574d7c491bVladimir Marko zip_file.GetFilename().c_str(), 7183a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe key_value_store, 7193a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe verify); 7203a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe if (verify) { 7213a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_FALSE(success); 7223a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe } else { 7233a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_TRUE(success); 7243a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 7253a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe std::string error_msg; 7263a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(oat_file.GetFilename(), 7273a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe oat_file.GetFilename(), 7283a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe nullptr, 7293a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe nullptr, 7303a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe false, 7310b4cbd0c2a75b47ae09d21e5d73d2b1709cb5b9eMathieu Chartier /*low_4gb*/false, 7323a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe nullptr, 7333a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe &error_msg)); 7343a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_TRUE(opened_oat_file != nullptr); 7353a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size()); 7363a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe std::unique_ptr<const DexFile> opened_dex_file1 = 7373a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg); 7383a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe std::unique_ptr<const DexFile> opened_dex_file2 = 7393a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg); 7403a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 7413a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_); 7423a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(), 7433a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe &opened_dex_file1->GetHeader(), 7443a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe dex_file1_data->GetHeader().file_size_)); 7453a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(DexFile::GetMultiDexLocation(0, zip_file.GetFilename().c_str()), 7463a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe opened_dex_file1->GetLocation()); 7473a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 7483a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_); 7493a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(), 7503a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe &opened_dex_file2->GetHeader(), 7513a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe dex_file2_data->GetHeader().file_size_)); 7523a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe ASSERT_EQ(DexFile::GetMultiDexLocation(1, zip_file.GetFilename().c_str()), 7533a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe opened_dex_file2->GetLocation()); 7543a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe } 7559bdf108885a27ba05fae8501725649574d7c491bVladimir Marko } 7569bdf108885a27ba05fae8501725649574d7c491bVladimir Marko} 7579bdf108885a27ba05fae8501725649574d7c491bVladimir Marko 7583a2bd29d274f60fdcfabebb052078edef0190164Andreas GampeTEST_F(OatTest, ZipFileInputCheckOutput) { 7593a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe TestZipFileInput(false); 7603a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe} 7613a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 7623a2bd29d274f60fdcfabebb052078edef0190164Andreas GampeTEST_F(OatTest, ZipFileInputCheckVerifier) { 7633a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe TestZipFileInput(true); 7643a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe} 7653a2bd29d274f60fdcfabebb052078edef0190164Andreas Gampe 7662c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff HaoTEST_F(OatTest, UpdateChecksum) { 7672c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao InstructionSet insn_set = kX86; 7682c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao std::string error_msg; 7692c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao std::unique_ptr<const InstructionSetFeatures> insn_features( 7702c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao InstructionSetFeatures::FromVariant(insn_set, "default", &error_msg)); 7712c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao ASSERT_TRUE(insn_features.get() != nullptr) << error_msg; 7722c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao std::unique_ptr<OatHeader> oat_header(OatHeader::Create(insn_set, 7732c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao insn_features.get(), 7742c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao 0u, 7752c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao nullptr)); 7762c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao // The starting adler32 value is 1. 7772c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao EXPECT_EQ(1U, oat_header->GetChecksum()); 7782c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao 7792c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao oat_header->UpdateChecksum(OatHeader::kOatMagic, sizeof(OatHeader::kOatMagic)); 7802c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao EXPECT_EQ(64291151U, oat_header->GetChecksum()); 7812c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao 7822c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao // Make sure that null data does not reset the checksum. 7832c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao oat_header->UpdateChecksum(nullptr, 0); 7842c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao EXPECT_EQ(64291151U, oat_header->GetChecksum()); 7852c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao 7862c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao oat_header->UpdateChecksum(OatHeader::kOatMagic, sizeof(OatHeader::kOatMagic)); 7872c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao EXPECT_EQ(216138397U, oat_header->GetChecksum()); 7882c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao} 7892c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao 790e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} // namespace art 791