xref: /aosp_15_r20/external/google-breakpad/src/processor/minidump_dump.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle // Copyright 2006 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle //     * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle //     * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle //     * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle 
29*9712c20fSFrederick Mayle // minidump_dump.cc: Print the contents of a minidump file in somewhat
30*9712c20fSFrederick Mayle // readable text.
31*9712c20fSFrederick Mayle //
32*9712c20fSFrederick Mayle // Author: Mark Mentovai
33*9712c20fSFrederick Mayle 
34*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
35*9712c20fSFrederick Mayle #include <config.h>  // Must come first
36*9712c20fSFrederick Mayle #endif
37*9712c20fSFrederick Mayle 
38*9712c20fSFrederick Mayle #include <stdio.h>
39*9712c20fSFrederick Mayle #include <string.h>
40*9712c20fSFrederick Mayle #include <unistd.h>
41*9712c20fSFrederick Mayle 
42*9712c20fSFrederick Mayle #include "common/path_helper.h"
43*9712c20fSFrederick Mayle #include "common/scoped_ptr.h"
44*9712c20fSFrederick Mayle #include "google_breakpad/processor/minidump.h"
45*9712c20fSFrederick Mayle #include "processor/logging.h"
46*9712c20fSFrederick Mayle 
47*9712c20fSFrederick Mayle namespace {
48*9712c20fSFrederick Mayle 
49*9712c20fSFrederick Mayle using google_breakpad::Minidump;
50*9712c20fSFrederick Mayle using google_breakpad::MinidumpThreadList;
51*9712c20fSFrederick Mayle using google_breakpad::MinidumpThreadNameList;
52*9712c20fSFrederick Mayle using google_breakpad::MinidumpModuleList;
53*9712c20fSFrederick Mayle using google_breakpad::MinidumpMemoryInfoList;
54*9712c20fSFrederick Mayle using google_breakpad::MinidumpMemoryList;
55*9712c20fSFrederick Mayle using google_breakpad::MinidumpException;
56*9712c20fSFrederick Mayle using google_breakpad::MinidumpAssertion;
57*9712c20fSFrederick Mayle using google_breakpad::MinidumpSystemInfo;
58*9712c20fSFrederick Mayle using google_breakpad::MinidumpMiscInfo;
59*9712c20fSFrederick Mayle using google_breakpad::MinidumpBreakpadInfo;
60*9712c20fSFrederick Mayle using google_breakpad::MinidumpCrashpadInfo;
61*9712c20fSFrederick Mayle 
62*9712c20fSFrederick Mayle struct Options {
Options__anon42a3008c0111::Options63*9712c20fSFrederick Mayle   Options()
64*9712c20fSFrederick Mayle       : minidumpPath(), hexdump(false), hexdump_width(16) {}
65*9712c20fSFrederick Mayle 
66*9712c20fSFrederick Mayle   string minidumpPath;
67*9712c20fSFrederick Mayle   bool hexdump;
68*9712c20fSFrederick Mayle   unsigned int hexdump_width;
69*9712c20fSFrederick Mayle };
70*9712c20fSFrederick Mayle 
DumpRawStream(Minidump * minidump,uint32_t stream_type,const char * stream_name,int * errors)71*9712c20fSFrederick Mayle static void DumpRawStream(Minidump *minidump,
72*9712c20fSFrederick Mayle                           uint32_t stream_type,
73*9712c20fSFrederick Mayle                           const char *stream_name,
74*9712c20fSFrederick Mayle                           int *errors) {
75*9712c20fSFrederick Mayle   uint32_t length = 0;
76*9712c20fSFrederick Mayle   if (!minidump->SeekToStreamType(stream_type, &length)) {
77*9712c20fSFrederick Mayle     return;
78*9712c20fSFrederick Mayle   }
79*9712c20fSFrederick Mayle 
80*9712c20fSFrederick Mayle   printf("Stream %s:\n", stream_name);
81*9712c20fSFrederick Mayle 
82*9712c20fSFrederick Mayle   if (length == 0) {
83*9712c20fSFrederick Mayle     printf("\n");
84*9712c20fSFrederick Mayle     return;
85*9712c20fSFrederick Mayle   }
86*9712c20fSFrederick Mayle   std::vector<char> contents(length);
87*9712c20fSFrederick Mayle   if (!minidump->ReadBytes(&contents[0], length)) {
88*9712c20fSFrederick Mayle     ++*errors;
89*9712c20fSFrederick Mayle     BPLOG(ERROR) << "minidump.ReadBytes failed";
90*9712c20fSFrederick Mayle     return;
91*9712c20fSFrederick Mayle   }
92*9712c20fSFrederick Mayle   size_t current_offset = 0;
93*9712c20fSFrederick Mayle   while (current_offset < length) {
94*9712c20fSFrederick Mayle     size_t remaining = length - current_offset;
95*9712c20fSFrederick Mayle     // Printf requires an int and direct casting from size_t results
96*9712c20fSFrederick Mayle     // in compatibility warnings.
97*9712c20fSFrederick Mayle     uint32_t int_remaining = remaining;
98*9712c20fSFrederick Mayle     printf("%.*s", int_remaining, &contents[current_offset]);
99*9712c20fSFrederick Mayle     char *next_null = reinterpret_cast<char*>(
100*9712c20fSFrederick Mayle         memchr(&contents[current_offset], 0, remaining));
101*9712c20fSFrederick Mayle     if (next_null == NULL)
102*9712c20fSFrederick Mayle       break;
103*9712c20fSFrederick Mayle     printf("\\0\n");
104*9712c20fSFrederick Mayle     size_t null_offset = next_null - &contents[0];
105*9712c20fSFrederick Mayle     current_offset = null_offset + 1;
106*9712c20fSFrederick Mayle   }
107*9712c20fSFrederick Mayle   printf("\n\n");
108*9712c20fSFrederick Mayle }
109*9712c20fSFrederick Mayle 
PrintMinidumpDump(const Options & options)110*9712c20fSFrederick Mayle static bool PrintMinidumpDump(const Options& options) {
111*9712c20fSFrederick Mayle   Minidump minidump(options.minidumpPath,
112*9712c20fSFrederick Mayle                     options.hexdump);
113*9712c20fSFrederick Mayle   if (!minidump.Read()) {
114*9712c20fSFrederick Mayle     BPLOG(ERROR) << "minidump.Read() failed";
115*9712c20fSFrederick Mayle     return false;
116*9712c20fSFrederick Mayle   }
117*9712c20fSFrederick Mayle   minidump.Print();
118*9712c20fSFrederick Mayle 
119*9712c20fSFrederick Mayle   int errors = 0;
120*9712c20fSFrederick Mayle 
121*9712c20fSFrederick Mayle   MinidumpThreadList *thread_list = minidump.GetThreadList();
122*9712c20fSFrederick Mayle   if (!thread_list) {
123*9712c20fSFrederick Mayle     ++errors;
124*9712c20fSFrederick Mayle     BPLOG(ERROR) << "minidump.GetThreadList() failed";
125*9712c20fSFrederick Mayle   } else {
126*9712c20fSFrederick Mayle     thread_list->Print();
127*9712c20fSFrederick Mayle   }
128*9712c20fSFrederick Mayle 
129*9712c20fSFrederick Mayle   MinidumpThreadNameList *thread_name_list = minidump.GetThreadNameList();
130*9712c20fSFrederick Mayle   if (thread_name_list) {
131*9712c20fSFrederick Mayle     thread_name_list->Print();
132*9712c20fSFrederick Mayle   }
133*9712c20fSFrederick Mayle 
134*9712c20fSFrederick Mayle   // It's useful to be able to see the full list of modules here even if it
135*9712c20fSFrederick Mayle   // would cause minidump_stackwalk to fail.
136*9712c20fSFrederick Mayle   MinidumpModuleList::set_max_modules(UINT32_MAX);
137*9712c20fSFrederick Mayle   MinidumpModuleList *module_list = minidump.GetModuleList();
138*9712c20fSFrederick Mayle   if (!module_list) {
139*9712c20fSFrederick Mayle     ++errors;
140*9712c20fSFrederick Mayle     BPLOG(ERROR) << "minidump.GetModuleList() failed";
141*9712c20fSFrederick Mayle   } else {
142*9712c20fSFrederick Mayle     module_list->Print();
143*9712c20fSFrederick Mayle   }
144*9712c20fSFrederick Mayle 
145*9712c20fSFrederick Mayle   MinidumpMemoryList *memory_list = minidump.GetMemoryList();
146*9712c20fSFrederick Mayle   if (!memory_list) {
147*9712c20fSFrederick Mayle     ++errors;
148*9712c20fSFrederick Mayle     BPLOG(ERROR) << "minidump.GetMemoryList() failed";
149*9712c20fSFrederick Mayle   } else {
150*9712c20fSFrederick Mayle     memory_list->Print();
151*9712c20fSFrederick Mayle   }
152*9712c20fSFrederick Mayle 
153*9712c20fSFrederick Mayle   MinidumpException *exception = minidump.GetException();
154*9712c20fSFrederick Mayle   if (!exception) {
155*9712c20fSFrederick Mayle     BPLOG(INFO) << "minidump.GetException() failed";
156*9712c20fSFrederick Mayle   } else {
157*9712c20fSFrederick Mayle     exception->Print();
158*9712c20fSFrederick Mayle   }
159*9712c20fSFrederick Mayle 
160*9712c20fSFrederick Mayle   MinidumpAssertion *assertion = minidump.GetAssertion();
161*9712c20fSFrederick Mayle   if (!assertion) {
162*9712c20fSFrederick Mayle     BPLOG(INFO) << "minidump.GetAssertion() failed";
163*9712c20fSFrederick Mayle   } else {
164*9712c20fSFrederick Mayle     assertion->Print();
165*9712c20fSFrederick Mayle   }
166*9712c20fSFrederick Mayle 
167*9712c20fSFrederick Mayle   MinidumpSystemInfo *system_info = minidump.GetSystemInfo();
168*9712c20fSFrederick Mayle   if (!system_info) {
169*9712c20fSFrederick Mayle     ++errors;
170*9712c20fSFrederick Mayle     BPLOG(ERROR) << "minidump.GetSystemInfo() failed";
171*9712c20fSFrederick Mayle   } else {
172*9712c20fSFrederick Mayle     system_info->Print();
173*9712c20fSFrederick Mayle   }
174*9712c20fSFrederick Mayle 
175*9712c20fSFrederick Mayle   MinidumpMiscInfo *misc_info = minidump.GetMiscInfo();
176*9712c20fSFrederick Mayle   if (!misc_info) {
177*9712c20fSFrederick Mayle     ++errors;
178*9712c20fSFrederick Mayle     BPLOG(ERROR) << "minidump.GetMiscInfo() failed";
179*9712c20fSFrederick Mayle   } else {
180*9712c20fSFrederick Mayle     misc_info->Print();
181*9712c20fSFrederick Mayle   }
182*9712c20fSFrederick Mayle 
183*9712c20fSFrederick Mayle   MinidumpBreakpadInfo *breakpad_info = minidump.GetBreakpadInfo();
184*9712c20fSFrederick Mayle   if (!breakpad_info) {
185*9712c20fSFrederick Mayle     // Breakpad info is optional, so don't treat this as an error.
186*9712c20fSFrederick Mayle     BPLOG(INFO) << "minidump.GetBreakpadInfo() failed";
187*9712c20fSFrederick Mayle   } else {
188*9712c20fSFrederick Mayle     breakpad_info->Print();
189*9712c20fSFrederick Mayle   }
190*9712c20fSFrederick Mayle 
191*9712c20fSFrederick Mayle   MinidumpMemoryInfoList *memory_info_list = minidump.GetMemoryInfoList();
192*9712c20fSFrederick Mayle   if (!memory_info_list) {
193*9712c20fSFrederick Mayle     ++errors;
194*9712c20fSFrederick Mayle     BPLOG(ERROR) << "minidump.GetMemoryInfoList() failed";
195*9712c20fSFrederick Mayle   } else {
196*9712c20fSFrederick Mayle     memory_info_list->Print();
197*9712c20fSFrederick Mayle   }
198*9712c20fSFrederick Mayle 
199*9712c20fSFrederick Mayle   MinidumpCrashpadInfo *crashpad_info = minidump.GetCrashpadInfo();
200*9712c20fSFrederick Mayle   if (crashpad_info) {
201*9712c20fSFrederick Mayle     // Crashpad info is optional, so don't treat absence as an error.
202*9712c20fSFrederick Mayle     crashpad_info->Print();
203*9712c20fSFrederick Mayle   }
204*9712c20fSFrederick Mayle 
205*9712c20fSFrederick Mayle   DumpRawStream(&minidump,
206*9712c20fSFrederick Mayle                 MD_LINUX_CMD_LINE,
207*9712c20fSFrederick Mayle                 "MD_LINUX_CMD_LINE",
208*9712c20fSFrederick Mayle                 &errors);
209*9712c20fSFrederick Mayle   DumpRawStream(&minidump,
210*9712c20fSFrederick Mayle                 MD_LINUX_ENVIRON,
211*9712c20fSFrederick Mayle                 "MD_LINUX_ENVIRON",
212*9712c20fSFrederick Mayle                 &errors);
213*9712c20fSFrederick Mayle   DumpRawStream(&minidump,
214*9712c20fSFrederick Mayle                 MD_LINUX_LSB_RELEASE,
215*9712c20fSFrederick Mayle                 "MD_LINUX_LSB_RELEASE",
216*9712c20fSFrederick Mayle                 &errors);
217*9712c20fSFrederick Mayle   DumpRawStream(&minidump,
218*9712c20fSFrederick Mayle                 MD_LINUX_PROC_STATUS,
219*9712c20fSFrederick Mayle                 "MD_LINUX_PROC_STATUS",
220*9712c20fSFrederick Mayle                 &errors);
221*9712c20fSFrederick Mayle   DumpRawStream(&minidump,
222*9712c20fSFrederick Mayle                 MD_LINUX_CPU_INFO,
223*9712c20fSFrederick Mayle                 "MD_LINUX_CPU_INFO",
224*9712c20fSFrederick Mayle                 &errors);
225*9712c20fSFrederick Mayle   DumpRawStream(&minidump,
226*9712c20fSFrederick Mayle                 MD_LINUX_MAPS,
227*9712c20fSFrederick Mayle                 "MD_LINUX_MAPS",
228*9712c20fSFrederick Mayle                 &errors);
229*9712c20fSFrederick Mayle 
230*9712c20fSFrederick Mayle   return errors == 0;
231*9712c20fSFrederick Mayle }
232*9712c20fSFrederick Mayle 
233*9712c20fSFrederick Mayle //=============================================================================
234*9712c20fSFrederick Mayle static void
Usage(int argc,char * argv[],bool error)235*9712c20fSFrederick Mayle Usage(int argc, char *argv[], bool error) {
236*9712c20fSFrederick Mayle   FILE *fp = error ? stderr : stdout;
237*9712c20fSFrederick Mayle 
238*9712c20fSFrederick Mayle   fprintf(fp,
239*9712c20fSFrederick Mayle           "Usage: %s [options...] <minidump>\n"
240*9712c20fSFrederick Mayle           "Dump data in a minidump.\n"
241*9712c20fSFrederick Mayle           "\n"
242*9712c20fSFrederick Mayle           "Options:\n"
243*9712c20fSFrederick Mayle           "  <minidump> should be a minidump.\n"
244*9712c20fSFrederick Mayle           "  -x:\t Display memory in a hexdump like format\n"
245*9712c20fSFrederick Mayle           "  -h:\t Usage\n",
246*9712c20fSFrederick Mayle           google_breakpad::BaseName(argv[0]).c_str());
247*9712c20fSFrederick Mayle }
248*9712c20fSFrederick Mayle 
249*9712c20fSFrederick Mayle //=============================================================================
250*9712c20fSFrederick Mayle static void
SetupOptions(int argc,char * argv[],Options * options)251*9712c20fSFrederick Mayle SetupOptions(int argc, char *argv[], Options *options) {
252*9712c20fSFrederick Mayle   int ch;
253*9712c20fSFrederick Mayle 
254*9712c20fSFrederick Mayle   while ((ch = getopt(argc, (char * const*)argv, "xh")) != -1) {
255*9712c20fSFrederick Mayle     switch (ch) {
256*9712c20fSFrederick Mayle       case 'x':
257*9712c20fSFrederick Mayle         options->hexdump = true;
258*9712c20fSFrederick Mayle         break;
259*9712c20fSFrederick Mayle       case 'h':
260*9712c20fSFrederick Mayle         Usage(argc, argv, false);
261*9712c20fSFrederick Mayle         exit(0);
262*9712c20fSFrederick Mayle 
263*9712c20fSFrederick Mayle       default:
264*9712c20fSFrederick Mayle         Usage(argc, argv, true);
265*9712c20fSFrederick Mayle         exit(1);
266*9712c20fSFrederick Mayle         break;
267*9712c20fSFrederick Mayle     }
268*9712c20fSFrederick Mayle   }
269*9712c20fSFrederick Mayle 
270*9712c20fSFrederick Mayle   if ((argc - optind) != 1) {
271*9712c20fSFrederick Mayle     fprintf(stderr, "%s: Missing minidump file\n", argv[0]);
272*9712c20fSFrederick Mayle     exit(1);
273*9712c20fSFrederick Mayle   }
274*9712c20fSFrederick Mayle 
275*9712c20fSFrederick Mayle   options->minidumpPath = argv[optind];
276*9712c20fSFrederick Mayle }
277*9712c20fSFrederick Mayle 
278*9712c20fSFrederick Mayle }  // namespace
279*9712c20fSFrederick Mayle 
main(int argc,char * argv[])280*9712c20fSFrederick Mayle int main(int argc, char *argv[]) {
281*9712c20fSFrederick Mayle   Options options;
282*9712c20fSFrederick Mayle   BPLOG_INIT(&argc, &argv);
283*9712c20fSFrederick Mayle   SetupOptions(argc, argv, &options);
284*9712c20fSFrederick Mayle   return PrintMinidumpDump(options) ? 0 : 1;
285*9712c20fSFrederick Mayle }
286