diff options
| -rw-r--r-- | build/Android.gtest.mk | 1 | ||||
| -rw-r--r-- | compiler/elf_builder.h | 19 | ||||
| -rw-r--r-- | compiler/oat_test.cc | 150 | ||||
| -rw-r--r-- | runtime/runtime.h | 5 |
4 files changed, 143 insertions, 32 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index ff41736a35..0afec2d5ef 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -74,6 +74,7 @@ ART_GTEST_jni_compiler_test_DEX_DEPS := MyClassNatives ART_GTEST_jni_internal_test_DEX_DEPS := AllFields StaticLeafMethods ART_GTEST_oat_file_assistant_test_DEX_DEPS := Main MainStripped MultiDex MultiDexModifiedSecondary Nested ART_GTEST_oat_file_test_DEX_DEPS := Main MultiDex +ART_GTEST_oat_test_DEX_DEPS := Main ART_GTEST_object_test_DEX_DEPS := ProtoCompare ProtoCompare2 StaticsFromCode XandY ART_GTEST_proxy_test_DEX_DEPS := Interfaces ART_GTEST_reflection_test_DEX_DEPS := Main NonStaticLeafMethods StaticLeafMethods diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h index 4e2b15d7b0..e977798ab1 100644 --- a/compiler/elf_builder.h +++ b/compiler/elf_builder.h @@ -599,6 +599,7 @@ class ElfBuilder FINAL { // This is the order in which they will be written. std::vector<Section*> sections; sections.push_back(&rodata_); + // Need to write text to update checksum of header even if it is empty. sections.push_back(&text_); if (bss_.GetSize() != 0u) { sections.push_back(&bss_); @@ -682,7 +683,9 @@ class ElfBuilder FINAL { const Elf_Shdr* rodata = rodata_.GetHeader(); program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R, 0, rodata->sh_offset + rodata->sh_size, rodata->sh_addralign)); - program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R | PF_X, text_)); + if (text_.GetHeader()->sh_size != 0u) { + program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R | PF_X, text_)); + } if (bss_.GetHeader()->sh_size != 0u) { program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R | PF_W, bss_)); } @@ -909,10 +912,16 @@ class ElfBuilder FINAL { void BuildDynsymSection() { dynsym_.AddSymbol("oatdata", &rodata_, 0, true, rodata_.GetSize(), STB_GLOBAL, STT_OBJECT); - dynsym_.AddSymbol("oatexec", &text_, 0, true, - text_.GetSize(), STB_GLOBAL, STT_OBJECT); - dynsym_.AddSymbol("oatlastword", &text_, text_.GetSize() - 4, - true, 4, STB_GLOBAL, STT_OBJECT); + if (text_.GetSize() != 0u) { + dynsym_.AddSymbol("oatexec", &text_, 0, true, + text_.GetSize(), STB_GLOBAL, STT_OBJECT); + dynsym_.AddSymbol("oatlastword", &text_, text_.GetSize() - 4, + true, 4, STB_GLOBAL, STT_OBJECT); + } else if (rodata_.GetSize() != 0) { + // rodata_ be size 0 for dwarf_test. + dynsym_.AddSymbol("oatlastword", &rodata_, rodata_.GetSize() - 4, + true, 4, STB_GLOBAL, STT_OBJECT); + } if (bss_.GetSize() != 0u) { dynsym_.AddSymbol("oatbss", &bss_, 0, true, bss_.GetSize(), STB_GLOBAL, STT_OBJECT); diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index ea3cb667e2..fb69f8e8d4 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -16,6 +16,7 @@ #include "arch/instruction_set_features.h" #include "art_method-inl.h" +#include "base/unix_file/fd_file.h" #include "class_linker.h" #include "common_compiler_test.h" #include "compiled_method.h" @@ -37,6 +38,16 @@ namespace art { +NO_RETURN static void Usage(const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + std::string error; + StringAppendV(&error, fmt, ap); + LOG(FATAL) << error; + va_end(ap); + UNREACHABLE(); +} + class OatTest : public CommonCompilerTest { protected: static const bool kCompile = false; // DISABLED_ due to the time to compile libcore @@ -71,6 +82,66 @@ class OatTest : public CommonCompilerTest { CHECK_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size)); } } + + void SetupCompiler(Compiler::Kind compiler_kind, + InstructionSet insn_set, + const std::vector<std::string>& compiler_options, + /*out*/std::string* error_msg) { + ASSERT_TRUE(error_msg != nullptr); + insn_features_.reset(InstructionSetFeatures::FromVariant(insn_set, "default", error_msg)); + ASSERT_TRUE(insn_features_ != nullptr) << error_msg; + compiler_options_.reset(new CompilerOptions); + for (const std::string& option : compiler_options) { + compiler_options_->ParseCompilerOption(option, Usage); + } + verification_results_.reset(new VerificationResults(compiler_options_.get())); + method_inliner_map_.reset(new DexFileToMethodInlinerMap); + callbacks_.reset(new QuickCompilerCallbacks(verification_results_.get(), + method_inliner_map_.get(), + CompilerCallbacks::CallbackMode::kCompileApp)); + Runtime::Current()->SetCompilerCallbacks(callbacks_.get()); + timer_.reset(new CumulativeLogger("Compilation times")); + compiler_driver_.reset(new CompilerDriver(compiler_options_.get(), + verification_results_.get(), + method_inliner_map_.get(), + compiler_kind, + insn_set, + insn_features_.get(), + false, + nullptr, + nullptr, + nullptr, + 2, + true, + true, + "", + false, + timer_.get(), + -1, + "")); + } + + bool WriteElf(File* file, + const std::vector<const DexFile*>& dex_files, + SafeMap<std::string, std::string>& key_value_store) { + TimingLogger timings("WriteElf", false, false); + OatWriter oat_writer(dex_files, + 42U, + 4096U, + 0, + compiler_driver_.get(), + nullptr, + &timings, + &key_value_store); + return compiler_driver_->WriteElf(GetTestAndroidRoot(), + !kIsTargetBuild, + dex_files, + &oat_writer, + file); + } + + std::unique_ptr<const InstructionSetFeatures> insn_features_; + std::unique_ptr<QuickCompilerCallbacks> callbacks_; }; TEST_F(OatTest, WriteRead) { @@ -80,21 +151,9 @@ TEST_F(OatTest, WriteRead) { // TODO: make selectable. Compiler::Kind compiler_kind = Compiler::kQuick; InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86; - std::string error_msg; - std::unique_ptr<const InstructionSetFeatures> insn_features( - InstructionSetFeatures::FromVariant(insn_set, "default", &error_msg)); - ASSERT_TRUE(insn_features.get() != nullptr) << error_msg; - compiler_options_.reset(new CompilerOptions); - verification_results_.reset(new VerificationResults(compiler_options_.get())); - method_inliner_map_.reset(new DexFileToMethodInlinerMap); - timer_.reset(new CumulativeLogger("Compilation times")); - compiler_driver_.reset(new CompilerDriver(compiler_options_.get(), - verification_results_.get(), - method_inliner_map_.get(), - compiler_kind, insn_set, - insn_features.get(), false, nullptr, nullptr, nullptr, - 2, true, true, "", false, timer_.get(), -1, "")); + SetupCompiler(compiler_kind, insn_set, std::vector<std::string>(), /*out*/ &error_msg); + jobject class_loader = nullptr; if (kCompile) { TimingLogger timings2("OatTest::WriteRead", false, false); @@ -105,19 +164,7 @@ TEST_F(OatTest, WriteRead) { ScratchFile tmp; SafeMap<std::string, std::string> key_value_store; key_value_store.Put(OatHeader::kImageLocationKey, "lue.art"); - OatWriter oat_writer(class_linker->GetBootClassPath(), - 42U, - 4096U, - 0, - compiler_driver_.get(), - nullptr, - &timings, - &key_value_store); - bool success = compiler_driver_->WriteElf(GetTestAndroidRoot(), - !kIsTargetBuild, - class_linker->GetBootClassPath(), - &oat_writer, - tmp.GetFile()); + bool success = WriteElf(tmp.GetFile(), class_linker->GetBootClassPath(), key_value_store); ASSERT_TRUE(success); if (kCompile) { // OatWriter strips the code, regenerate to compare @@ -212,4 +259,53 @@ TEST_F(OatTest, OatHeaderIsValid) { ASSERT_FALSE(oat_header->IsValid()); } +TEST_F(OatTest, EmptyTextSection) { + TimingLogger timings("OatTest::EmptyTextSection", false, false); + + // TODO: make selectable. + Compiler::Kind compiler_kind = Compiler::kQuick; + InstructionSet insn_set = kRuntimeISA; + if (insn_set == kArm) insn_set = kThumb2; + std::string error_msg; + std::vector<std::string> compiler_options; + compiler_options.push_back("--compiler-filter=verify-at-runtime"); + SetupCompiler(compiler_kind, insn_set, compiler_options, /*out*/ &error_msg); + + jobject class_loader; + { + ScopedObjectAccess soa(Thread::Current()); + class_loader = LoadDex("Main"); + } + ASSERT_TRUE(class_loader != nullptr); + std::vector<const DexFile*> dex_files = GetDexFiles(class_loader); + ASSERT_TRUE(!dex_files.empty()); + + ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); + for (const DexFile* dex_file : dex_files) { + ScopedObjectAccess soa(Thread::Current()); + class_linker->RegisterDexFile( + *dex_file, + class_linker->GetOrCreateAllocatorForClassLoader( + soa.Decode<mirror::ClassLoader*>(class_loader))); + } + compiler_driver_->SetDexFilesForOatFile(dex_files); + compiler_driver_->CompileAll(class_loader, dex_files, &timings); + + ScratchFile tmp; + SafeMap<std::string, std::string> key_value_store; + key_value_store.Put(OatHeader::kImageLocationKey, "test.art"); + bool success = WriteElf(tmp.GetFile(), dex_files, key_value_store); + ASSERT_TRUE(success); + + std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), + tmp.GetFilename(), + nullptr, + nullptr, + false, + nullptr, + &error_msg)); + ASSERT_TRUE(oat_file != nullptr); + EXPECT_LT(static_cast<size_t>(oat_file->Size()), static_cast<size_t>(tmp.GetFile()->GetLength())); +} + } // namespace art diff --git a/runtime/runtime.h b/runtime/runtime.h index 7b1fdb21c4..a8ba19bd95 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -151,6 +151,11 @@ class Runtime { return compiler_callbacks_; } + void SetCompilerCallbacks(CompilerCallbacks* callbacks) { + CHECK(callbacks != nullptr); + compiler_callbacks_ = callbacks; + } + bool IsZygote() const { return is_zygote_; } |