Fix reading DW_AT_ranges in split dwarf.
Bug: b/280290608, chromium:1448979 Change-Id: I3f9e4c3d62b4c858238ccbbda0366926c306e27f Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/4568824 Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
6857c7c65f
commit
02fe1eef8e
7 changed files with 86 additions and 52 deletions
|
@ -580,10 +580,10 @@ enum DwarfSectionId {
|
||||||
DW_SECT_TYPES = 2,
|
DW_SECT_TYPES = 2,
|
||||||
DW_SECT_ABBREV = 3,
|
DW_SECT_ABBREV = 3,
|
||||||
DW_SECT_LINE = 4,
|
DW_SECT_LINE = 4,
|
||||||
DW_SECT_LOC = 5,
|
DW_SECT_LOCLISTS = 5,
|
||||||
DW_SECT_STR_OFFSETS = 6,
|
DW_SECT_STR_OFFSETS = 6,
|
||||||
DW_SECT_MACINFO = 7,
|
DW_SECT_MACRO = 7,
|
||||||
DW_SECT_MACRO = 8
|
DW_SECT_RNGLISTS = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
// Source languages. These are values for DW_AT_language.
|
// Source languages. These are values for DW_AT_language.
|
||||||
|
|
|
@ -80,7 +80,7 @@ CompilationUnit::CompilationUnit(const string& path,
|
||||||
str_offsets_buffer_(NULL), str_offsets_buffer_length_(0),
|
str_offsets_buffer_(NULL), str_offsets_buffer_length_(0),
|
||||||
addr_buffer_(NULL), addr_buffer_length_(0),
|
addr_buffer_(NULL), addr_buffer_length_(0),
|
||||||
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), ranges_base_(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) {}
|
||||||
|
|
||||||
|
@ -91,16 +91,11 @@ 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(const uint8_t* addr_buffer,
|
void CompilationUnit::SetSplitDwarf(
|
||||||
uint64_t addr_buffer_length,
|
|
||||||
uint64_t addr_base,
|
uint64_t addr_base,
|
||||||
uint64_t ranges_base,
|
|
||||||
uint64_t dwo_id) {
|
uint64_t dwo_id) {
|
||||||
is_split_dwarf_ = true;
|
is_split_dwarf_ = true;
|
||||||
addr_buffer_ = addr_buffer;
|
|
||||||
addr_buffer_length_ = addr_buffer_length;
|
|
||||||
addr_base_ = addr_base;
|
addr_base_ = addr_base;
|
||||||
ranges_base_ = ranges_base;
|
|
||||||
skeleton_dwo_id_ = dwo_id;
|
skeleton_dwo_id_ = dwo_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -889,7 +884,9 @@ const uint8_t* CompilationUnit::ProcessDIE(uint64_t dieoffset,
|
||||||
// DW_AT_str_offsets_base or DW_AT_addr_base. If it does, that attribute must
|
// DW_AT_str_offsets_base or DW_AT_addr_base. If it does, that attribute must
|
||||||
// be found and processed before trying to process the other attributes;
|
// be found and processed before trying to process the other attributes;
|
||||||
// otherwise the string or address values will all come out incorrect.
|
// otherwise the string or address values will all come out incorrect.
|
||||||
if (abbrev.tag == DW_TAG_compile_unit && header_.version == 5) {
|
if ((abbrev.tag == DW_TAG_compile_unit ||
|
||||||
|
abbrev.tag == DW_TAG_skeleton_unit) &&
|
||||||
|
header_.version == 5) {
|
||||||
uint64_t dieoffset_copy = dieoffset;
|
uint64_t dieoffset_copy = dieoffset;
|
||||||
const uint8_t* start_copy = start;
|
const uint8_t* start_copy = start;
|
||||||
for (AttributeList::const_iterator i = abbrev.attributes.begin();
|
for (AttributeList::const_iterator i = abbrev.attributes.begin();
|
||||||
|
@ -1016,7 +1013,8 @@ bool CompilationUnit::ProcessSplitDwarf(std::string& split_file,
|
||||||
string debug_suffix(".debug");
|
string debug_suffix(".debug");
|
||||||
dwp_path = path_;
|
dwp_path = path_;
|
||||||
size_t found = path_.rfind(debug_suffix);
|
size_t found = path_.rfind(debug_suffix);
|
||||||
if (found + debug_suffix.length() == path_.length())
|
if (found != string::npos &&
|
||||||
|
found + debug_suffix.length() == path_.length())
|
||||||
dwp_path = dwp_path.replace(found, debug_suffix.length(), dwp_suffix);
|
dwp_path = dwp_path.replace(found, debug_suffix.length(), dwp_suffix);
|
||||||
}
|
}
|
||||||
if (stat(dwp_path.c_str(), &statbuf) == 0) {
|
if (stat(dwp_path.c_str(), &statbuf) == 0) {
|
||||||
|
@ -1133,6 +1131,8 @@ void DwpReader::Initialize() {
|
||||||
info_data_ = elf_reader_->GetSectionByName(".debug_info.dwo", &info_size_);
|
info_data_ = elf_reader_->GetSectionByName(".debug_info.dwo", &info_size_);
|
||||||
str_offsets_data_ = elf_reader_->GetSectionByName(".debug_str_offsets.dwo",
|
str_offsets_data_ = elf_reader_->GetSectionByName(".debug_str_offsets.dwo",
|
||||||
&str_offsets_size_);
|
&str_offsets_size_);
|
||||||
|
rnglist_data_ =
|
||||||
|
elf_reader_->GetSectionByName(".debug_rnglists.dwo", &rnglist_size_);
|
||||||
if (size_table_ >= cu_index_ + cu_index_size_) {
|
if (size_table_ >= cu_index_ + cu_index_size_) {
|
||||||
version_ = 0;
|
version_ = 0;
|
||||||
}
|
}
|
||||||
|
@ -1245,6 +1245,12 @@ void DwpReader::ReadDebugSectionsForCU(uint64_t dwo_id,
|
||||||
".debug_str_offsets",
|
".debug_str_offsets",
|
||||||
std::make_pair(reinterpret_cast<const uint8_t*> (str_offsets_data_)
|
std::make_pair(reinterpret_cast<const uint8_t*> (str_offsets_data_)
|
||||||
+ offset, size)));
|
+ offset, size)));
|
||||||
|
} else if (section_id == DW_SECT_RNGLISTS) {
|
||||||
|
sections->insert(std::make_pair(
|
||||||
|
".debug_rnglists",
|
||||||
|
std::make_pair(
|
||||||
|
reinterpret_cast<const uint8_t*>(rnglist_data_) + offset,
|
||||||
|
size)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sections->insert(std::make_pair(
|
sections->insert(std::make_pair(
|
||||||
|
@ -1830,6 +1836,11 @@ bool RangeListReader::ReadRanges(enum DwarfForm form, uint64_t data) {
|
||||||
return ReadDebugRngList(data);
|
return ReadDebugRngList(data);
|
||||||
}
|
}
|
||||||
} else if (form == DW_FORM_rnglistx) {
|
} else if (form == DW_FORM_rnglistx) {
|
||||||
|
if (cu_info_->ranges_base_ == 0) {
|
||||||
|
// In split dwarf, there's no DW_AT_rnglists_base attribute, range_base
|
||||||
|
// will just be the first byte after the header.
|
||||||
|
cu_info_->ranges_base_ = reader_->OffsetSize() == 4? 12: 20;
|
||||||
|
}
|
||||||
offset_array_ = cu_info_->ranges_base_;
|
offset_array_ = cu_info_->ranges_base_;
|
||||||
uint64_t index_offset = reader_->OffsetSize() * data;
|
uint64_t index_offset = reader_->OffsetSize() * data;
|
||||||
uint64_t range_list_offset =
|
uint64_t range_list_offset =
|
||||||
|
|
|
@ -469,8 +469,7 @@ class CompilationUnit {
|
||||||
// compilation unit. We also inherit the Dwarf2Handler from
|
// compilation unit. We also inherit the Dwarf2Handler from
|
||||||
// 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 SetSplitDwarf(const uint8_t* addr_buffer, uint64_t addr_buffer_length,
|
void SetSplitDwarf(uint64_t addr_base, uint64_t dwo_id);
|
||||||
uint64_t addr_base, uint64_t ranges_base, uint64_t dwo_id);
|
|
||||||
|
|
||||||
// Begin reading a Dwarf2 compilation unit, and calling the
|
// Begin reading a Dwarf2 compilation unit, and calling the
|
||||||
// callbacks in the Dwarf2Handler
|
// callbacks in the Dwarf2Handler
|
||||||
|
@ -493,7 +492,7 @@ class CompilationUnit {
|
||||||
|
|
||||||
uint64_t GetAddrBase() { return addr_base_; }
|
uint64_t GetAddrBase() { return addr_base_; }
|
||||||
|
|
||||||
uint64_t GetRangeBase() { return ranges_base_; }
|
uint64_t GetLowPC() { return low_pc_; }
|
||||||
|
|
||||||
uint64_t GetDWOID() { return dwo_id_; }
|
uint64_t GetDWOID() { return dwo_id_; }
|
||||||
|
|
||||||
|
@ -583,14 +582,8 @@ class CompilationUnit {
|
||||||
else if (attr == DW_AT_str_offsets_base) {
|
else if (attr == DW_AT_str_offsets_base) {
|
||||||
str_offsets_base_ = data;
|
str_offsets_base_ = data;
|
||||||
}
|
}
|
||||||
else if (attr == DW_AT_GNU_ranges_base || attr == DW_AT_rnglists_base) {
|
else if (attr == DW_AT_low_pc) {
|
||||||
ranges_base_ = data;
|
low_pc_ = data;
|
||||||
}
|
|
||||||
// TODO(yunlian): When we add DW_AT_ranges_base from DWARF-5,
|
|
||||||
// that base will apply to DW_AT_ranges attributes in the
|
|
||||||
// skeleton CU as well as in the .dwo/.dwp files.
|
|
||||||
else if (attr == DW_AT_ranges && is_split_dwarf_) {
|
|
||||||
data += ranges_base_;
|
|
||||||
}
|
}
|
||||||
handler_->ProcessAttributeUnsigned(offset, attr, form, data);
|
handler_->ProcessAttributeUnsigned(offset, attr, form, data);
|
||||||
}
|
}
|
||||||
|
@ -745,10 +738,6 @@ class CompilationUnit {
|
||||||
// from the skeleton CU.
|
// from the skeleton CU.
|
||||||
uint64_t skeleton_dwo_id_;
|
uint64_t skeleton_dwo_id_;
|
||||||
|
|
||||||
// The value of the DW_AT_GNU_ranges_base or DW_AT_rnglists_base attribute,
|
|
||||||
// if any.
|
|
||||||
uint64_t ranges_base_;
|
|
||||||
|
|
||||||
// The value of the DW_AT_GNU_addr_base attribute, if any.
|
// The value of the DW_AT_GNU_addr_base attribute, if any.
|
||||||
uint64_t addr_base_;
|
uint64_t addr_base_;
|
||||||
|
|
||||||
|
@ -765,6 +754,9 @@ class CompilationUnit {
|
||||||
std::unique_ptr<DwpReader> dwp_reader_;
|
std::unique_ptr<DwpReader> dwp_reader_;
|
||||||
|
|
||||||
bool should_process_split_dwarf_;
|
bool should_process_split_dwarf_;
|
||||||
|
|
||||||
|
// The value of the DW_AT_low_pc attribute, if any.
|
||||||
|
uint64_t low_pc_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A Reader for a .dwp file. Supports the fetching of DWARF debug
|
// A Reader for a .dwp file. Supports the fetching of DWARF debug
|
||||||
|
@ -851,6 +843,8 @@ class DwpReader {
|
||||||
size_t info_size_;
|
size_t info_size_;
|
||||||
const char* str_offsets_data_;
|
const char* str_offsets_data_;
|
||||||
size_t str_offsets_size_;
|
size_t str_offsets_size_;
|
||||||
|
const char* rnglist_data_;
|
||||||
|
size_t rnglist_size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This class is a reader for DWARF's Call Frame Information. CFI
|
// This class is a reader for DWARF's Call Frame Information. CFI
|
||||||
|
|
|
@ -169,19 +169,23 @@ bool DwarfCUToModule::FileContext::IsUnhandledInterCUReference(
|
||||||
// parsing. This is for data shared across the CU's entire DIE tree,
|
// parsing. This is for data shared across the CU's entire DIE tree,
|
||||||
// and parameters from the code invoking the CU parser.
|
// and parameters from the code invoking the CU parser.
|
||||||
struct DwarfCUToModule::CUContext {
|
struct DwarfCUToModule::CUContext {
|
||||||
CUContext(FileContext* file_context_arg, WarningReporter* reporter_arg,
|
CUContext(FileContext* file_context_arg,
|
||||||
RangesHandler* ranges_handler_arg)
|
WarningReporter* reporter_arg,
|
||||||
|
RangesHandler* ranges_handler_arg,
|
||||||
|
uint64_t low_pc,
|
||||||
|
uint64_t addr_base)
|
||||||
: version(0),
|
: version(0),
|
||||||
file_context(file_context_arg),
|
file_context(file_context_arg),
|
||||||
reporter(reporter_arg),
|
reporter(reporter_arg),
|
||||||
ranges_handler(ranges_handler_arg),
|
ranges_handler(ranges_handler_arg),
|
||||||
language(Language::CPlusPlus),
|
language(Language::CPlusPlus),
|
||||||
low_pc(0),
|
low_pc(low_pc),
|
||||||
high_pc(0),
|
high_pc(0),
|
||||||
ranges_form(DW_FORM_sec_offset),
|
ranges_form(DW_FORM_sec_offset),
|
||||||
ranges_data(0),
|
ranges_data(0),
|
||||||
ranges_base(0),
|
ranges_base(0),
|
||||||
str_offsets_base(0) { }
|
addr_base(addr_base),
|
||||||
|
str_offsets_base(0) {}
|
||||||
|
|
||||||
~CUContext() {
|
~CUContext() {
|
||||||
for (vector<Module::Function*>::iterator it = functions.begin();
|
for (vector<Module::Function*>::iterator it = functions.begin();
|
||||||
|
@ -854,7 +858,7 @@ void DwarfCUToModule::FuncHandler::Finish() {
|
||||||
iter->second->name = name_;
|
iter->second->name = name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ranges_data_) {
|
if (low_pc_ && high_pc_) {
|
||||||
// Make high_pc_ an address, if it isn't already.
|
// Make high_pc_ an address, if it isn't already.
|
||||||
if (high_pc_form_ != DW_FORM_addr &&
|
if (high_pc_form_ != DW_FORM_addr &&
|
||||||
high_pc_form_ != DW_FORM_GNU_addr_index &&
|
high_pc_form_ != DW_FORM_GNU_addr_index &&
|
||||||
|
@ -868,7 +872,7 @@ void DwarfCUToModule::FuncHandler::Finish() {
|
||||||
|
|
||||||
Module::Range range(low_pc_, high_pc_ - low_pc_);
|
Module::Range range(low_pc_, high_pc_ - low_pc_);
|
||||||
ranges.push_back(range);
|
ranges.push_back(range);
|
||||||
} else {
|
} else if (ranges_data_) {
|
||||||
RangesHandler* ranges_handler = cu_context_->ranges_handler;
|
RangesHandler* ranges_handler = cu_context_->ranges_handler;
|
||||||
if (ranges_handler) {
|
if (ranges_handler) {
|
||||||
RangeListReader::CURangesInfo cu_info;
|
RangeListReader::CURangesInfo cu_info;
|
||||||
|
@ -1069,10 +1073,16 @@ DwarfCUToModule::DwarfCUToModule(FileContext* file_context,
|
||||||
LineToModuleHandler* line_reader,
|
LineToModuleHandler* line_reader,
|
||||||
RangesHandler* ranges_handler,
|
RangesHandler* ranges_handler,
|
||||||
WarningReporter* reporter,
|
WarningReporter* reporter,
|
||||||
bool handle_inline)
|
bool handle_inline,
|
||||||
|
uint64_t low_pc,
|
||||||
|
uint64_t addr_base)
|
||||||
: RootDIEHandler(handle_inline),
|
: RootDIEHandler(handle_inline),
|
||||||
line_reader_(line_reader),
|
line_reader_(line_reader),
|
||||||
cu_context_(new CUContext(file_context, reporter, ranges_handler)),
|
cu_context_(new CUContext(file_context,
|
||||||
|
reporter,
|
||||||
|
ranges_handler,
|
||||||
|
low_pc,
|
||||||
|
addr_base)),
|
||||||
child_context_(new DIEContext()),
|
child_context_(new DIEContext()),
|
||||||
has_source_line_info_(false) {}
|
has_source_line_info_(false) {}
|
||||||
|
|
||||||
|
|
|
@ -264,7 +264,9 @@ class DwarfCUToModule: public RootDIEHandler {
|
||||||
LineToModuleHandler* line_reader,
|
LineToModuleHandler* line_reader,
|
||||||
RangesHandler* ranges_handler,
|
RangesHandler* ranges_handler,
|
||||||
WarningReporter* reporter,
|
WarningReporter* reporter,
|
||||||
bool handle_inline = false);
|
bool handle_inline = false,
|
||||||
|
uint64_t low_pc = 0,
|
||||||
|
uint64_t addr_base = 0);
|
||||||
~DwarfCUToModule();
|
~DwarfCUToModule();
|
||||||
|
|
||||||
void ProcessAttributeSigned(enum DwarfAttribute attr,
|
void ProcessAttributeSigned(enum DwarfAttribute attr,
|
||||||
|
|
|
@ -348,18 +348,27 @@ void StartProcessSplitDwarf(google_breakpad::CompilationUnit* reader,
|
||||||
return;
|
return;
|
||||||
DwarfCUToModule::FileContext file_context(split_file, module,
|
DwarfCUToModule::FileContext file_context(split_file, module,
|
||||||
handle_inter_cu_refs);
|
handle_inter_cu_refs);
|
||||||
|
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.
|
||||||
|
if (file_context.section_map().find(".debug_addr") ==
|
||||||
|
file_context.section_map().end())
|
||||||
|
file_context.AddSectionToSectionMap(".debug_addr", reader->GetAddrBuffer(),
|
||||||
|
reader->GetAddrBufferLen());
|
||||||
|
|
||||||
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(&file_context, &line_to_module, &ranges_handler,
|
||||||
&reporter, handle_inline);
|
&reporter, handle_inline, reader->GetLowPC(),
|
||||||
|
reader->GetAddrBase());
|
||||||
google_breakpad::DIEDispatcher die_dispatcher(&root_handler);
|
google_breakpad::DIEDispatcher die_dispatcher(&root_handler);
|
||||||
google_breakpad::CompilationUnit split_reader(split_file, split_sections,
|
google_breakpad::CompilationUnit split_reader(
|
||||||
cu_offset, &split_byte_reader,
|
split_file, file_context.section_map(), cu_offset, &split_byte_reader,
|
||||||
&die_dispatcher);
|
&die_dispatcher);
|
||||||
split_reader.SetSplitDwarf(reader->GetAddrBuffer(),
|
split_reader.SetSplitDwarf(reader->GetAddrBase(), reader->GetDWOID());
|
||||||
reader->GetAddrBufferLen(), reader->GetAddrBase(),
|
|
||||||
reader->GetRangeBase(), reader->GetDWOID());
|
|
||||||
split_reader.Start();
|
split_reader.Start();
|
||||||
// Normally, it won't happen unless we have transitive reference.
|
// Normally, it won't happen unless we have transitive reference.
|
||||||
if (split_reader.ShouldProcessSplitDwarf()) {
|
if (split_reader.ShouldProcessSplitDwarf()) {
|
||||||
|
|
|
@ -439,18 +439,26 @@ void DumpSymbols::StartProcessSplitDwarf(
|
||||||
return;
|
return;
|
||||||
DwarfCUToModule::FileContext file_context(split_file, module,
|
DwarfCUToModule::FileContext file_context(split_file, module,
|
||||||
handle_inter_cu_refs);
|
handle_inter_cu_refs);
|
||||||
|
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.
|
||||||
|
if (file_context.section_map().find(".debug_addr") ==
|
||||||
|
file_context.section_map().end())
|
||||||
|
file_context.AddSectionToSectionMap(".debug_addr", reader->GetAddrBuffer(),
|
||||||
|
reader->GetAddrBufferLen());
|
||||||
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(&file_context, &line_to_module, &ranges_handler,
|
||||||
&reporter, handle_inline);
|
&reporter, handle_inline, reader->GetLowPC(),
|
||||||
|
reader->GetAddrBase());
|
||||||
google_breakpad::DIEDispatcher die_dispatcher(&root_handler);
|
google_breakpad::DIEDispatcher die_dispatcher(&root_handler);
|
||||||
google_breakpad::CompilationUnit split_reader(split_file, split_sections,
|
google_breakpad::CompilationUnit split_reader(
|
||||||
cu_offset, &split_byte_reader,
|
split_file, file_context.section_map(), cu_offset, &split_byte_reader,
|
||||||
&die_dispatcher);
|
&die_dispatcher);
|
||||||
split_reader.SetSplitDwarf(reader->GetAddrBuffer(),
|
split_reader.SetSplitDwarf(reader->GetAddrBase(), reader->GetDWOID());
|
||||||
reader->GetAddrBufferLen(), reader->GetAddrBase(),
|
|
||||||
reader->GetRangeBase(), reader->GetDWOID());
|
|
||||||
split_reader.Start();
|
split_reader.Start();
|
||||||
// Normally, it won't happen unless we have transitive reference.
|
// Normally, it won't happen unless we have transitive reference.
|
||||||
if (split_reader.ShouldProcessSplitDwarf()) {
|
if (split_reader.ShouldProcessSplitDwarf()) {
|
||||||
|
|
Loading…
Reference in a new issue