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 <jperaza@chromium.org>
This commit is contained in:
Zequan Wu 2023-05-31 16:26:04 -04:00 committed by Joshua Peraza
parent 18aa6faf2e
commit a9bb984785
6 changed files with 72 additions and 17 deletions

View file

@ -82,7 +82,8 @@ CompilationUnit::CompilationUnit(const string& path,
is_split_dwarf_(false), is_type_unit_(false), dwo_id_(0), dwo_name_(), is_split_dwarf_(false), is_type_unit_(false), dwo_id_(0), dwo_name_(),
skeleton_dwo_id_(0), addr_base_(0), skeleton_dwo_id_(0), addr_base_(0),
str_offsets_base_(0), have_checked_for_dwp_(false), 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. // Initialize a compilation unit from a .dwo or .dwp file.
// In this case, we need the .debug_addr section from the // 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 // the executable file, and call it as if we were still
// processing the original compilation unit. // processing the original compilation unit.
void CompilationUnit::SetSplitDwarf( void CompilationUnit::SetSplitDwarf(uint64_t addr_base,
uint64_t addr_base,
uint64_t dwo_id) { uint64_t dwo_id) {
is_split_dwarf_ = true; is_split_dwarf_ = true;
addr_base_ = addr_base; addr_base_ = addr_base;
@ -435,6 +435,12 @@ uint64_t CompilationUnit::Start() {
string_buffer_length_ = iter->second.second; 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. // Set the line string section if we have one.
iter = GetSectionByName(sections_, ".debug_line_str"); iter = GetSectionByName(sections_, ".debug_line_str");
if (iter != sections_.end()) { if (iter != sections_.end()) {

View file

@ -496,6 +496,18 @@ class CompilationUnit {
uint64_t GetDWOID() { return dwo_id_; } 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_; } bool ShouldProcessSplitDwarf() { return should_process_split_dwarf_; }
private: private:
@ -585,6 +597,10 @@ class CompilationUnit {
else if (attr == DW_AT_low_pc) { else if (attr == DW_AT_low_pc) {
low_pc_ = data; 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); handler_->ProcessAttributeUnsigned(offset, attr, form, data);
} }
@ -696,7 +712,7 @@ class CompilationUnit {
const uint8_t* string_buffer_; const uint8_t* string_buffer_;
uint64_t string_buffer_length_; uint64_t string_buffer_length_;
// Similarly for .debug_line_string. // Similarly for .debug_line_str.
const uint8_t* line_string_buffer_; const uint8_t* line_string_buffer_;
uint64_t line_string_buffer_length_; uint64_t line_string_buffer_length_;
@ -710,6 +726,10 @@ class CompilationUnit {
const uint8_t* addr_buffer_; const uint8_t* addr_buffer_;
uint64_t addr_buffer_length_; 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 // Flag indicating whether this compilation unit is part of a .dwo
// or .dwp file. If true, we are reading this unit because a // or .dwp file. If true, we are reading this unit because a
// skeleton compilation unit in an executable file had 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. // The value of the DW_AT_low_pc attribute, if any.
uint64_t low_pc_; 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 // A Reader for a .dwp file. Supports the fetching of DWARF debug

View file

@ -1075,7 +1075,9 @@ DwarfCUToModule::DwarfCUToModule(FileContext* file_context,
WarningReporter* reporter, WarningReporter* reporter,
bool handle_inline, bool handle_inline,
uint64_t low_pc, 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), : RootDIEHandler(handle_inline),
line_reader_(line_reader), line_reader_(line_reader),
cu_context_(new CUContext(file_context, cu_context_(new CUContext(file_context,
@ -1084,7 +1086,8 @@ DwarfCUToModule::DwarfCUToModule(FileContext* file_context,
low_pc, low_pc,
addr_base)), addr_base)),
child_context_(new DIEContext()), 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() { DwarfCUToModule::~DwarfCUToModule() {
} }

View file

@ -266,7 +266,9 @@ class DwarfCUToModule: public RootDIEHandler {
WarningReporter* reporter, WarningReporter* reporter,
bool handle_inline = false, bool handle_inline = false,
uint64_t low_pc = 0, 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(); ~DwarfCUToModule();
void ProcessAttributeSigned(enum DwarfAttribute attr, void ProcessAttributeSigned(enum DwarfAttribute attr,

View file

@ -351,19 +351,29 @@ void StartProcessSplitDwarf(google_breakpad::CompilationUnit* reader,
for (auto section : split_sections) for (auto section : split_sections)
file_context.AddSectionToSectionMap(section.first, section.second.first, file_context.AddSectionToSectionMap(section.first, section.second.first,
section.second.second); section.second.second);
// Because DWP/DWO file doesn't have .debug_addr/.debug_line, its debug info // Because DWP/DWO file doesn't have .debug_addr/.debug_line/.debug_line_str,
// will refer to .debug_addr/.debug_line in the main binary. // its debug info will refer to .debug_addr/.debug_line in the main binary.
if (file_context.section_map().find(".debug_addr") == if (file_context.section_map().find(".debug_addr") ==
file_context.section_map().end()) file_context.section_map().end())
file_context.AddSectionToSectionMap(".debug_addr", reader->GetAddrBuffer(), file_context.AddSectionToSectionMap(".debug_addr", reader->GetAddrBuffer(),
reader->GetAddrBufferLen()); 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); DumperRangesHandler ranges_handler(&split_byte_reader);
DumperLineToModule line_to_module(&split_byte_reader); DumperLineToModule line_to_module(&split_byte_reader);
DwarfCUToModule::WarningReporter reporter(split_file, cu_offset); DwarfCUToModule::WarningReporter reporter(split_file, cu_offset);
DwarfCUToModule root_handler(&file_context, &line_to_module, &ranges_handler, DwarfCUToModule root_handler(
&reporter, handle_inline, reader->GetLowPC(), &file_context, &line_to_module, &ranges_handler, &reporter, handle_inline,
reader->GetAddrBase()); reader->GetLowPC(), reader->GetAddrBase(), reader->HasSourceLineInfo(),
reader->GetSourceLineOffset());
google_breakpad::DIEDispatcher die_dispatcher(&root_handler); google_breakpad::DIEDispatcher die_dispatcher(&root_handler);
google_breakpad::CompilationUnit split_reader( google_breakpad::CompilationUnit split_reader(
split_file, file_context.section_map(), cu_offset, &split_byte_reader, split_file, file_context.section_map(), cu_offset, &split_byte_reader,

View file

@ -442,18 +442,28 @@ void DumpSymbols::StartProcessSplitDwarf(
for (auto section : split_sections) for (auto section : split_sections)
file_context.AddSectionToSectionMap(section.first, section.second.first, file_context.AddSectionToSectionMap(section.first, section.second.first,
section.second.second); section.second.second);
// If DWP/DWO file doesn't have .debug_addr, its debug info will refer to // Because DWP/DWO file doesn't have .debug_addr/.debug_line/.debug_line_str,
// .debug_addr in the main binary. // its debug info will refer to .debug_addr/.debug_line in the main binary.
if (file_context.section_map().find(".debug_addr") == if (file_context.section_map().find(".debug_addr") ==
file_context.section_map().end()) file_context.section_map().end())
file_context.AddSectionToSectionMap(".debug_addr", reader->GetAddrBuffer(), file_context.AddSectionToSectionMap(".debug_addr", reader->GetAddrBuffer(),
reader->GetAddrBufferLen()); 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); DumperRangesHandler ranges_handler(&split_byte_reader);
DumperLineToModule line_to_module(&split_byte_reader); DumperLineToModule line_to_module(&split_byte_reader);
DwarfCUToModule::WarningReporter reporter(split_file, cu_offset); DwarfCUToModule::WarningReporter reporter(split_file, cu_offset);
DwarfCUToModule root_handler(&file_context, &line_to_module, &ranges_handler, DwarfCUToModule root_handler(
&reporter, handle_inline, reader->GetLowPC(), &file_context, &line_to_module, &ranges_handler, &reporter, handle_inline,
reader->GetAddrBase()); reader->GetLowPC(), reader->GetAddrBase(), reader->HasSourceLineInfo(),
reader->GetSourceLineOffset());
google_breakpad::DIEDispatcher die_dispatcher(&root_handler); google_breakpad::DIEDispatcher die_dispatcher(&root_handler);
google_breakpad::CompilationUnit split_reader( google_breakpad::CompilationUnit split_reader(
split_file, file_context.section_map(), cu_offset, &split_byte_reader, split_file, file_context.section_map(), cu_offset, &split_byte_reader,