diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/debug/elf_debug_info_writer.h | 26 | ||||
| -rw-r--r-- | compiler/debug/elf_debug_writer.cc | 34 |
2 files changed, 49 insertions, 11 deletions
diff --git a/compiler/debug/elf_debug_info_writer.h b/compiler/debug/elf_debug_info_writer.h index de32351abf..6c6bd63b14 100644 --- a/compiler/debug/elf_debug_info_writer.h +++ b/compiler/debug/elf_debug_info_writer.h @@ -122,17 +122,39 @@ class ElfCompilationUnitWriter { const Elf_Addr base_address = compilation_unit.is_code_address_text_relative ? owner_->builder_->GetText()->GetAddress() : 0; - const uint64_t cu_size = compilation_unit.code_end - compilation_unit.code_address; + const bool is64bit = Is64BitInstructionSet(owner_->builder_->GetIsa()); using namespace dwarf; // NOLINT. For easy access to DWARF constants. info_.StartTag(DW_TAG_compile_unit); info_.WriteString(DW_AT_producer, "Android dex2oat"); info_.WriteData1(DW_AT_language, DW_LANG_Java); info_.WriteString(DW_AT_comp_dir, "$JAVA_SRC_ROOT"); + // The low_pc acts as base address for several other addresses/ranges. info_.WriteAddr(DW_AT_low_pc, base_address + compilation_unit.code_address); - info_.WriteUdata(DW_AT_high_pc, dchecked_integral_cast<uint32_t>(cu_size)); info_.WriteSecOffset(DW_AT_stmt_list, compilation_unit.debug_line_offset); + // Write .debug_ranges entries covering code ranges of the whole compilation unit. + dwarf::Writer<> debug_ranges(&owner_->debug_ranges_); + info_.WriteSecOffset(DW_AT_ranges, owner_->debug_ranges_.size()); + for (auto mi : compilation_unit.methods) { + uint64_t low_pc = mi->code_address - compilation_unit.code_address; + uint64_t high_pc = low_pc + mi->code_size; + if (is64bit) { + debug_ranges.PushUint64(low_pc); + debug_ranges.PushUint64(high_pc); + } else { + debug_ranges.PushUint32(low_pc); + debug_ranges.PushUint32(high_pc); + } + } + if (is64bit) { + debug_ranges.PushUint64(0); // End of list. + debug_ranges.PushUint64(0); + } else { + debug_ranges.PushUint32(0); // End of list. + debug_ranges.PushUint32(0); + } + const char* last_dex_class_desc = nullptr; for (auto mi : compilation_unit.methods) { DCHECK(mi->dex_file != nullptr); diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc index 16e73b0824..c5ff85827e 100644 --- a/compiler/debug/elf_debug_writer.cc +++ b/compiler/debug/elf_debug_writer.cc @@ -17,6 +17,7 @@ #include "elf_debug_writer.h" #include <vector> +#include <unordered_map> #include "base/array_ref.h" #include "debug/dwarf/dwarf_constants.h" @@ -46,27 +47,42 @@ void WriteDebugInfo(ElfBuilder<ElfTypes>* builder, // Write .debug_frame. WriteCFISection(builder, method_infos, cfi_format, write_oat_patches); - // Group the methods into compilation units based on source file. - std::vector<ElfCompilationUnit> compilation_units; - const char* last_source_file = nullptr; + // Group the methods into compilation units based on class. + std::unordered_map<const DexFile::ClassDef*, ElfCompilationUnit> class_to_compilation_unit; for (const MethodDebugInfo& mi : method_infos) { if (mi.dex_file != nullptr) { auto& dex_class_def = mi.dex_file->GetClassDef(mi.class_def_index); - const char* source_file = mi.dex_file->GetSourceFile(dex_class_def); - if (compilation_units.empty() || source_file != last_source_file) { - compilation_units.push_back(ElfCompilationUnit()); - } - ElfCompilationUnit& cu = compilation_units.back(); + ElfCompilationUnit& cu = class_to_compilation_unit[&dex_class_def]; cu.methods.push_back(&mi); // All methods must have the same addressing mode otherwise the min/max below does not work. DCHECK_EQ(cu.methods.front()->is_code_address_text_relative, mi.is_code_address_text_relative); cu.is_code_address_text_relative = mi.is_code_address_text_relative; cu.code_address = std::min(cu.code_address, mi.code_address); cu.code_end = std::max(cu.code_end, mi.code_address + mi.code_size); - last_source_file = source_file; } } + // Sort compilation units to make the compiler output deterministic. + std::vector<ElfCompilationUnit> compilation_units; + compilation_units.reserve(class_to_compilation_unit.size()); + for (auto& it : class_to_compilation_unit) { + // The .debug_line section requires the methods to be sorted by code address. + std::stable_sort(it.second.methods.begin(), + it.second.methods.end(), + [](const MethodDebugInfo* a, const MethodDebugInfo* b) { + return a->code_address < b->code_address; + }); + compilation_units.push_back(std::move(it.second)); + } + std::sort(compilation_units.begin(), + compilation_units.end(), + [](ElfCompilationUnit& a, ElfCompilationUnit& b) { + // Sort by index of the first method within the method_infos array. + // This assumes that the order of method_infos is deterministic. + // Code address is not good for sorting due to possible duplicates. + return a.methods.front() < b.methods.front(); + }); + // Write .debug_line section. if (!compilation_units.empty()) { ElfDebugLineWriter<ElfTypes> line_writer(builder); |