diff options
author | 2017-12-11 16:06:29 +0000 | |
---|---|---|
committer | 2017-12-14 13:52:07 +0000 | |
commit | f4886df5e72fa21eddfc4cc7860f4154929b3380 (patch) | |
tree | 897e74d9da4e92faae5c24350fa2f999cbfb2b1e /compiler | |
parent | 7eb4333d0b60a13f9d3126eadef9eb16c399662a (diff) |
Add mini-debug-info generation mode for JIT.
This excludes everything that is not needed for backtraces and
compresses the resulting ELF file (wrapped in another ELF file).
This approximately halves the size of the debug data for JIT.
The vast majority of the data is the overhead of ELF header.
We could amortize this by storing more methods per ELF file.
It also adds NOBITS .text section to all debug ELF files,
as that seems necessary for gdb to find the symbols.
On the other hand, it removes .rodata from debug ELF files.
Test: Manually tested that gdb can use this data to unwind.
Test: m test-art-host-gtest
Test: testrunner.py --optimizing --host
Test: testrunner.py -t 137-cfi
Change-Id: Ic0a2dfa953cb79973a7b2ae99d32018599e61171
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/debug/elf_debug_writer.cc | 40 | ||||
-rw-r--r-- | compiler/debug/elf_debug_writer.h | 7 | ||||
-rw-r--r-- | compiler/debug/elf_gnu_debugdata_writer.h | 10 | ||||
-rw-r--r-- | compiler/debug/elf_symtab_writer.h | 5 | ||||
-rw-r--r-- | compiler/linker/elf_builder.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 18 |
6 files changed, 52 insertions, 32 deletions
diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc index 33c46d7e1f..a6267292bf 100644 --- a/compiler/debug/elf_debug_writer.cc +++ b/compiler/debug/elf_debug_writer.cc @@ -108,29 +108,32 @@ void WriteDebugInfo(linker::ElfBuilder<ElfTypes>* builder, std::vector<uint8_t> MakeMiniDebugInfo( InstructionSet isa, const InstructionSetFeatures* features, - size_t rodata_size, + uint64_t text_address, size_t text_size, const ArrayRef<const MethodDebugInfo>& method_infos) { if (Is64BitInstructionSet(isa)) { return MakeMiniDebugInfoInternal<ElfTypes64>(isa, features, - rodata_size, + text_address, text_size, method_infos); } else { return MakeMiniDebugInfoInternal<ElfTypes32>(isa, features, - rodata_size, + text_address, text_size, method_infos); } } template <typename ElfTypes> -static std::vector<uint8_t> WriteDebugElfFileForMethodsInternal( +static std::vector<uint8_t> MakeElfFileForJITInternal( InstructionSet isa, const InstructionSetFeatures* features, - const ArrayRef<const MethodDebugInfo>& method_infos) { + bool mini_debug_info, + const MethodDebugInfo& mi) { + CHECK_EQ(mi.is_code_address_text_relative, false); + ArrayRef<const MethodDebugInfo> method_infos(&mi, 1); std::vector<uint8_t> buffer; buffer.reserve(KB); linker::VectorOutputStream out("Debug ELF file", &buffer); @@ -138,23 +141,34 @@ static std::vector<uint8_t> WriteDebugElfFileForMethodsInternal( new linker::ElfBuilder<ElfTypes>(isa, features, &out)); // No program headers since the ELF file is not linked and has no allocated sections. builder->Start(false /* write_program_headers */); - WriteDebugInfo(builder.get(), - method_infos, - dwarf::DW_DEBUG_FRAME_FORMAT, - false /* write_oat_patches */); + if (mini_debug_info) { + std::vector<uint8_t> mdi = MakeMiniDebugInfo(isa, + features, + mi.code_address, + mi.code_size, + method_infos); + builder->WriteSection(".gnu_debugdata", &mdi); + } else { + builder->GetText()->AllocateVirtualMemory(mi.code_address, mi.code_size); + WriteDebugInfo(builder.get(), + method_infos, + dwarf::DW_DEBUG_FRAME_FORMAT, + false /* write_oat_patches */); + } builder->End(); CHECK(builder->Good()); return buffer; } -std::vector<uint8_t> WriteDebugElfFileForMethods( +std::vector<uint8_t> MakeElfFileForJIT( InstructionSet isa, const InstructionSetFeatures* features, - const ArrayRef<const MethodDebugInfo>& method_infos) { + bool mini_debug_info, + const MethodDebugInfo& method_info) { if (Is64BitInstructionSet(isa)) { - return WriteDebugElfFileForMethodsInternal<ElfTypes64>(isa, features, method_infos); + return MakeElfFileForJITInternal<ElfTypes64>(isa, features, mini_debug_info, method_info); } else { - return WriteDebugElfFileForMethodsInternal<ElfTypes32>(isa, features, method_infos); + return MakeElfFileForJITInternal<ElfTypes32>(isa, features, mini_debug_info, method_info); } } diff --git a/compiler/debug/elf_debug_writer.h b/compiler/debug/elf_debug_writer.h index d24ca9b203..a47bf076b9 100644 --- a/compiler/debug/elf_debug_writer.h +++ b/compiler/debug/elf_debug_writer.h @@ -43,14 +43,15 @@ void WriteDebugInfo( std::vector<uint8_t> MakeMiniDebugInfo( InstructionSet isa, const InstructionSetFeatures* features, - size_t rodata_section_size, + uint64_t text_section_address, size_t text_section_size, const ArrayRef<const MethodDebugInfo>& method_infos); -std::vector<uint8_t> WriteDebugElfFileForMethods( +std::vector<uint8_t> MakeElfFileForJIT( InstructionSet isa, const InstructionSetFeatures* features, - const ArrayRef<const MethodDebugInfo>& method_infos); + bool mini_debug_info, + const MethodDebugInfo& method_info); std::vector<uint8_t> WriteDebugElfFileForClasses( InstructionSet isa, diff --git a/compiler/debug/elf_gnu_debugdata_writer.h b/compiler/debug/elf_gnu_debugdata_writer.h index 9b8ec35ed1..78b8e2780c 100644 --- a/compiler/debug/elf_gnu_debugdata_writer.h +++ b/compiler/debug/elf_gnu_debugdata_writer.h @@ -80,7 +80,7 @@ template <typename ElfTypes> static std::vector<uint8_t> MakeMiniDebugInfoInternal( InstructionSet isa, const InstructionSetFeatures* features, - size_t rodata_section_size, + typename ElfTypes::Addr text_section_address, size_t text_section_size, const ArrayRef<const MethodDebugInfo>& method_infos) { std::vector<uint8_t> buffer; @@ -88,11 +88,9 @@ static std::vector<uint8_t> MakeMiniDebugInfoInternal( linker::VectorOutputStream out("Mini-debug-info ELF file", &buffer); std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder( new linker::ElfBuilder<ElfTypes>(isa, features, &out)); - builder->Start(); - // Mirror .rodata and .text as NOBITS sections. - // It is needed to detected relocations after compression. - builder->GetRoData()->AllocateVirtualMemory(rodata_section_size); - builder->GetText()->AllocateVirtualMemory(text_section_size); + builder->Start(false /* write_program_headers */); + // Mirror .text as NOBITS section since the added symbols will reference it. + builder->GetText()->AllocateVirtualMemory(text_section_address, text_section_size); WriteDebugSymbols(builder.get(), method_infos, false /* with_signature */); WriteCFISection(builder.get(), method_infos, diff --git a/compiler/debug/elf_symtab_writer.h b/compiler/debug/elf_symtab_writer.h index 0907e102a0..57e010f232 100644 --- a/compiler/debug/elf_symtab_writer.h +++ b/compiler/debug/elf_symtab_writer.h @@ -79,8 +79,9 @@ static void WriteDebugSymbols(linker::ElfBuilder<ElfTypes>* builder, last_name_offset = name_offset; } - const auto* text = info.is_code_address_text_relative ? builder->GetText() : nullptr; - uint64_t address = info.code_address + (text != nullptr ? text->GetAddress() : 0); + const auto* text = builder->GetText(); + uint64_t address = info.code_address; + address += info.is_code_address_text_relative ? text->GetAddress() : 0; // Add in code delta, e.g., thumb bit 0 for Thumb2 code. address += CompiledMethod::CodeDelta(info.isa); symtab->Add(name_offset, text, address, info.code_size, STB_GLOBAL, STT_FUNC); diff --git a/compiler/linker/elf_builder.h b/compiler/linker/elf_builder.h index 3710878ea1..aa3cd98595 100644 --- a/compiler/linker/elf_builder.h +++ b/compiler/linker/elf_builder.h @@ -203,13 +203,13 @@ class ElfBuilder FINAL { if (section_index_ == 0) { std::vector<Section*>& sections = owner_->sections_; Elf_Word last = sections.empty() ? PF_R : sections.back()->phdr_flags_; - if (owner_->write_program_headers_ && phdr_flags_ != last) { + if (phdr_flags_ != last) { header_.sh_addralign = kPageSize; // Page-align if R/W/X flags changed. } sections.push_back(this); section_index_ = sections.size(); // First ELF section has index 1. } - return header_.sh_addralign; + return owner_->write_program_headers_ ? header_.sh_addralign : 1; } ElfBuilder<ElfTypes>* owner_; diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 73c72fc57a..24b1a123ee 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -1224,7 +1224,7 @@ bool OptimizingCompiler::JitCompile(Thread* self, } const CompilerOptions& compiler_options = GetCompilerDriver()->GetCompilerOptions(); - if (compiler_options.GetGenerateDebugInfo()) { + if (compiler_options.GenerateAnyDebugInfo()) { const auto* method_header = reinterpret_cast<const OatQuickMethodHeader*>(code); const uintptr_t code_address = reinterpret_cast<uintptr_t>(method_header->GetCode()); debug::MethodDebugInfo info = {}; @@ -1244,10 +1244,13 @@ bool OptimizingCompiler::JitCompile(Thread* self, info.frame_size_in_bytes = method_header->GetFrameSizeInBytes(); info.code_info = nullptr; info.cfi = jni_compiled_method.GetCfi(); - std::vector<uint8_t> elf_file = debug::WriteDebugElfFileForMethods( + // If both flags are passed, generate full debug info. + const bool mini_debug_info = !compiler_options.GetGenerateDebugInfo(); + std::vector<uint8_t> elf_file = debug::MakeElfFileForJIT( GetCompilerDriver()->GetInstructionSet(), GetCompilerDriver()->GetInstructionSetFeatures(), - ArrayRef<const debug::MethodDebugInfo>(&info, 1)); + mini_debug_info, + info); CreateJITCodeEntryForAddress(code_address, std::move(elf_file)); } @@ -1352,7 +1355,7 @@ bool OptimizingCompiler::JitCompile(Thread* self, } const CompilerOptions& compiler_options = GetCompilerDriver()->GetCompilerOptions(); - if (compiler_options.GetGenerateDebugInfo()) { + if (compiler_options.GenerateAnyDebugInfo()) { const auto* method_header = reinterpret_cast<const OatQuickMethodHeader*>(code); const uintptr_t code_address = reinterpret_cast<uintptr_t>(method_header->GetCode()); debug::MethodDebugInfo info = {}; @@ -1372,10 +1375,13 @@ bool OptimizingCompiler::JitCompile(Thread* self, info.frame_size_in_bytes = method_header->GetFrameSizeInBytes(); info.code_info = stack_map_size == 0 ? nullptr : stack_map_data; info.cfi = ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data()); - std::vector<uint8_t> elf_file = debug::WriteDebugElfFileForMethods( + // If both flags are passed, generate full debug info. + const bool mini_debug_info = !compiler_options.GetGenerateDebugInfo(); + std::vector<uint8_t> elf_file = debug::MakeElfFileForJIT( GetCompilerDriver()->GetInstructionSet(), GetCompilerDriver()->GetInstructionSetFeatures(), - ArrayRef<const debug::MethodDebugInfo>(&info, 1)); + mini_debug_info, + info); CreateJITCodeEntryForAddress(code_address, std::move(elf_file)); } |