summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/breakpad-patches/17-unloaded-modules.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/crashreporter/breakpad-patches/17-unloaded-modules.patch')
-rw-r--r--toolkit/crashreporter/breakpad-patches/17-unloaded-modules.patch251
1 files changed, 251 insertions, 0 deletions
diff --git a/toolkit/crashreporter/breakpad-patches/17-unloaded-modules.patch b/toolkit/crashreporter/breakpad-patches/17-unloaded-modules.patch
new file mode 100644
index 0000000000..c413e4eff4
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/17-unloaded-modules.patch
@@ -0,0 +1,251 @@
+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));
+