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 42namespace { 43 44using google_breakpad::Minidump; 45using google_breakpad::MinidumpThreadList; 46using google_breakpad::MinidumpModuleList; 47using google_breakpad::MinidumpMemoryInfoList; 48using google_breakpad::MinidumpMemoryList; 49using google_breakpad::MinidumpException; 50using google_breakpad::MinidumpAssertion; 51using google_breakpad::MinidumpSystemInfo; 52using google_breakpad::MinidumpMiscInfo; 53using google_breakpad::MinidumpBreakpadInfo; 54 55static 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 94static 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 204int 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