xref: /aosp_15_r20/external/google-breakpad/src/processor/minidump_stackwalk.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle // Copyright 2010 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_stackwalk.cc: Process a minidump with MinidumpProcessor, printing
30*9712c20fSFrederick Mayle // the results, including stack traces.
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 <limits>
43*9712c20fSFrederick Mayle #include <string>
44*9712c20fSFrederick Mayle #include <vector>
45*9712c20fSFrederick Mayle 
46*9712c20fSFrederick Mayle #include "common/path_helper.h"
47*9712c20fSFrederick Mayle #include "common/scoped_ptr.h"
48*9712c20fSFrederick Mayle #include "common/using_std_string.h"
49*9712c20fSFrederick Mayle #include "google_breakpad/processor/basic_source_line_resolver.h"
50*9712c20fSFrederick Mayle #include "google_breakpad/processor/minidump.h"
51*9712c20fSFrederick Mayle #include "google_breakpad/processor/minidump_processor.h"
52*9712c20fSFrederick Mayle #include "google_breakpad/processor/process_state.h"
53*9712c20fSFrederick Mayle #include "processor/logging.h"
54*9712c20fSFrederick Mayle #include "processor/simple_symbol_supplier.h"
55*9712c20fSFrederick Mayle #include "processor/stackwalk_common.h"
56*9712c20fSFrederick Mayle 
57*9712c20fSFrederick Mayle 
58*9712c20fSFrederick Mayle namespace {
59*9712c20fSFrederick Mayle 
60*9712c20fSFrederick Mayle struct Options {
61*9712c20fSFrederick Mayle   bool machine_readable;
62*9712c20fSFrederick Mayle   bool output_stack_contents;
63*9712c20fSFrederick Mayle   bool output_requesting_thread_only;
64*9712c20fSFrederick Mayle   bool brief;
65*9712c20fSFrederick Mayle 
66*9712c20fSFrederick Mayle   string minidump_file;
67*9712c20fSFrederick Mayle   std::vector<string> symbol_paths;
68*9712c20fSFrederick Mayle };
69*9712c20fSFrederick Mayle 
70*9712c20fSFrederick Mayle using google_breakpad::BasicSourceLineResolver;
71*9712c20fSFrederick Mayle using google_breakpad::Minidump;
72*9712c20fSFrederick Mayle using google_breakpad::MinidumpMemoryList;
73*9712c20fSFrederick Mayle using google_breakpad::MinidumpThreadList;
74*9712c20fSFrederick Mayle using google_breakpad::MinidumpProcessor;
75*9712c20fSFrederick Mayle using google_breakpad::ProcessState;
76*9712c20fSFrederick Mayle using google_breakpad::SimpleSymbolSupplier;
77*9712c20fSFrederick Mayle using google_breakpad::scoped_ptr;
78*9712c20fSFrederick Mayle 
79*9712c20fSFrederick Mayle // Processes |options.minidump_file| using MinidumpProcessor.
80*9712c20fSFrederick Mayle // |options.symbol_path|, if non-empty, is the base directory of a
81*9712c20fSFrederick Mayle // symbol storage area, laid out in the format required by
82*9712c20fSFrederick Mayle // SimpleSymbolSupplier.  If such a storage area is specified, it is
83*9712c20fSFrederick Mayle // made available for use by the MinidumpProcessor.
84*9712c20fSFrederick Mayle //
85*9712c20fSFrederick Mayle // Returns the value of MinidumpProcessor::Process.  If processing succeeds,
86*9712c20fSFrederick Mayle // prints identifying OS and CPU information from the minidump, crash
87*9712c20fSFrederick Mayle // information if the minidump was produced as a result of a crash, and
88*9712c20fSFrederick Mayle // call stacks for each thread contained in the minidump.  All information
89*9712c20fSFrederick Mayle // is printed to stdout.
PrintMinidumpProcess(const Options & options)90*9712c20fSFrederick Mayle bool PrintMinidumpProcess(const Options& options) {
91*9712c20fSFrederick Mayle   scoped_ptr<SimpleSymbolSupplier> symbol_supplier;
92*9712c20fSFrederick Mayle   if (!options.symbol_paths.empty()) {
93*9712c20fSFrederick Mayle     // TODO(mmentovai): check existence of symbol_path if specified?
94*9712c20fSFrederick Mayle     symbol_supplier.reset(new SimpleSymbolSupplier(options.symbol_paths));
95*9712c20fSFrederick Mayle   }
96*9712c20fSFrederick Mayle 
97*9712c20fSFrederick Mayle   BasicSourceLineResolver resolver;
98*9712c20fSFrederick Mayle   MinidumpProcessor minidump_processor(symbol_supplier.get(), &resolver);
99*9712c20fSFrederick Mayle 
100*9712c20fSFrederick Mayle   // Increase the maximum number of threads and regions.
101*9712c20fSFrederick Mayle   MinidumpThreadList::set_max_threads(std::numeric_limits<uint32_t>::max());
102*9712c20fSFrederick Mayle   MinidumpMemoryList::set_max_regions(std::numeric_limits<uint32_t>::max());
103*9712c20fSFrederick Mayle   // Process the minidump.
104*9712c20fSFrederick Mayle   Minidump dump(options.minidump_file);
105*9712c20fSFrederick Mayle   if (!dump.Read()) {
106*9712c20fSFrederick Mayle      BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read";
107*9712c20fSFrederick Mayle      return false;
108*9712c20fSFrederick Mayle   }
109*9712c20fSFrederick Mayle   ProcessState process_state;
110*9712c20fSFrederick Mayle   if (minidump_processor.Process(&dump, &process_state) !=
111*9712c20fSFrederick Mayle       google_breakpad::PROCESS_OK) {
112*9712c20fSFrederick Mayle     BPLOG(ERROR) << "MinidumpProcessor::Process failed";
113*9712c20fSFrederick Mayle     return false;
114*9712c20fSFrederick Mayle   }
115*9712c20fSFrederick Mayle 
116*9712c20fSFrederick Mayle   if (options.machine_readable) {
117*9712c20fSFrederick Mayle     PrintProcessStateMachineReadable(process_state);
118*9712c20fSFrederick Mayle   } else if (options.brief) {
119*9712c20fSFrederick Mayle     PrintRequestingThreadBrief(process_state);
120*9712c20fSFrederick Mayle   } else {
121*9712c20fSFrederick Mayle     PrintProcessState(process_state, options.output_stack_contents,
122*9712c20fSFrederick Mayle                       options.output_requesting_thread_only, &resolver);
123*9712c20fSFrederick Mayle   }
124*9712c20fSFrederick Mayle 
125*9712c20fSFrederick Mayle   return true;
126*9712c20fSFrederick Mayle }
127*9712c20fSFrederick Mayle 
128*9712c20fSFrederick Mayle }  // namespace
129*9712c20fSFrederick Mayle 
Usage(int argc,const char * argv[],bool error)130*9712c20fSFrederick Mayle static void Usage(int argc, const char *argv[], bool error) {
131*9712c20fSFrederick Mayle   fprintf(error ? stderr : stdout,
132*9712c20fSFrederick Mayle           "Usage: %s [options] <minidump-file> [symbol-path ...]\n"
133*9712c20fSFrederick Mayle           "\n"
134*9712c20fSFrederick Mayle           "Output a stack trace for the provided minidump\n"
135*9712c20fSFrederick Mayle           "\n"
136*9712c20fSFrederick Mayle           "Options:\n"
137*9712c20fSFrederick Mayle           "\n"
138*9712c20fSFrederick Mayle           "  -m         Output in machine-readable format\n"
139*9712c20fSFrederick Mayle           "  -s         Output stack contents\n"
140*9712c20fSFrederick Mayle           "  -c         Output thread that causes crash or dump only\n"
141*9712c20fSFrederick Mayle           "  -b         Brief of the thread that causes crash or dump\n",
142*9712c20fSFrederick Mayle           google_breakpad::BaseName(argv[0]).c_str());
143*9712c20fSFrederick Mayle }
144*9712c20fSFrederick Mayle 
SetupOptions(int argc,const char * argv[],Options * options)145*9712c20fSFrederick Mayle static void SetupOptions(int argc, const char *argv[], Options* options) {
146*9712c20fSFrederick Mayle   int ch;
147*9712c20fSFrederick Mayle 
148*9712c20fSFrederick Mayle   options->machine_readable = false;
149*9712c20fSFrederick Mayle   options->output_stack_contents = false;
150*9712c20fSFrederick Mayle   options->output_requesting_thread_only = false;
151*9712c20fSFrederick Mayle   options->brief = false;
152*9712c20fSFrederick Mayle 
153*9712c20fSFrederick Mayle   while ((ch = getopt(argc, (char* const*)argv, "bchms")) != -1) {
154*9712c20fSFrederick Mayle     switch (ch) {
155*9712c20fSFrederick Mayle       case 'h':
156*9712c20fSFrederick Mayle         Usage(argc, argv, false);
157*9712c20fSFrederick Mayle         exit(0);
158*9712c20fSFrederick Mayle         break;
159*9712c20fSFrederick Mayle 
160*9712c20fSFrederick Mayle       case 'b':
161*9712c20fSFrederick Mayle         options->brief = true;
162*9712c20fSFrederick Mayle         break;
163*9712c20fSFrederick Mayle       case 'c':
164*9712c20fSFrederick Mayle         options->output_requesting_thread_only = true;
165*9712c20fSFrederick Mayle         break;
166*9712c20fSFrederick Mayle       case 'm':
167*9712c20fSFrederick Mayle         options->machine_readable = true;
168*9712c20fSFrederick Mayle         break;
169*9712c20fSFrederick Mayle       case 's':
170*9712c20fSFrederick Mayle         options->output_stack_contents = true;
171*9712c20fSFrederick Mayle         break;
172*9712c20fSFrederick Mayle 
173*9712c20fSFrederick Mayle       case '?':
174*9712c20fSFrederick Mayle         Usage(argc, argv, true);
175*9712c20fSFrederick Mayle         exit(1);
176*9712c20fSFrederick Mayle         break;
177*9712c20fSFrederick Mayle     }
178*9712c20fSFrederick Mayle   }
179*9712c20fSFrederick Mayle 
180*9712c20fSFrederick Mayle   if ((argc - optind) == 0) {
181*9712c20fSFrederick Mayle     fprintf(stderr, "%s: Missing minidump file\n", argv[0]);
182*9712c20fSFrederick Mayle     Usage(argc, argv, true);
183*9712c20fSFrederick Mayle     exit(1);
184*9712c20fSFrederick Mayle   }
185*9712c20fSFrederick Mayle 
186*9712c20fSFrederick Mayle   options->minidump_file = argv[optind];
187*9712c20fSFrederick Mayle 
188*9712c20fSFrederick Mayle   for (int argi = optind + 1; argi < argc; ++argi)
189*9712c20fSFrederick Mayle     options->symbol_paths.push_back(argv[argi]);
190*9712c20fSFrederick Mayle }
191*9712c20fSFrederick Mayle 
main(int argc,const char * argv[])192*9712c20fSFrederick Mayle int main(int argc, const char* argv[]) {
193*9712c20fSFrederick Mayle   Options options;
194*9712c20fSFrederick Mayle   SetupOptions(argc, argv, &options);
195*9712c20fSFrederick Mayle 
196*9712c20fSFrederick Mayle   return PrintMinidumpProcess(options) ? 0 : 1;
197*9712c20fSFrederick Mayle }
198