From a9bb98478507cd9a07ebf0b20faae501e9798106 Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Wed, 31 May 2023 16:26:04 -0400 Subject: [PATCH] Share .debug_line and .debug_line_str among dwp file and main binary file. The debug info in the dwp file needs to refer to the .debug_line and .debug_line_str sections in the main binary. This fixes dump_syms not generating LINE records for dwp in split dwarf. Bug: chromium:1448979 Change-Id: I71923f12cea72caae081c1406e2cbca55e95859e Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/4576346 Reviewed-by: Joshua Peraza --- src/common/dwarf/dwarf2reader.cc | 12 +++++++++--- src/common/dwarf/dwarf2reader.h | 26 +++++++++++++++++++++++++- src/common/dwarf_cu_to_module.cc | 7 +++++-- src/common/dwarf_cu_to_module.h | 4 +++- src/common/linux/dump_symbols.cc | 20 +++++++++++++++----- src/common/mac/dump_syms.cc | 20 +++++++++++++++----- 6 files changed, 72 insertions(+), 17 deletions(-) diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc index 0a1ff060..8a8bf6f8 100644 --- a/src/common/dwarf/dwarf2reader.cc +++ b/src/common/dwarf/dwarf2reader.cc @@ -82,7 +82,8 @@ CompilationUnit::CompilationUnit(const string& path, is_split_dwarf_(false), is_type_unit_(false), dwo_id_(0), dwo_name_(), skeleton_dwo_id_(0), addr_base_(0), str_offsets_base_(0), have_checked_for_dwp_(false), - should_process_split_dwarf_(false) {} + should_process_split_dwarf_(false), low_pc_(0), + has_source_line_info_(false), source_line_offset_(0) {} // Initialize a compilation unit from a .dwo or .dwp file. // In this case, we need the .debug_addr section from the @@ -91,8 +92,7 @@ CompilationUnit::CompilationUnit(const string& path, // the executable file, and call it as if we were still // processing the original compilation unit. -void CompilationUnit::SetSplitDwarf( - uint64_t addr_base, +void CompilationUnit::SetSplitDwarf(uint64_t addr_base, uint64_t dwo_id) { is_split_dwarf_ = true; addr_base_ = addr_base; @@ -435,6 +435,12 @@ uint64_t CompilationUnit::Start() { string_buffer_length_ = iter->second.second; } + iter = GetSectionByName(sections_, ".debug_line"); + if (iter != sections_.end()) { + line_buffer_ = iter->second.first; + line_buffer_length_ = iter->second.second; + } + // Set the line string section if we have one. iter = GetSectionByName(sections_, ".debug_line_str"); if (iter != sections_.end()) { diff --git a/src/common/dwarf/dwarf2reader.h b/src/common/dwarf/dwarf2reader.h index a5c5febf..b6bd2f31 100644 --- a/src/common/dwarf/dwarf2reader.h +++ b/src/common/dwarf/dwarf2reader.h @@ -496,6 +496,18 @@ class CompilationUnit { uint64_t GetDWOID() { return dwo_id_; } + const uint8_t* GetLineBuffer() { return line_buffer_; } + + uint64_t GetLineBufferLen() { return line_buffer_length_; } + + const uint8_t* GetLineStrBuffer() { return line_string_buffer_; } + + uint64_t GetLineStrBufferLen() { return line_string_buffer_length_; } + + bool HasSourceLineInfo() { return has_source_line_info_; } + + uint64_t GetSourceLineOffset() { return source_line_offset_; } + bool ShouldProcessSplitDwarf() { return should_process_split_dwarf_; } private: @@ -585,6 +597,10 @@ class CompilationUnit { else if (attr == DW_AT_low_pc) { low_pc_ = data; } + else if (attr == DW_AT_stmt_list) { + has_source_line_info_ = true; + source_line_offset_ = data; + } handler_->ProcessAttributeUnsigned(offset, attr, form, data); } @@ -696,7 +712,7 @@ class CompilationUnit { const uint8_t* string_buffer_; uint64_t string_buffer_length_; - // Similarly for .debug_line_string. + // Similarly for .debug_line_str. const uint8_t* line_string_buffer_; uint64_t line_string_buffer_length_; @@ -710,6 +726,10 @@ class CompilationUnit { const uint8_t* addr_buffer_; uint64_t addr_buffer_length_; + // .debug_line section buffer and length. + const uint8_t* line_buffer_; + uint64_t line_buffer_length_; + // Flag indicating whether this compilation unit is part of a .dwo // or .dwp file. If true, we are reading this unit because a // skeleton compilation unit in an executable file had a @@ -757,6 +777,10 @@ class CompilationUnit { // The value of the DW_AT_low_pc attribute, if any. uint64_t low_pc_; + + // The value of DW_AT_stmt_list attribute if any. + bool has_source_line_info_; + uint64_t source_line_offset_; }; // A Reader for a .dwp file. Supports the fetching of DWARF debug diff --git a/src/common/dwarf_cu_to_module.cc b/src/common/dwarf_cu_to_module.cc index a6cfb49c..3beaff2c 100644 --- a/src/common/dwarf_cu_to_module.cc +++ b/src/common/dwarf_cu_to_module.cc @@ -1075,7 +1075,9 @@ DwarfCUToModule::DwarfCUToModule(FileContext* file_context, WarningReporter* reporter, bool handle_inline, uint64_t low_pc, - uint64_t addr_base) + uint64_t addr_base, + bool has_source_line_info, + uint64_t source_line_offset) : RootDIEHandler(handle_inline), line_reader_(line_reader), cu_context_(new CUContext(file_context, @@ -1084,7 +1086,8 @@ DwarfCUToModule::DwarfCUToModule(FileContext* file_context, low_pc, addr_base)), child_context_(new DIEContext()), - has_source_line_info_(false) {} + has_source_line_info_(has_source_line_info), + source_line_offset_(source_line_offset) {} DwarfCUToModule::~DwarfCUToModule() { } diff --git a/src/common/dwarf_cu_to_module.h b/src/common/dwarf_cu_to_module.h index 90ee2dec..1ff0ebc7 100644 --- a/src/common/dwarf_cu_to_module.h +++ b/src/common/dwarf_cu_to_module.h @@ -266,7 +266,9 @@ class DwarfCUToModule: public RootDIEHandler { WarningReporter* reporter, bool handle_inline = false, uint64_t low_pc = 0, - uint64_t addr_base = 0); + uint64_t addr_base = 0, + bool has_source_line_info = false, + uint64_t source_line_offset = 0); ~DwarfCUToModule(); void ProcessAttributeSigned(enum DwarfAttribute attr, diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc index 2f468dfe..86c948d9 100644 --- a/src/common/linux/dump_symbols.cc +++ b/src/common/linux/dump_symbols.cc @@ -351,19 +351,29 @@ void StartProcessSplitDwarf(google_breakpad::CompilationUnit* reader, for (auto section : split_sections) file_context.AddSectionToSectionMap(section.first, section.second.first, section.second.second); - // Because DWP/DWO file doesn't have .debug_addr/.debug_line, its debug info - // will refer to .debug_addr/.debug_line in the main binary. + // Because DWP/DWO file doesn't have .debug_addr/.debug_line/.debug_line_str, + // its debug info will refer to .debug_addr/.debug_line in the main binary. if (file_context.section_map().find(".debug_addr") == file_context.section_map().end()) file_context.AddSectionToSectionMap(".debug_addr", reader->GetAddrBuffer(), reader->GetAddrBufferLen()); + if (file_context.section_map().find(".debug_line") == + file_context.section_map().end()) + file_context.AddSectionToSectionMap(".debug_line", reader->GetLineBuffer(), + reader->GetLineBufferLen()); + if (file_context.section_map().find(".debug_line_str") == + file_context.section_map().end()) + file_context.AddSectionToSectionMap(".debug_line_str", + reader->GetLineStrBuffer(), + reader->GetLineStrBufferLen()); DumperRangesHandler ranges_handler(&split_byte_reader); DumperLineToModule line_to_module(&split_byte_reader); DwarfCUToModule::WarningReporter reporter(split_file, cu_offset); - DwarfCUToModule root_handler(&file_context, &line_to_module, &ranges_handler, - &reporter, handle_inline, reader->GetLowPC(), - reader->GetAddrBase()); + DwarfCUToModule root_handler( + &file_context, &line_to_module, &ranges_handler, &reporter, handle_inline, + reader->GetLowPC(), reader->GetAddrBase(), reader->HasSourceLineInfo(), + reader->GetSourceLineOffset()); google_breakpad::DIEDispatcher die_dispatcher(&root_handler); google_breakpad::CompilationUnit split_reader( split_file, file_context.section_map(), cu_offset, &split_byte_reader, diff --git a/src/common/mac/dump_syms.cc b/src/common/mac/dump_syms.cc index 2f48cb4f..c06945e4 100644 --- a/src/common/mac/dump_syms.cc +++ b/src/common/mac/dump_syms.cc @@ -442,18 +442,28 @@ void DumpSymbols::StartProcessSplitDwarf( for (auto section : split_sections) file_context.AddSectionToSectionMap(section.first, section.second.first, section.second.second); - // If DWP/DWO file doesn't have .debug_addr, its debug info will refer to - // .debug_addr in the main binary. + // Because DWP/DWO file doesn't have .debug_addr/.debug_line/.debug_line_str, + // its debug info will refer to .debug_addr/.debug_line in the main binary. if (file_context.section_map().find(".debug_addr") == file_context.section_map().end()) file_context.AddSectionToSectionMap(".debug_addr", reader->GetAddrBuffer(), reader->GetAddrBufferLen()); + if (file_context.section_map().find(".debug_line") == + file_context.section_map().end()) + file_context.AddSectionToSectionMap(".debug_line", reader->GetLineBuffer(), + reader->GetLineBufferLen()); + if (file_context.section_map().find(".debug_line_str") == + file_context.section_map().end()) + file_context.AddSectionToSectionMap(".debug_line_str", + reader->GetLineStrBuffer(), + reader->GetLineStrBufferLen()); DumperRangesHandler ranges_handler(&split_byte_reader); DumperLineToModule line_to_module(&split_byte_reader); DwarfCUToModule::WarningReporter reporter(split_file, cu_offset); - DwarfCUToModule root_handler(&file_context, &line_to_module, &ranges_handler, - &reporter, handle_inline, reader->GetLowPC(), - reader->GetAddrBase()); + DwarfCUToModule root_handler( + &file_context, &line_to_module, &ranges_handler, &reporter, handle_inline, + reader->GetLowPC(), reader->GetAddrBase(), reader->HasSourceLineInfo(), + reader->GetSourceLineOffset()); google_breakpad::DIEDispatcher die_dispatcher(&root_handler); google_breakpad::CompilationUnit split_reader( split_file, file_context.section_map(), cu_offset, &split_byte_reader,