diff options
author | 2015-12-23 12:10:14 +0000 | |
---|---|---|
committer | 2015-12-23 12:10:14 +0000 | |
commit | d674bf7ba2a209790cea8ef8d935480ef515c9e1 (patch) | |
tree | 0bcd337212b37fe09c46d095b0d6e1f193a0e4d4 | |
parent | 975dd7279694f345bd4fc31b04ff3275f3082961 (diff) | |
parent | e0febdfc2d9585d0d1b4a562b8e44d9058c71c37 (diff) |
Merge "Move debug symbol writing code to elf_writer_debug.cc"
-rw-r--r-- | compiler/elf_writer_debug.cc | 100 | ||||
-rw-r--r-- | compiler/elf_writer_debug.h | 12 | ||||
-rw-r--r-- | compiler/elf_writer_quick.cc | 80 |
3 files changed, 92 insertions, 100 deletions
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc index 06553a6d62..2bc8c89f73 100644 --- a/compiler/elf_writer_debug.cc +++ b/compiler/elf_writer_debug.cc @@ -36,6 +36,15 @@ namespace art { namespace dwarf { +// The ARM specification defines three special mapping symbols +// $a, $t and $d which mark ARM, Thumb and data ranges respectively. +// These symbols can be used by tools, for example, to pretty +// print instructions correctly. Objdump will use them if they +// exist, but it will still work well without them. +// However, these extra symbols take space, so let's just generate +// one symbol which marks the whole .text section as code. +constexpr bool kGenerateSingleArmMappingSymbol = true; + static Reg GetDwarfCoreReg(InstructionSet isa, int machine_reg) { switch (isa) { case kArm: @@ -207,8 +216,7 @@ template<typename ElfTypes> void WriteCFISection(ElfBuilder<ElfTypes>* builder, const ArrayRef<const MethodDebugInfo>& method_infos, CFIFormat format) { - CHECK(format == dwarf::DW_DEBUG_FRAME_FORMAT || - format == dwarf::DW_EH_FRAME_FORMAT); + CHECK(format == DW_DEBUG_FRAME_FORMAT || format == DW_EH_FRAME_FORMAT); typedef typename ElfTypes::Addr Elf_Addr; std::vector<uint32_t> binary_search_table; @@ -220,7 +228,7 @@ void WriteCFISection(ElfBuilder<ElfTypes>* builder, } // Write .eh_frame/.debug_frame section. - auto* cfi_section = (format == dwarf::DW_DEBUG_FRAME_FORMAT + auto* cfi_section = (format == DW_DEBUG_FRAME_FORMAT ? builder->GetDebugFrame() : builder->GetEhFrame()); { @@ -1134,21 +1142,87 @@ void WriteDebugSections(ElfBuilder<ElfTypes>* builder, } } +template <typename ElfTypes> +void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, + const ArrayRef<const MethodDebugInfo>& method_infos) { + bool generated_mapping_symbol = false; + auto* strtab = builder->GetStrTab(); + auto* symtab = builder->GetSymTab(); + + if (method_infos.empty()) { + return; + } + + // Find all addresses (low_pc) which contain deduped methods. + // The first instance of method is not marked deduped_, but the rest is. + std::unordered_set<uint32_t> deduped_addresses; + for (const MethodDebugInfo& info : method_infos) { + if (info.deduped_) { + deduped_addresses.insert(info.low_pc_); + } + } + + strtab->Start(); + strtab->Write(""); // strtab should start with empty string. + for (const MethodDebugInfo& info : method_infos) { + if (info.deduped_) { + continue; // Add symbol only for the first instance. + } + std::string name = PrettyMethod(info.dex_method_index_, *info.dex_file_, true); + if (deduped_addresses.find(info.low_pc_) != deduped_addresses.end()) { + name += " [DEDUPED]"; + } + + uint32_t low_pc = info.low_pc_; + // Add in code delta, e.g., thumb bit 0 for Thumb2 code. + low_pc += info.compiled_method_->CodeDelta(); + symtab->Add(strtab->Write(name), builder->GetText(), low_pc, + true, info.high_pc_ - info.low_pc_, STB_GLOBAL, STT_FUNC); + + // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2 + // instructions, so that disassembler tools can correctly disassemble. + // Note that even if we generate just a single mapping symbol, ARM's Streamline + // requires it to match function symbol. Just address 0 does not work. + if (info.compiled_method_->GetInstructionSet() == kThumb2) { + if (!generated_mapping_symbol || !kGenerateSingleArmMappingSymbol) { + symtab->Add(strtab->Write("$t"), builder->GetText(), info.low_pc_ & ~1, + true, 0, STB_LOCAL, STT_NOTYPE); + generated_mapping_symbol = true; + } + } + } + strtab->End(); + + // Symbols are buffered and written after names (because they are smaller). + // We could also do two passes in this function to avoid the buffering. + symtab->Start(); + symtab->Write(); + symtab->End(); +} + +template <typename ElfTypes> +void WriteDebugInfo(ElfBuilder<ElfTypes>* builder, + const ArrayRef<const MethodDebugInfo>& method_infos, + CFIFormat cfi_format) { + if (!method_infos.empty()) { + // Add methods to .symtab. + WriteDebugSymbols(builder, method_infos); + // Generate CFI (stack unwinding information). + WriteCFISection(builder, method_infos, cfi_format); + // Write DWARF .debug_* sections. + WriteDebugSections(builder, method_infos); + } +} + // Explicit instantiations -template void WriteCFISection<ElfTypes32>( +template void WriteDebugInfo<ElfTypes32>( ElfBuilder<ElfTypes32>* builder, const ArrayRef<const MethodDebugInfo>& method_infos, - CFIFormat format); -template void WriteCFISection<ElfTypes64>( + CFIFormat cfi_format); +template void WriteDebugInfo<ElfTypes64>( ElfBuilder<ElfTypes64>* builder, const ArrayRef<const MethodDebugInfo>& method_infos, - CFIFormat format); -template void WriteDebugSections<ElfTypes32>( - ElfBuilder<ElfTypes32>* builder, - const ArrayRef<const MethodDebugInfo>& method_infos); -template void WriteDebugSections<ElfTypes64>( - ElfBuilder<ElfTypes64>* builder, - const ArrayRef<const MethodDebugInfo>& method_infos); + CFIFormat cfi_format); } // namespace dwarf } // namespace art diff --git a/compiler/elf_writer_debug.h b/compiler/elf_writer_debug.h index 9ed102f91b..7ec0be185a 100644 --- a/compiler/elf_writer_debug.h +++ b/compiler/elf_writer_debug.h @@ -25,14 +25,10 @@ namespace art { namespace dwarf { -template<typename ElfTypes> -void WriteCFISection(ElfBuilder<ElfTypes>* builder, - const ArrayRef<const MethodDebugInfo>& method_infos, - CFIFormat format); - -template<typename ElfTypes> -void WriteDebugSections(ElfBuilder<ElfTypes>* builder, - const ArrayRef<const MethodDebugInfo>& method_infos); +template <typename ElfTypes> +void WriteDebugInfo(ElfBuilder<ElfTypes>* builder, + const ArrayRef<const MethodDebugInfo>& method_infos, + CFIFormat cfi_format); } // namespace dwarf } // namespace art diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc index e411496980..7b1bdd72e5 100644 --- a/compiler/elf_writer_quick.cc +++ b/compiler/elf_writer_quick.cc @@ -46,15 +46,6 @@ namespace art { // Let's use .debug_frame because it is easier to strip or compress. constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT; -// The ARM specification defines three special mapping symbols -// $a, $t and $d which mark ARM, Thumb and data ranges respectively. -// These symbols can be used by tools, for example, to pretty -// print instructions correctly. Objdump will use them if they -// exist, but it will still work well without them. -// However, these extra symbols take space, so let's just generate -// one symbol which marks the whole .text section as code. -constexpr bool kGenerateSingleArmMappingSymbol = true; - template <typename ElfTypes> class ElfWriterQuick FINAL : public ElfWriter { public: @@ -99,10 +90,6 @@ std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set, } template <typename ElfTypes> -static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, - const ArrayRef<const dwarf::MethodDebugInfo>& method_infos); - -template <typename ElfTypes> ElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set, const CompilerOptions* compiler_options, File* elf_file) @@ -165,14 +152,7 @@ template <typename ElfTypes> void ElfWriterQuick<ElfTypes>::WriteDebugInfo( const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) { if (compiler_options_->GetGenerateDebugInfo()) { - if (!method_infos.empty()) { - // Add methods to .symtab. - WriteDebugSymbols(builder_.get(), method_infos); - // Generate CFI (stack unwinding information). - dwarf::WriteCFISection(builder_.get(), method_infos, kCFIFormat); - // Write DWARF .debug_* sections. - dwarf::WriteDebugSections(builder_.get(), method_infos); - } + dwarf::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat); } } @@ -199,64 +179,6 @@ OutputStream* ElfWriterQuick<ElfTypes>::GetStream() { return builder_->GetStream(); } -template <typename ElfTypes> -static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, - const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) { - bool generated_mapping_symbol = false; - auto* strtab = builder->GetStrTab(); - auto* symtab = builder->GetSymTab(); - - if (method_infos.empty()) { - return; - } - - // Find all addresses (low_pc) which contain deduped methods. - // The first instance of method is not marked deduped_, but the rest is. - std::unordered_set<uint32_t> deduped_addresses; - for (const dwarf::MethodDebugInfo& info : method_infos) { - if (info.deduped_) { - deduped_addresses.insert(info.low_pc_); - } - } - - strtab->Start(); - strtab->Write(""); // strtab should start with empty string. - for (const dwarf::MethodDebugInfo& info : method_infos) { - if (info.deduped_) { - continue; // Add symbol only for the first instance. - } - std::string name = PrettyMethod(info.dex_method_index_, *info.dex_file_, true); - if (deduped_addresses.find(info.low_pc_) != deduped_addresses.end()) { - name += " [DEDUPED]"; - } - - uint32_t low_pc = info.low_pc_; - // Add in code delta, e.g., thumb bit 0 for Thumb2 code. - low_pc += info.compiled_method_->CodeDelta(); - symtab->Add(strtab->Write(name), builder->GetText(), low_pc, - true, info.high_pc_ - info.low_pc_, STB_GLOBAL, STT_FUNC); - - // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2 - // instructions, so that disassembler tools can correctly disassemble. - // Note that even if we generate just a single mapping symbol, ARM's Streamline - // requires it to match function symbol. Just address 0 does not work. - if (info.compiled_method_->GetInstructionSet() == kThumb2) { - if (!generated_mapping_symbol || !kGenerateSingleArmMappingSymbol) { - symtab->Add(strtab->Write("$t"), builder->GetText(), info.low_pc_ & ~1, - true, 0, STB_LOCAL, STT_NOTYPE); - generated_mapping_symbol = true; - } - } - } - strtab->End(); - - // Symbols are buffered and written after names (because they are smaller). - // We could also do two passes in this function to avoid the buffering. - symtab->Start(); - symtab->Write(); - symtab->End(); -} - // Explicit instantiations template class ElfWriterQuick<ElfTypes32>; template class ElfWriterQuick<ElfTypes64>; |