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
diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc
index 33c46d7..a626729 100644
--- a/compiler/debug/elf_debug_writer.cc
+++ b/compiler/debug/elf_debug_writer.cc
@@ -108,29 +108,32 @@
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 @@
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 d24ca9b..a47bf07 100644
--- a/compiler/debug/elf_debug_writer.h
+++ b/compiler/debug/elf_debug_writer.h
@@ -43,14 +43,15 @@
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 9b8ec35..78b8e27 100644
--- a/compiler/debug/elf_gnu_debugdata_writer.h
+++ b/compiler/debug/elf_gnu_debugdata_writer.h
@@ -80,7 +80,7 @@
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 @@
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 0907e10..57e010f 100644
--- a/compiler/debug/elf_symtab_writer.h
+++ b/compiler/debug/elf_symtab_writer.h
@@ -79,8 +79,9 @@
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);