diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc')
-rw-r--r-- | toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc new file mode 100644 index 0000000000..63f25f3800 --- /dev/null +++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc @@ -0,0 +1,291 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// minidump_dump.cc: Print the contents of a minidump file in somewhat +// readable text. +// +// Author: Mark Mentovai + +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "common/scoped_ptr.h" +#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; +using google_breakpad::MinidumpThreadNamesList; + +struct Options { + Options() + : minidumpPath(), hexdump(false), hexdump_width(16) {} + + string minidumpPath; + bool hexdump; + unsigned int hexdump_width; +}; + +static void DumpRawStream(Minidump *minidump, + uint32_t stream_type, + const char *stream_name, + int *errors) { + uint32_t length = 0; + if (!minidump->SeekToStreamType(stream_type, &length)) { + return; + } + + printf("Stream %s:\n", stream_name); + + if (length == 0) { + printf("\n"); + return; + } + std::vector<char> contents(length); + if (!minidump->ReadBytes(&contents[0], length)) { + ++*errors; + BPLOG(ERROR) << "minidump.ReadBytes failed"; + return; + } + size_t current_offset = 0; + while (current_offset < length) { + size_t remaining = length - current_offset; + // Printf requires an int and direct casting from size_t results + // in compatibility warnings. + uint32_t int_remaining = remaining; + printf("%.*s", int_remaining, &contents[current_offset]); + char *next_null = reinterpret_cast<char *>( + memchr(&contents[current_offset], 0, remaining)); + if (next_null == NULL) + break; + printf("\\0\n"); + size_t null_offset = next_null - &contents[0]; + current_offset = null_offset + 1; + } + printf("\n\n"); +} + +static bool PrintMinidumpDump(const Options& options) { + Minidump minidump(options.minidumpPath, + options.hexdump); + if (!minidump.Read()) { + BPLOG(ERROR) << "minidump.Read() failed"; + return false; + } + minidump.Print(); + + int errors = 0; + + MinidumpThreadList *thread_list = minidump.GetThreadList(); + if (!thread_list) { + ++errors; + BPLOG(ERROR) << "minidump.GetThreadList() failed"; + } else { + thread_list->Print(); + } + + // It's useful to be able to see the full list of modules here even if it + // would cause minidump_stackwalk to fail. + MinidumpModuleList::set_max_modules(UINT32_MAX); + 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(); + } + + MinidumpException *exception = minidump.GetException(); + if (!exception) { + BPLOG(INFO) << "minidump.GetException() failed"; + } else { + exception->Print(); + } + + MinidumpAssertion *assertion = minidump.GetAssertion(); + if (!assertion) { + BPLOG(INFO) << "minidump.GetAssertion() failed"; + } else { + assertion->Print(); + } + + MinidumpSystemInfo *system_info = minidump.GetSystemInfo(); + if (!system_info) { + ++errors; + BPLOG(ERROR) << "minidump.GetSystemInfo() failed"; + } else { + system_info->Print(); + } + + MinidumpMiscInfo *misc_info = minidump.GetMiscInfo(); + if (!misc_info) { + ++errors; + BPLOG(ERROR) << "minidump.GetMiscInfo() failed"; + } else { + misc_info->Print(); + } + + MinidumpBreakpadInfo *breakpad_info = minidump.GetBreakpadInfo(); + if (!breakpad_info) { + // Breakpad info is optional, so don't treat this as an error. + BPLOG(INFO) << "minidump.GetBreakpadInfo() failed"; + } else { + breakpad_info->Print(); + } + + MinidumpMemoryInfoList *memory_info_list = minidump.GetMemoryInfoList(); + if (!memory_info_list) { + ++errors; + BPLOG(ERROR) << "minidump.GetMemoryInfoList() failed"; + } else { + memory_info_list->Print(); + } + + MinidumpCrashpadInfo *crashpad_info = minidump.GetCrashpadInfo(); + if (crashpad_info) { + // Crashpad info is optional, so don't treat absence as an error. + crashpad_info->Print(); + } + + MinidumpThreadNamesList *thread_names_list = minidump.GetThreadNamesList(); + if (thread_names_list) { + thread_names_list->Print(); + } + + DumpRawStream(&minidump, + MD_LINUX_CMD_LINE, + "MD_LINUX_CMD_LINE", + &errors); + DumpRawStream(&minidump, + MD_LINUX_ENVIRON, + "MD_LINUX_ENVIRON", + &errors); + DumpRawStream(&minidump, + MD_LINUX_LSB_RELEASE, + "MD_LINUX_LSB_RELEASE", + &errors); + DumpRawStream(&minidump, + MD_LINUX_PROC_STATUS, + "MD_LINUX_PROC_STATUS", + &errors); + DumpRawStream(&minidump, + MD_LINUX_CPU_INFO, + "MD_LINUX_CPU_INFO", + &errors); + DumpRawStream(&minidump, + MD_LINUX_MAPS, + "MD_LINUX_MAPS", + &errors); + + return errors == 0; +} + +//============================================================================= +static void +Usage(int argc, char *argv[], bool error) { + FILE *fp = error ? stderr : stdout; + + fprintf(fp, + "Usage: %s [options...] <minidump>\n" + "Dump data in a minidump.\n" + "\n" + "Options:\n" + " <minidump> should be a minidump.\n" + " -x:\t Display memory in a hexdump like format\n" + " -h:\t Usage\n", + argv[0]); +} + +//============================================================================= +static void +SetupOptions(int argc, char *argv[], Options *options) { + int ch; + + while ((ch = getopt(argc, (char * const *)argv, "xh")) != -1) { + switch (ch) { + case 'x': + options->hexdump = true; + break; + case 'h': + Usage(argc, argv, false); + exit(0); + + default: + Usage(argc, argv, true); + exit(1); + break; + } + } + + if ((argc - optind) != 1) { + fprintf(stderr, "%s: Missing minidump file\n", argv[0]); + exit(1); + } + + options->minidumpPath = argv[optind]; +} + +} // namespace + +int main(int argc, char *argv[]) { + Options options; + BPLOG_INIT(&argc, &argv); + SetupOptions(argc, argv, &options); + return PrintMinidumpDump(options) ? 0 : 1; +} |