Add command line switch for reporting DWARF warnings.
Change-Id: Ibcf1b0ddb93f1cf6bf12681ed82871328571f2aa Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/5137659 Reviewed-by: Ivan Penkov <ivanpe@chromium.org>
This commit is contained in:
parent
446298620b
commit
048e14caf8
4 changed files with 88 additions and 5 deletions
|
@ -254,6 +254,63 @@ class DwarfCUToModule: public RootDIEHandler {
|
||||||
void UncoveredHeading();
|
void UncoveredHeading();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NullWarningReporter: public WarningReporter {
|
||||||
|
public:
|
||||||
|
NullWarningReporter(const string &filename, uint64_t cu_offset):
|
||||||
|
WarningReporter(filename, cu_offset) { }
|
||||||
|
|
||||||
|
// Set the name of the compilation unit we're processing to NAME.
|
||||||
|
void SetCUName(const string &name) { }
|
||||||
|
|
||||||
|
// Accessor and setter for uncovered_warnings_enabled_.
|
||||||
|
// UncoveredFunction and UncoveredLine only report a problem if that is
|
||||||
|
// true. By default, these warnings are disabled, because those
|
||||||
|
// conditions occur occasionally in healthy code.
|
||||||
|
void set_uncovered_warnings_enabled(bool value) { }
|
||||||
|
|
||||||
|
// A DW_AT_specification in the DIE at OFFSET refers to a DIE we
|
||||||
|
// haven't processed yet, or that wasn't marked as a declaration,
|
||||||
|
// at TARGET.
|
||||||
|
void UnknownSpecification(uint64_t offset, uint64_t target) { }
|
||||||
|
|
||||||
|
// A DW_AT_abstract_origin in the DIE at OFFSET refers to a DIE we
|
||||||
|
// haven't processed yet, or that wasn't marked as inline, at TARGET.
|
||||||
|
void UnknownAbstractOrigin(uint64_t offset, uint64_t target) { }
|
||||||
|
|
||||||
|
// We were unable to find the DWARF section named SECTION_NAME.
|
||||||
|
void MissingSection(const string §ion_name) { }
|
||||||
|
|
||||||
|
// The CU's DW_AT_stmt_list offset OFFSET is bogus.
|
||||||
|
void BadLineInfoOffset(uint64_t offset) { }
|
||||||
|
|
||||||
|
// FUNCTION includes code covered by no line number data.
|
||||||
|
void UncoveredFunction(const Module::Function &function) { }
|
||||||
|
|
||||||
|
// Line number NUMBER in LINE_FILE, of length LENGTH, includes code
|
||||||
|
// covered by no function.
|
||||||
|
void UncoveredLine(const Module::Line &line) { }
|
||||||
|
|
||||||
|
// The DW_TAG_subprogram DIE at OFFSET has no name specified directly
|
||||||
|
// in the DIE, nor via a DW_AT_specification or DW_AT_abstract_origin
|
||||||
|
// link.
|
||||||
|
void UnnamedFunction(uint64_t offset) { }
|
||||||
|
|
||||||
|
// __cxa_demangle() failed to demangle INPUT.
|
||||||
|
void DemangleError(const string &input) { }
|
||||||
|
|
||||||
|
// The DW_FORM_ref_addr at OFFSET to TARGET was not handled because
|
||||||
|
// FilePrivate did not retain the inter-CU specification data.
|
||||||
|
void UnhandledInterCUReference(uint64_t offset, uint64_t target) { }
|
||||||
|
|
||||||
|
// The DW_AT_ranges at offset is malformed (truncated or outside of the
|
||||||
|
// .debug_ranges section's bound).
|
||||||
|
void MalformedRangeList(uint64_t offset) { }
|
||||||
|
|
||||||
|
// A DW_AT_ranges attribute was encountered but the no .debug_ranges
|
||||||
|
// section was found.
|
||||||
|
void MissingRanges() { }
|
||||||
|
};
|
||||||
|
|
||||||
// Create a DWARF debugging info handler for a compilation unit
|
// Create a DWARF debugging info handler for a compilation unit
|
||||||
// within FILE_CONTEXT. This uses information received from the
|
// within FILE_CONTEXT. This uses information received from the
|
||||||
// CompilationUnit DWARF parser to populate
|
// CompilationUnit DWARF parser to populate
|
||||||
|
|
|
@ -265,6 +265,10 @@ SuperFatArch* DumpSymbols::FindBestMatchForArchitecture(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DumpSymbols::SetReportWarnings(bool report_warnings) {
|
||||||
|
report_warnings_ = report_warnings;
|
||||||
|
}
|
||||||
|
|
||||||
string DumpSymbols::Identifier() {
|
string DumpSymbols::Identifier() {
|
||||||
scoped_ptr<FileID> file_id;
|
scoped_ptr<FileID> file_id;
|
||||||
|
|
||||||
|
@ -524,10 +528,17 @@ void DumpSymbols::ReadDwarf(google_breakpad::Module* module,
|
||||||
for (uint64_t offset = 0; offset < debug_info_length;) {
|
for (uint64_t offset = 0; offset < debug_info_length;) {
|
||||||
// Make a handler for the root DIE that populates MODULE with the
|
// Make a handler for the root DIE that populates MODULE with the
|
||||||
// debug info.
|
// debug info.
|
||||||
DwarfCUToModule::WarningReporter reporter(selected_object_name_,
|
DwarfCUToModule::WarningReporter *reporter = nullptr;
|
||||||
offset);
|
if (report_warnings_) {
|
||||||
|
reporter = new DwarfCUToModule::WarningReporter(
|
||||||
|
selected_object_name_, offset);
|
||||||
|
} else {
|
||||||
|
reporter = new DwarfCUToModule::NullWarningReporter(
|
||||||
|
selected_object_name_, offset);
|
||||||
|
}
|
||||||
DwarfCUToModule root_handler(&file_context, &line_to_module,
|
DwarfCUToModule root_handler(&file_context, &line_to_module,
|
||||||
&ranges_handler, &reporter, handle_inline);
|
&ranges_handler, reporter,
|
||||||
|
handle_inline);
|
||||||
// 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.
|
||||||
|
@ -543,6 +554,7 @@ void DumpSymbols::ReadDwarf(google_breakpad::Module* module,
|
||||||
StartProcessSplitDwarf(&dwarf_reader, module, endianness,
|
StartProcessSplitDwarf(&dwarf_reader, module, endianness,
|
||||||
handle_inter_cu_refs, handle_inline);
|
handle_inter_cu_refs, handle_inline);
|
||||||
}
|
}
|
||||||
|
delete reporter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,8 @@ class DumpSymbols {
|
||||||
selected_object_name_(),
|
selected_object_name_(),
|
||||||
enable_multiple_(enable_multiple),
|
enable_multiple_(enable_multiple),
|
||||||
module_name_(module_name),
|
module_name_(module_name),
|
||||||
prefer_extern_name_(prefer_extern_name) {}
|
prefer_extern_name_(prefer_extern_name),
|
||||||
|
report_warnings_(true) {}
|
||||||
~DumpSymbols() = default;
|
~DumpSymbols() = default;
|
||||||
|
|
||||||
// Prepare to read debugging information from |filename|. |filename| may be
|
// Prepare to read debugging information from |filename|. |filename| may be
|
||||||
|
@ -103,6 +104,9 @@ class DumpSymbols {
|
||||||
// architecture matches that of this dumper program.
|
// architecture matches that of this dumper program.
|
||||||
bool SetArchitecture(const ArchInfo& info);
|
bool SetArchitecture(const ArchInfo& info);
|
||||||
|
|
||||||
|
// Set whether or not to report DWARF warnings
|
||||||
|
void SetReportWarnings(bool report_warnings);
|
||||||
|
|
||||||
// Return a pointer to an array of SuperFatArch structures describing the
|
// Return a pointer to an array of SuperFatArch structures describing the
|
||||||
// object files contained in this dumper's file. Set *|count| to the number
|
// object files contained in this dumper's file. Set *|count| to the number
|
||||||
// of elements in the array. The returned array is owned by this DumpSymbols
|
// of elements in the array. The returned array is owned by this DumpSymbols
|
||||||
|
@ -224,6 +228,9 @@ class DumpSymbols {
|
||||||
// (which are placed in the Extern), not in the DWARF symbols (which are
|
// (which are placed in the Extern), not in the DWARF symbols (which are
|
||||||
// placed in the Function).
|
// placed in the Function).
|
||||||
bool prefer_extern_name_;
|
bool prefer_extern_name_;
|
||||||
|
|
||||||
|
// Whether or not to report warnings
|
||||||
|
bool report_warnings_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
|
@ -77,6 +77,7 @@ struct Options {
|
||||||
bool enable_multiple;
|
bool enable_multiple;
|
||||||
string module_name;
|
string module_name;
|
||||||
bool prefer_extern_name;
|
bool prefer_extern_name;
|
||||||
|
bool report_warnings;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool StackFrameEntryComparator(const Module::StackFrameEntry* a,
|
static bool StackFrameEntryComparator(const Module::StackFrameEntry* a,
|
||||||
|
@ -169,6 +170,8 @@ static bool Start(const Options& options) {
|
||||||
const string& primary_file =
|
const string& primary_file =
|
||||||
split_module ? options.dsymPath : options.srcPath;
|
split_module ? options.dsymPath : options.srcPath;
|
||||||
|
|
||||||
|
dump_symbols.SetReportWarnings(options.report_warnings);
|
||||||
|
|
||||||
if (!dump_symbols.Read(primary_file))
|
if (!dump_symbols.Read(primary_file))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -250,6 +253,7 @@ static void Usage(int argc, const char *argv[]) {
|
||||||
"[-n MODULE] [-x] <Mach-o file>\n",
|
"[-n MODULE] [-x] <Mach-o file>\n",
|
||||||
argv[0]);
|
argv[0]);
|
||||||
fprintf(stderr, "\t-i: Output module header information only.\n");
|
fprintf(stderr, "\t-i: Output module header information only.\n");
|
||||||
|
fprintf(stderr, "\t-w: Output warning information.\n");
|
||||||
fprintf(stderr, "\t-a: Architecture type [default: native, or whatever is\n");
|
fprintf(stderr, "\t-a: Architecture type [default: native, or whatever is\n");
|
||||||
fprintf(stderr, "\t in the file, if it contains only one architecture]\n");
|
fprintf(stderr, "\t in the file, if it contains only one architecture]\n");
|
||||||
fprintf(stderr, "\t-g: Debug symbol file (dSYM) to dump in addition to the "
|
fprintf(stderr, "\t-g: Debug symbol file (dSYM) to dump in addition to the "
|
||||||
|
@ -275,11 +279,14 @@ static void SetupOptions(int argc, const char *argv[], Options *options) {
|
||||||
extern int optind;
|
extern int optind;
|
||||||
signed char ch;
|
signed char ch;
|
||||||
|
|
||||||
while ((ch = getopt(argc, (char* const*)argv, "ia:g:crdm?hn:x")) != -1) {
|
while ((ch = getopt(argc, (char* const*)argv, "iwa:g:crdm?hn:x")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'i':
|
case 'i':
|
||||||
options->header_only = true;
|
options->header_only = true;
|
||||||
break;
|
break;
|
||||||
|
case 'w':
|
||||||
|
options->report_warnings = true;
|
||||||
|
break;
|
||||||
case 'a': {
|
case 'a': {
|
||||||
std::optional<ArchInfo> arch_info = GetArchInfoFromName(optarg);
|
std::optional<ArchInfo> arch_info = GetArchInfoFromName(optarg);
|
||||||
if (!arch_info) {
|
if (!arch_info) {
|
||||||
|
|
Loading…
Reference in a new issue