1 // Copyright (c) 2006, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 // minidump_dump.cc: Print the contents of a minidump file in somewhat
31 // readable text.
32 //
33 // Author: Mark Mentovai
34
35 #include <stdio.h>
36 #include <string.h>
37
38 #include "common/scoped_ptr.h"
39 #include "google_breakpad/processor/minidump.h"
40 #include "processor/logging.h"
41
42 namespace {
43
44 using google_breakpad::Minidump;
45 using google_breakpad::MinidumpThreadList;
46 using google_breakpad::MinidumpModuleList;
47 using google_breakpad::MinidumpMemoryInfoList;
48 using google_breakpad::MinidumpMemoryList;
49 using google_breakpad::MinidumpException;
50 using google_breakpad::MinidumpAssertion;
51 using google_breakpad::MinidumpSystemInfo;
52 using google_breakpad::MinidumpMiscInfo;
53 using google_breakpad::MinidumpBreakpadInfo;
54
DumpRawStream(Minidump * minidump,uint32_t stream_type,const char * stream_name,int * errors)55 static void DumpRawStream(Minidump *minidump,
56 uint32_t stream_type,
57 const char *stream_name,
58 int *errors) {
59 uint32_t length = 0;
60 if (!minidump->SeekToStreamType(stream_type, &length)) {
61 return;
62 }
63
64 printf("Stream %s:\n", stream_name);
65
66 if (length == 0) {
67 printf("\n");
68 return;
69 }
70 std::vector<char> contents(length);
71 if (!minidump->ReadBytes(&contents[0], length)) {
72 ++*errors;
73 BPLOG(ERROR) << "minidump.ReadBytes failed";
74 return;
75 }
76 size_t current_offset = 0;
77 while (current_offset < length) {
78 size_t remaining = length - current_offset;
79 // Printf requires an int and direct casting from size_t results
80 // in compatibility warnings.
81 uint32_t int_remaining = remaining;
82 printf("%.*s", int_remaining, &contents[current_offset]);
83 char *next_null = reinterpret_cast<char *>(
84 memchr(&contents[current_offset], 0, remaining));
85 if (next_null == NULL)
86 break;
87 printf("\\0\n");
88 size_t null_offset = next_null - &contents[0];
89 current_offset = null_offset + 1;
90 }
91 printf("\n\n");
92 }
93
PrintMinidumpDump(const char * minidump_file)94 static bool PrintMinidumpDump(const char *minidump_file) {
95 Minidump minidump(minidump_file);
96 if (!minidump.Read()) {
97 BPLOG(ERROR) << "minidump.Read() failed";
98 return false;
99 }
100 minidump.Print();
101
102 int errors = 0;
103
104 MinidumpThreadList *thread_list = minidump.GetThreadList();
105 if (!thread_list) {
106 ++errors;
107 BPLOG(ERROR) << "minidump.GetThreadList() failed";
108 } else {
109 thread_list->Print();
110 }
111
112 MinidumpModuleList *module_list = minidump.GetModuleList();
113 if (!module_list) {
114 ++errors;
115 BPLOG(ERROR) << "minidump.GetModuleList() failed";
116 } else {
117 module_list->Print();
118 }
119
120 MinidumpMemoryList *memory_list = minidump.GetMemoryList();
121 if (!memory_list) {
122 ++errors;
123 BPLOG(ERROR) << "minidump.GetMemoryList() failed";
124 } else {
125 memory_list->Print();
126 }
127
128 MinidumpException *exception = minidump.GetException();
129 if (!exception) {
130 BPLOG(INFO) << "minidump.GetException() failed";
131 } else {
132 exception->Print();
133 }
134
135 MinidumpAssertion *assertion = minidump.GetAssertion();
136 if (!assertion) {
137 BPLOG(INFO) << "minidump.GetAssertion() failed";
138 } else {
139 assertion->Print();
140 }
141
142 MinidumpSystemInfo *system_info = minidump.GetSystemInfo();
143 if (!system_info) {
144 ++errors;
145 BPLOG(ERROR) << "minidump.GetSystemInfo() failed";
146 } else {
147 system_info->Print();
148 }
149
150 MinidumpMiscInfo *misc_info = minidump.GetMiscInfo();
151 if (!misc_info) {
152 ++errors;
153 BPLOG(ERROR) << "minidump.GetMiscInfo() failed";
154 } else {
155 misc_info->Print();
156 }
157
158 MinidumpBreakpadInfo *breakpad_info = minidump.GetBreakpadInfo();
159 if (!breakpad_info) {
160 // Breakpad info is optional, so don't treat this as an error.
161 BPLOG(INFO) << "minidump.GetBreakpadInfo() failed";
162 } else {
163 breakpad_info->Print();
164 }
165
166 MinidumpMemoryInfoList *memory_info_list = minidump.GetMemoryInfoList();
167 if (!memory_info_list) {
168 ++errors;
169 BPLOG(ERROR) << "minidump.GetMemoryInfoList() failed";
170 } else {
171 memory_info_list->Print();
172 }
173
174 DumpRawStream(&minidump,
175 MD_LINUX_CMD_LINE,
176 "MD_LINUX_CMD_LINE",
177 &errors);
178 DumpRawStream(&minidump,
179 MD_LINUX_ENVIRON,
180 "MD_LINUX_ENVIRON",
181 &errors);
182 DumpRawStream(&minidump,
183 MD_LINUX_LSB_RELEASE,
184 "MD_LINUX_LSB_RELEASE",
185 &errors);
186 DumpRawStream(&minidump,
187 MD_LINUX_PROC_STATUS,
188 "MD_LINUX_PROC_STATUS",
189 &errors);
190 DumpRawStream(&minidump,
191 MD_LINUX_CPU_INFO,
192 "MD_LINUX_CPU_INFO",
193 &errors);
194 DumpRawStream(&minidump,
195 MD_LINUX_MAPS,
196 "MD_LINUX_MAPS",
197 &errors);
198
199 return errors == 0;
200 }
201
202 } // namespace
203
main(int argc,char ** argv)204 int main(int argc, char **argv) {
205 BPLOG_INIT(&argc, &argv);
206
207 if (argc != 2) {
208 fprintf(stderr, "usage: %s <file>\n", argv[0]);
209 return 1;
210 }
211
212 return PrintMinidumpDump(argv[1]) ? 0 : 1;
213 }
214