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