Use -d flag enable procecessing DW_TAG_inlined_subroutine
This change makes sure dump_syms process DW_TAG_inlined_subroutine only when -d flag is given, which save memory and time when -d is not given. Before this, it always processes DW_TAG_inlined_subroutine and -d determines whether or not to emit INLINE records. Bug: chromium:1250351, chromium:1246974 Change-Id: I54725ba1e513cafe17268ca389ff8acc9c11b25e Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/3166674 Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
94c4208821
commit
30020c0d47
6 changed files with 54 additions and 43 deletions
|
@ -258,10 +258,13 @@ class DIEHandler {
|
||||||
|
|
||||||
// A subclass of DIEHandler, with additional kludges for handling the
|
// A subclass of DIEHandler, with additional kludges for handling the
|
||||||
// compilation unit's root die.
|
// compilation unit's root die.
|
||||||
class RootDIEHandler: public DIEHandler {
|
class RootDIEHandler : public DIEHandler {
|
||||||
public:
|
public:
|
||||||
RootDIEHandler() { }
|
bool handle_inline;
|
||||||
virtual ~RootDIEHandler() { }
|
|
||||||
|
explicit RootDIEHandler(bool handle_inline = false)
|
||||||
|
: handle_inline(handle_inline) {}
|
||||||
|
virtual ~RootDIEHandler() {}
|
||||||
|
|
||||||
// We pass the values reported via Dwarf2Handler::StartCompilationUnit
|
// We pass the values reported via Dwarf2Handler::StartCompilationUnit
|
||||||
// to this member function, and skip the entire compilation unit if it
|
// to this member function, and skip the entire compilation unit if it
|
||||||
|
|
|
@ -766,11 +766,12 @@ void DwarfCUToModule::InlineHandler::Finish() {
|
||||||
class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
|
class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
|
||||||
public:
|
public:
|
||||||
FuncHandler(CUContext* cu_context, DIEContext* parent_context,
|
FuncHandler(CUContext* cu_context, DIEContext* parent_context,
|
||||||
uint64_t offset)
|
uint64_t offset, bool handle_inline)
|
||||||
: GenericDIEHandler(cu_context, parent_context, offset),
|
: GenericDIEHandler(cu_context, parent_context, offset),
|
||||||
low_pc_(0), high_pc_(0), high_pc_form_(DW_FORM_addr),
|
low_pc_(0), high_pc_(0), high_pc_form_(DW_FORM_addr),
|
||||||
ranges_form_(DW_FORM_sec_offset), ranges_data_(0),
|
ranges_form_(DW_FORM_sec_offset), ranges_data_(0),
|
||||||
decl_file_data_(UINT64_MAX), inline_(false) { }
|
decl_file_data_(UINT64_MAX), inline_(false),
|
||||||
|
handle_inline_(handle_inline) { }
|
||||||
|
|
||||||
void ProcessAttributeUnsigned(enum DwarfAttribute attr,
|
void ProcessAttributeUnsigned(enum DwarfAttribute attr,
|
||||||
enum DwarfForm form,
|
enum DwarfForm form,
|
||||||
|
@ -794,6 +795,7 @@ class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
|
||||||
uint64_t decl_file_data_;
|
uint64_t decl_file_data_;
|
||||||
bool inline_;
|
bool inline_;
|
||||||
vector<unique_ptr<Module::Inline>> child_inlines_;
|
vector<unique_ptr<Module::Inline>> child_inlines_;
|
||||||
|
bool handle_inline_;
|
||||||
};
|
};
|
||||||
|
|
||||||
void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
|
void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
|
||||||
|
@ -844,8 +846,9 @@ DIEHandler* DwarfCUToModule::FuncHandler::FindChildHandler(
|
||||||
enum DwarfTag tag) {
|
enum DwarfTag tag) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case DW_TAG_inlined_subroutine:
|
case DW_TAG_inlined_subroutine:
|
||||||
return new InlineHandler(cu_context_, new DIEContext(), offset, 0,
|
if (handle_inline_)
|
||||||
child_inlines_);
|
return new InlineHandler(cu_context_, new DIEContext(), offset, 0,
|
||||||
|
child_inlines_);
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -949,7 +952,8 @@ void DwarfCUToModule::FuncHandler::Finish() {
|
||||||
|
|
||||||
// Only keep track of DW_TAG_subprogram which have the attributes we are
|
// Only keep track of DW_TAG_subprogram which have the attributes we are
|
||||||
// interested.
|
// interested.
|
||||||
if (!empty_range || inline_ || decl_file_data_ != UINT64_MAX) {
|
if (handle_inline_ &&
|
||||||
|
(!empty_range || inline_ || decl_file_data_ != UINT64_MAX)) {
|
||||||
uint64_t offset =
|
uint64_t offset =
|
||||||
specification_offset_ != 0 ? specification_offset_ : offset_;
|
specification_offset_ != 0 ? specification_offset_ : offset_;
|
||||||
cu_context_->file_context->file_private_->inline_origin_map.SetReference(
|
cu_context_->file_context->file_private_->inline_origin_map.SetReference(
|
||||||
|
@ -967,13 +971,14 @@ void DwarfCUToModule::FuncHandler::Finish() {
|
||||||
class DwarfCUToModule::NamedScopeHandler: public GenericDIEHandler {
|
class DwarfCUToModule::NamedScopeHandler: public GenericDIEHandler {
|
||||||
public:
|
public:
|
||||||
NamedScopeHandler(CUContext* cu_context, DIEContext* parent_context,
|
NamedScopeHandler(CUContext* cu_context, DIEContext* parent_context,
|
||||||
uint64_t offset)
|
uint64_t offset, bool handle_inline)
|
||||||
: GenericDIEHandler(cu_context, parent_context, offset) { }
|
: GenericDIEHandler(cu_context, parent_context, offset) { }
|
||||||
bool EndAttributes();
|
bool EndAttributes();
|
||||||
DIEHandler* FindChildHandler(uint64_t offset, enum DwarfTag tag);
|
DIEHandler* FindChildHandler(uint64_t offset, enum DwarfTag tag);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DIEContext child_context_; // A context for our children.
|
DIEContext child_context_; // A context for our children.
|
||||||
|
bool handle_inline_;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool DwarfCUToModule::NamedScopeHandler::EndAttributes() {
|
bool DwarfCUToModule::NamedScopeHandler::EndAttributes() {
|
||||||
|
@ -986,12 +991,14 @@ DIEHandler* DwarfCUToModule::NamedScopeHandler::FindChildHandler(
|
||||||
enum DwarfTag tag) {
|
enum DwarfTag tag) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case DW_TAG_subprogram:
|
case DW_TAG_subprogram:
|
||||||
return new FuncHandler(cu_context_, &child_context_, offset);
|
return new FuncHandler(cu_context_, &child_context_, offset,
|
||||||
|
handle_inline_);
|
||||||
case DW_TAG_namespace:
|
case DW_TAG_namespace:
|
||||||
case DW_TAG_class_type:
|
case DW_TAG_class_type:
|
||||||
case DW_TAG_structure_type:
|
case DW_TAG_structure_type:
|
||||||
case DW_TAG_union_type:
|
case DW_TAG_union_type:
|
||||||
return new NamedScopeHandler(cu_context_, &child_context_, offset);
|
return new NamedScopeHandler(cu_context_, &child_context_, offset,
|
||||||
|
handle_inline_);
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1101,12 +1108,13 @@ void DwarfCUToModule::WarningReporter::MissingRanges() {
|
||||||
DwarfCUToModule::DwarfCUToModule(FileContext* file_context,
|
DwarfCUToModule::DwarfCUToModule(FileContext* file_context,
|
||||||
LineToModuleHandler* line_reader,
|
LineToModuleHandler* line_reader,
|
||||||
RangesHandler* ranges_handler,
|
RangesHandler* ranges_handler,
|
||||||
WarningReporter* reporter)
|
WarningReporter* reporter,
|
||||||
: line_reader_(line_reader),
|
bool handle_inline)
|
||||||
|
: RootDIEHandler(handle_inline),
|
||||||
|
line_reader_(line_reader),
|
||||||
cu_context_(new CUContext(file_context, reporter, ranges_handler)),
|
cu_context_(new CUContext(file_context, reporter, ranges_handler)),
|
||||||
child_context_(new DIEContext()),
|
child_context_(new DIEContext()),
|
||||||
has_source_line_info_(false) {
|
has_source_line_info_(false) {}
|
||||||
}
|
|
||||||
|
|
||||||
DwarfCUToModule::~DwarfCUToModule() {
|
DwarfCUToModule::~DwarfCUToModule() {
|
||||||
}
|
}
|
||||||
|
@ -1183,14 +1191,15 @@ DIEHandler* DwarfCUToModule::FindChildHandler(
|
||||||
enum DwarfTag tag) {
|
enum DwarfTag tag) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case DW_TAG_subprogram:
|
case DW_TAG_subprogram:
|
||||||
return new FuncHandler(cu_context_.get(), child_context_.get(), offset);
|
return new FuncHandler(cu_context_.get(), child_context_.get(), offset,
|
||||||
|
handle_inline);
|
||||||
case DW_TAG_namespace:
|
case DW_TAG_namespace:
|
||||||
case DW_TAG_class_type:
|
case DW_TAG_class_type:
|
||||||
case DW_TAG_structure_type:
|
case DW_TAG_structure_type:
|
||||||
case DW_TAG_union_type:
|
case DW_TAG_union_type:
|
||||||
case DW_TAG_module:
|
case DW_TAG_module:
|
||||||
return new NamedScopeHandler(cu_context_.get(), child_context_.get(),
|
return new NamedScopeHandler(cu_context_.get(), child_context_.get(),
|
||||||
offset);
|
offset, handle_inline);
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,7 +258,8 @@ class DwarfCUToModule: public RootDIEHandler {
|
||||||
DwarfCUToModule(FileContext* file_context,
|
DwarfCUToModule(FileContext* file_context,
|
||||||
LineToModuleHandler* line_reader,
|
LineToModuleHandler* line_reader,
|
||||||
RangesHandler* ranges_handler,
|
RangesHandler* ranges_handler,
|
||||||
WarningReporter* reporter);
|
WarningReporter* reporter,
|
||||||
|
bool handle_inline = false);
|
||||||
~DwarfCUToModule();
|
~DwarfCUToModule();
|
||||||
|
|
||||||
void ProcessAttributeSigned(enum DwarfAttribute attr,
|
void ProcessAttributeSigned(enum DwarfAttribute attr,
|
||||||
|
|
|
@ -287,6 +287,7 @@ bool LoadDwarf(const string& dwarf_filename,
|
||||||
const typename ElfClass::Ehdr* elf_header,
|
const typename ElfClass::Ehdr* elf_header,
|
||||||
const bool big_endian,
|
const bool big_endian,
|
||||||
bool handle_inter_cu_refs,
|
bool handle_inter_cu_refs,
|
||||||
|
bool handle_inline,
|
||||||
Module* module) {
|
Module* module) {
|
||||||
typedef typename ElfClass::Shdr Shdr;
|
typedef typename ElfClass::Shdr Shdr;
|
||||||
|
|
||||||
|
@ -333,7 +334,7 @@ bool LoadDwarf(const string& dwarf_filename,
|
||||||
// data that was found.
|
// data that was found.
|
||||||
DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset);
|
DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset);
|
||||||
DwarfCUToModule root_handler(&file_context, &line_to_module,
|
DwarfCUToModule root_handler(&file_context, &line_to_module,
|
||||||
&ranges_handler, &reporter);
|
&ranges_handler, &reporter, handle_inline);
|
||||||
// Make a Dwarf2Handler that drives the DIEHandler.
|
// Make a Dwarf2Handler that drives the DIEHandler.
|
||||||
google_breakpad::DIEDispatcher die_dispatcher(&root_handler);
|
google_breakpad::DIEDispatcher die_dispatcher(&root_handler);
|
||||||
// Make a DWARF parser for the compilation unit at OFFSET.
|
// Make a DWARF parser for the compilation unit at OFFSET.
|
||||||
|
@ -786,7 +787,8 @@ bool LoadSymbols(const string& obj_file,
|
||||||
found_usable_info = true;
|
found_usable_info = true;
|
||||||
info->LoadedSection(".debug_info");
|
info->LoadedSection(".debug_info");
|
||||||
if (!LoadDwarf<ElfClass>(obj_file, elf_header, big_endian,
|
if (!LoadDwarf<ElfClass>(obj_file, elf_header, big_endian,
|
||||||
options.handle_inter_cu_refs, module)) {
|
options.handle_inter_cu_refs,
|
||||||
|
options.symbol_data & INLINES, module)) {
|
||||||
fprintf(stderr, "%s: \".debug_info\" section found, but failed to load "
|
fprintf(stderr, "%s: \".debug_info\" section found, but failed to load "
|
||||||
"DWARF debugging information\n", obj_file.c_str());
|
"DWARF debugging information\n", obj_file.c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,7 +476,8 @@ void DumpSymbols::ReadDwarf(google_breakpad::Module* module,
|
||||||
DwarfCUToModule::WarningReporter reporter(selected_object_name_,
|
DwarfCUToModule::WarningReporter reporter(selected_object_name_,
|
||||||
offset);
|
offset);
|
||||||
DwarfCUToModule root_handler(&file_context, &line_to_module,
|
DwarfCUToModule root_handler(&file_context, &line_to_module,
|
||||||
&ranges_handler, &reporter);
|
&ranges_handler, &reporter,
|
||||||
|
symbol_data_ & INLINES);
|
||||||
// Make a Dwarf2Handler that drives our DIEHandler.
|
// Make a Dwarf2Handler that drives our DIEHandler.
|
||||||
DIEDispatcher die_dispatcher(&root_handler);
|
DIEDispatcher die_dispatcher(&root_handler);
|
||||||
// Make a DWARF parser for the compilation unit at OFFSET.
|
// Make a DWARF parser for the compilation unit at OFFSET.
|
||||||
|
|
|
@ -303,8 +303,7 @@ bool Module::Write(std::ostream& stream, SymbolData symbol_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (symbol_data & SYMBOLS_AND_FILES) {
|
if (symbol_data & SYMBOLS_AND_FILES) {
|
||||||
if (symbol_data & INLINES)
|
CreateInlineOrigins();
|
||||||
CreateInlineOrigins();
|
|
||||||
AssignSourceIds();
|
AssignSourceIds();
|
||||||
|
|
||||||
// Write out files.
|
// Write out files.
|
||||||
|
@ -318,13 +317,11 @@ bool Module::Write(std::ostream& stream, SymbolData symbol_data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Write out inline origins.
|
// Write out inline origins.
|
||||||
if (symbol_data & INLINES) {
|
for (InlineOrigin* origin : inline_origins_) {
|
||||||
for (InlineOrigin* origin : inline_origins_) {
|
stream << "INLINE_ORIGIN " << origin->id << " " << origin->getFileID()
|
||||||
stream << "INLINE_ORIGIN " << origin->id << " " << origin->getFileID()
|
<< " " << origin->name << "\n";
|
||||||
<< " " << origin->name << "\n";
|
if (!stream.good())
|
||||||
if (!stream.good())
|
return ReportError();
|
||||||
return ReportError();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write out functions and their inlines and lines.
|
// Write out functions and their inlines and lines.
|
||||||
|
@ -344,19 +341,17 @@ bool Module::Write(std::ostream& stream, SymbolData symbol_data) {
|
||||||
return ReportError();
|
return ReportError();
|
||||||
|
|
||||||
// Write out inlines.
|
// Write out inlines.
|
||||||
if (symbol_data & INLINES) {
|
auto write_inline = [&](unique_ptr<Inline>& in) {
|
||||||
auto write_inline = [&](unique_ptr<Inline>& in) {
|
stream << "INLINE ";
|
||||||
stream << "INLINE ";
|
stream << in->inline_nest_level << " " << in->call_site_line << " "
|
||||||
stream << in->inline_nest_level << " " << in->call_site_line << " "
|
<< in->origin->id << hex;
|
||||||
<< in->origin->id << hex;
|
for (const Range& r : in->ranges)
|
||||||
for (const Range& r : in->ranges)
|
stream << " " << (r.address - load_address_) << " " << r.size;
|
||||||
stream << " " << (r.address - load_address_) << " " << r.size;
|
stream << dec << "\n";
|
||||||
stream << dec << "\n";
|
};
|
||||||
};
|
InlineDFS(func->inlines, write_inline);
|
||||||
InlineDFS(func->inlines, write_inline);
|
if (!stream.good())
|
||||||
if (!stream.good())
|
return ReportError();
|
||||||
return ReportError();
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((line_it != func->lines.end()) &&
|
while ((line_it != func->lines.end()) &&
|
||||||
(line_it->address >= range_it->address) &&
|
(line_it->address >= range_it->address) &&
|
||||||
|
|
Loading…
Reference in a new issue