Source code

Revision control

Copy as Markdown

Other Tools

changeset: 649910:59994b59eb51
tag: tip
parent: 649905:058997a8167d
user: Gabriele Svelto <gsvelto@mozilla.com>
date: Wed Mar 31 16:25:34 2021 +0200
summary: Bug 1702043 - Print out the list of unloaded modules when processing a minidump
diff --git a/src/google_breakpad/processor/minidump.h b/src/google_breakpad/processor/minidump.h
--- a/src/google_breakpad/processor/minidump.h
+++ b/src/google_breakpad/processor/minidump.h
@@ -792,16 +792,19 @@ class MinidumpUnloadedModule : public Mi
string debug_file() const override;
string debug_identifier() const override;
string version() const override;
CodeModule* Copy() const override;
bool is_unloaded() const override { return true; }
uint64_t shrink_down_delta() const override;
void SetShrinkDownDelta(uint64_t shrink_down_delta) override;
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
protected:
explicit MinidumpUnloadedModule(Minidump* minidump);
private:
// These objects are managed by MinidumpUnloadedModuleList
friend class MinidumpUnloadedModuleList;
// This works like MinidumpStream::Read, but is driven by
@@ -850,16 +853,19 @@ class MinidumpUnloadedModuleList : publi
const MinidumpUnloadedModule* GetMainModule() const override;
const MinidumpUnloadedModule*
GetModuleAtSequence(unsigned int sequence) const override;
const MinidumpUnloadedModule*
GetModuleAtIndex(unsigned int index) const override;
const CodeModules* Copy() const override;
vector<linked_ptr<const CodeModule>> GetShrunkRangeModules() const override;
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
protected:
explicit MinidumpUnloadedModuleList(Minidump* minidump_);
private:
friend class Minidump;
typedef vector<MinidumpUnloadedModule> MinidumpUnloadedModules;
diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc
--- a/src/processor/minidump.cc
+++ b/src/processor/minidump.cc
@@ -3727,16 +3727,46 @@ MinidumpUnloadedModule::MinidumpUnloaded
name_(NULL) {
}
MinidumpUnloadedModule::~MinidumpUnloadedModule() {
delete name_;
}
+void MinidumpUnloadedModule::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpUnloadedModule cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawUnloadedModule\n");
+ printf(" base_of_image = 0x%" PRIx64 "\n",
+ unloaded_module_.base_of_image);
+ printf(" size_of_image = 0x%x\n",
+ unloaded_module_.size_of_image);
+ printf(" checksum = 0x%x\n",
+ unloaded_module_.checksum);
+ printf(" time_date_stamp = 0x%x %s\n",
+ unloaded_module_.time_date_stamp,
+ TimeTToUTCString(unloaded_module_.time_date_stamp).c_str());
+ printf(" module_name_rva = 0x%x\n",
+ unloaded_module_.module_name_rva);
+
+ printf(" (code_file) = \"%s\"\n", code_file().c_str());
+ printf(" (code_identifier) = \"%s\"\n",
+ code_identifier().c_str());
+
+ printf(" (debug_file) = \"%s\"\n", debug_file().c_str());
+ printf(" (debug_identifier) = \"%s\"\n",
+ debug_identifier().c_str());
+ printf(" (version) = \"%s\"\n", version().c_str());
+ printf("\n");
+}
+
string MinidumpUnloadedModule::code_file() const {
if (!valid_) {
BPLOG(ERROR) << "Invalid MinidumpUnloadedModule for code_file";
return "";
}
return *name_;
}
@@ -3911,16 +3941,34 @@ MinidumpUnloadedModuleList::MinidumpUnlo
range_map_->SetMergeStrategy(MergeRangeStrategy::kTruncateLower);
}
MinidumpUnloadedModuleList::~MinidumpUnloadedModuleList() {
delete range_map_;
delete unloaded_modules_;
}
+void MinidumpUnloadedModuleList::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpUnloadedModuleList cannot print invalid data";
+ return;
+ }
+
+ printf("MinidumpUnloadedModuleList\n");
+ printf(" module_count = %d\n", module_count_);
+ printf("\n");
+
+ for (unsigned int module_index = 0;
+ module_index < module_count_;
+ ++module_index) {
+ printf("module[%d]\n", module_index);
+
+ (*unloaded_modules_)[module_index].Print();
+ }
+}
bool MinidumpUnloadedModuleList::Read(uint32_t expected_size) {
range_map_->Clear();
delete unloaded_modules_;
unloaded_modules_ = NULL;
module_count_ = 0;
valid_ = false;
diff --git a/src/processor/minidump_dump.cc b/src/processor/minidump_dump.cc
--- a/src/processor/minidump_dump.cc
+++ b/src/processor/minidump_dump.cc
@@ -40,16 +40,17 @@
#include "google_breakpad/processor/minidump.h"
#include "processor/logging.h"
namespace {
using google_breakpad::Minidump;
using google_breakpad::MinidumpThreadList;
using google_breakpad::MinidumpModuleList;
+using google_breakpad::MinidumpUnloadedModuleList;
using google_breakpad::MinidumpMemoryInfoList;
using google_breakpad::MinidumpMemoryList;
using google_breakpad::MinidumpException;
using google_breakpad::MinidumpAssertion;
using google_breakpad::MinidumpSystemInfo;
using google_breakpad::MinidumpMiscInfo;
using google_breakpad::MinidumpBreakpadInfo;
using google_breakpad::MinidumpCrashpadInfo;
@@ -127,16 +128,25 @@ static bool PrintMinidumpDump(const Opti
MinidumpModuleList *module_list = minidump.GetModuleList();
if (!module_list) {
++errors;
BPLOG(ERROR) << "minidump.GetModuleList() failed";
} else {
module_list->Print();
}
+ MinidumpUnloadedModuleList::set_max_modules(UINT32_MAX);
+ MinidumpUnloadedModuleList *unloaded_module_list = minidump.GetUnloadedModuleList();
+ if (!unloaded_module_list) {
+ ++errors;
+ BPLOG(ERROR) << "minidump.GetUnloadedModuleList() failed";
+ } else {
+ unloaded_module_list->Print();
+ }
+
MinidumpMemoryList *memory_list = minidump.GetMemoryList();
if (!memory_list) {
++errors;
BPLOG(ERROR) << "minidump.GetMemoryList() failed";
} else {
memory_list->Print();
}
diff --git a/src/processor/stackwalk_common.cc b/src/processor/stackwalk_common.cc
--- a/src/processor/stackwalk_common.cc
+++ b/src/processor/stackwalk_common.cc
@@ -777,16 +777,46 @@ static void PrintModulesMachineReadable(
StripSeparator(module->debug_identifier()).c_str(),
kOutputSeparator, base_address,
kOutputSeparator, base_address + module->size() - 1,
kOutputSeparator,
main_module != NULL && base_address == main_address ? 1 : 0);
}
}
+// PrintUnloadedModulesMachineReadable outputs a list of loaded modules,
+// one per line, in the following machine-readable pipe-delimited
+// text format:
+// UnloadedModule|{Module Filename}|{Base Address}|{Max Address}|{Main}
+static void PrintUnloadedModulesMachineReadable(const CodeModules* modules) {
+ if (!modules)
+ return;
+
+ uint64_t main_address = 0;
+ const CodeModule* main_module = modules->GetMainModule();
+ if (main_module) {
+ main_address = main_module->base_address();
+ }
+
+ unsigned int module_count = modules->module_count();
+ for (unsigned int module_sequence = 0;
+ module_sequence < module_count;
+ ++module_sequence) {
+ const CodeModule* module = modules->GetModuleAtSequence(module_sequence);
+ uint64_t base_address = module->base_address();
+ printf("UnloadedModule%c%s%c0x%08" PRIx64 "%c0x%08" PRIx64 "%c%d\n",
+ kOutputSeparator,
+ StripSeparator(PathnameStripper::File(module->code_file())).c_str(),
+ kOutputSeparator, base_address,
+ kOutputSeparator, base_address + module->size() - 1,
+ kOutputSeparator,
+ main_module != NULL && base_address == main_address ? 1 : 0);
+ }
+}
+
} // namespace
void PrintProcessState(const ProcessState& process_state,
bool output_stack_contents,
SourceLineResolverInterface* resolver) {
// Print OS and CPU information.
string cpu = process_state.system_info()->cpu;
string cpu_info = process_state.system_info()->cpu_info;
@@ -921,16 +951,17 @@ void PrintProcessStateMachineReadable(co
if (requesting_thread != -1) {
printf("%d\n", requesting_thread);
} else {
printf("\n");
}
PrintModulesMachineReadable(process_state.modules());
+ PrintUnloadedModulesMachineReadable(process_state.unloaded_modules());
// blank line to indicate start of threads
printf("\n");
// If the thread that requested the dump is known, print it first.
if (requesting_thread != -1) {
PrintStackMachineReadable(requesting_thread,
process_state.threads()->at(requesting_thread));