minidump_generator.h revision 4621ee06914b2ebe963c93ea78fabf982cf670df
15ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// Copyright (c) 2006, Google Inc.
25ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// All rights reserved.
35ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis//
45ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// Redistribution and use in source and binary forms, with or without
55ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// modification, are permitted provided that the following conditions are
65ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// met:
75ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis//
85ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis//     * Redistributions of source code must retain the above copyright
95ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// notice, this list of conditions and the following disclaimer.
105ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis//     * Redistributions in binary form must reproduce the above
115ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// copyright notice, this list of conditions and the following disclaimer
125ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// in the documentation and/or other materials provided with the
135ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// distribution.
145ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis//     * Neither the name of Google Inc. nor the names of its
155ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// contributors may be used to endorse or promote products derived from
165ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// this software without specific prior written permission.
175ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis//
185ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
305ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// minidump_generator.h:  Create a minidump of the current MacOS process.
315ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
325ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis#ifndef CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
335ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis#define CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
345ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
355ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis#include <mach/mach.h>
365ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
375ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis#include <string>
385ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
395ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis#include "client/minidump_file_writer.h"
404621ee06914b2ebe963c93ea78fabf982cf670dfted.mielczarek#include "common/memory.h"
419be806efde6c55fbd7e9443d2700255835019a03ted.mielczarek#include "common/mac/macho_utilities.h"
424621ee06914b2ebe963c93ea78fabf982cf670dfted.mielczarek#include "google_breakpad/common/minidump_format.h"
435ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
44de2fd15db9a480c807ba337690669538a97756a4ladderbreaker#include "dynamic_images.h"
45de2fd15db9a480c807ba337690669538a97756a4ladderbreaker
46e5dc60822e5938fea2ae892ccddb906641ba174emmentovainamespace google_breakpad {
475ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
485ac2b9a569890f165478f91670dcdd553ce2d10ewaylonisusing std::string;
495ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
50867df1c65264c657ed71d68c3d266401686edcadnealsid#if TARGET_CPU_X86_64 || TARGET_CPU_PPC64
51867df1c65264c657ed71d68c3d266401686edcadnealsid#define TOP_OF_THREAD0_STACK 0x00007fff5fbff000
52867df1c65264c657ed71d68c3d266401686edcadnealsid#else
53867df1c65264c657ed71d68c3d266401686edcadnealsid#define TOP_OF_THREAD0_STACK 0xbffff000
54867df1c65264c657ed71d68c3d266401686edcadnealsid#endif
55867df1c65264c657ed71d68c3d266401686edcadnealsid
56867df1c65264c657ed71d68c3d266401686edcadnealsid#if TARGET_CPU_X86_64
57867df1c65264c657ed71d68c3d266401686edcadnealsidtypedef x86_thread_state64_t breakpad_thread_state_t;
58867df1c65264c657ed71d68c3d266401686edcadnealsidtypedef MDRawContextAMD64 MinidumpContext;
59867df1c65264c657ed71d68c3d266401686edcadnealsid#elif TARGET_CPU_X86
60867df1c65264c657ed71d68c3d266401686edcadnealsidtypedef  i386_thread_state_t breakpad_thread_state_t;
61867df1c65264c657ed71d68c3d266401686edcadnealsidtypedef MDRawContextX86 MinidumpContext;
62867df1c65264c657ed71d68c3d266401686edcadnealsid#elif TARGET_CPU_PPC64
63867df1c65264c657ed71d68c3d266401686edcadnealsidtypedef ppc_thread_state64_t breakpad_thread_state_t;
64867df1c65264c657ed71d68c3d266401686edcadnealsidtypedef MDRawContextPPC64 MinidumpContext;
65867df1c65264c657ed71d68c3d266401686edcadnealsid#elif TARGET_CPU_PPC
66867df1c65264c657ed71d68c3d266401686edcadnealsidtypedef ppc_thread_state_t breakpad_thread_state_t;
67867df1c65264c657ed71d68c3d266401686edcadnealsidtypedef MDRawContextPPC MinidumpContext;
68867df1c65264c657ed71d68c3d266401686edcadnealsid#endif
69867df1c65264c657ed71d68c3d266401686edcadnealsid
70a0a0de39a8b25bea9ae18d98c4eb4c052c1a9864nealsid// Use the REGISTER_FROM_THREADSTATE to access a register name from the
71a0a0de39a8b25bea9ae18d98c4eb4c052c1a9864nealsid// breakpad_thread_state_t structure.
72b73230385c3d0d256a704ead20396714db43d7bbted.mielczarek#if __DARWIN_UNIX03 || TARGET_CPU_X86_64 || TARGET_CPU_PPC64
73a0a0de39a8b25bea9ae18d98c4eb4c052c1a9864nealsid// In The 10.5 SDK Headers Apple prepended __ to the variable names in the
74a0a0de39a8b25bea9ae18d98c4eb4c052c1a9864nealsid// i386_thread_state_t structure.  There's no good way to tell what version of
75a0a0de39a8b25bea9ae18d98c4eb4c052c1a9864nealsid// the SDK we're compiling against so we just toggle on the same preprocessor
76a0a0de39a8b25bea9ae18d98c4eb4c052c1a9864nealsid// symbol Apple's headers use.
77a0a0de39a8b25bea9ae18d98c4eb4c052c1a9864nealsid#define REGISTER_FROM_THREADSTATE(a, b) ((a)->__ ## b)
78a0a0de39a8b25bea9ae18d98c4eb4c052c1a9864nealsid#else
79a0a0de39a8b25bea9ae18d98c4eb4c052c1a9864nealsid#define REGISTER_FROM_THREADSTATE(a, b) (a->b)
80a0a0de39a8b25bea9ae18d98c4eb4c052c1a9864nealsid#endif
81a0a0de39a8b25bea9ae18d98c4eb4c052c1a9864nealsid
825ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// Creates a minidump file of the current process.  If there is exception data,
835ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// use SetExceptionInformation() to add this to the minidump.  The minidump
845ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// file is generated by the Write() function.
855ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// Usage:
865ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// MinidumpGenerator minidump();
875ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis// minidump.Write("/tmp/minidump");
885ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis//
895ac2b9a569890f165478f91670dcdd553ce2d10ewaylonisclass MinidumpGenerator {
905ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis public:
915ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  MinidumpGenerator();
92de2fd15db9a480c807ba337690669538a97756a4ladderbreaker  MinidumpGenerator(mach_port_t crashing_task, mach_port_t handler_thread);
93de2fd15db9a480c807ba337690669538a97756a4ladderbreaker
945ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  ~MinidumpGenerator();
955ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
965ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // Return <dir>/<unique_name>.dmp
975ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // Sets |unique_name| (if requested) to the unique name for the minidump
985ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  static string UniqueNameInDirectory(const string &dir, string *unique_name);
995ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
1005ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // Write out the minidump into |path|
1015ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // All of the components of |path| must exist and be writable
1025ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // Return true if successful, false otherwise
1035ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  bool Write(const char *path);
1045ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
1055ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // Specify some exception information, if applicable
10661e88c7ad7eb072977b4d4d26bcf8929b75af2d4ted.mielczarek  void SetExceptionInformation(int type, int code, int subcode,
10761e88c7ad7eb072977b4d4d26bcf8929b75af2d4ted.mielczarek                               mach_port_t thread_name) {
1085ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis    exception_type_ = type;
1095ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis    exception_code_ = code;
11061e88c7ad7eb072977b4d4d26bcf8929b75af2d4ted.mielczarek    exception_subcode_ = subcode;
1115ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis    exception_thread_ = thread_name;
1125ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  }
1135ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
1145ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // Gather system information.  This should be call at least once before using
1155ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // the MinidumpGenerator class.
1165ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  static void GatherSystemInformation();
1175ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
1185ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis private:
1195ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis    typedef bool (MinidumpGenerator::*WriteStreamFN)(MDRawDirectory *);
1205ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
1215ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // Stream writers
1225ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  bool WriteThreadListStream(MDRawDirectory *thread_list_stream);
1234621ee06914b2ebe963c93ea78fabf982cf670dfted.mielczarek  bool WriteMemoryListStream(MDRawDirectory *memory_list_stream);
1245ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  bool WriteExceptionStream(MDRawDirectory *exception_stream);
1255ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  bool WriteSystemInfoStream(MDRawDirectory *system_info_stream);
1265ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  bool WriteModuleListStream(MDRawDirectory *module_list_stream);
1275ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  bool WriteMiscInfoStream(MDRawDirectory *misc_info_stream);
128e5dc60822e5938fea2ae892ccddb906641ba174emmentovai  bool WriteBreakpadInfoStream(MDRawDirectory *breakpad_info_stream);
1295ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
1305ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // Helpers
131255bbe93ed7aef5418000339b6cdb5677bf9e4d6ted.mielczarek  u_int64_t CurrentPCForStack(breakpad_thread_state_data_t state);
132867df1c65264c657ed71d68c3d266401686edcadnealsid  bool WriteStackFromStartAddress(mach_vm_address_t start_addr,
1335ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis                                  MDMemoryDescriptor *stack_location);
134255bbe93ed7aef5418000339b6cdb5677bf9e4d6ted.mielczarek  bool WriteStack(breakpad_thread_state_data_t state,
1355ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis                  MDMemoryDescriptor *stack_location);
136255bbe93ed7aef5418000339b6cdb5677bf9e4d6ted.mielczarek  bool WriteContext(breakpad_thread_state_data_t state,
1375ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis                    MDLocationDescriptor *register_location);
1385ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  bool WriteThreadStream(mach_port_t thread_id, MDRawThread *thread);
139d31c8b02925a1b20c09ee9ab771322353aea6267waylonis  bool WriteCVRecord(MDRawModule *module, int cpu_type,
140d31c8b02925a1b20c09ee9ab771322353aea6267waylonis                     const char *module_path);
1415ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  bool WriteModuleStream(unsigned int index, MDRawModule *module);
142867df1c65264c657ed71d68c3d266401686edcadnealsid
143867df1c65264c657ed71d68c3d266401686edcadnealsid  size_t CalculateStackSize(mach_vm_address_t start_addr);
144867df1c65264c657ed71d68c3d266401686edcadnealsid
145de2fd15db9a480c807ba337690669538a97756a4ladderbreaker  int  FindExecutableModule();
1465ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
1475ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // disallow copy ctor and operator=
1485ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  explicit MinidumpGenerator(const MinidumpGenerator &);
1495ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  void operator=(const MinidumpGenerator &);
1505ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
1515ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // Use this writer to put the data to disk
1525ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  MinidumpFileWriter writer_;
1535ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
1545ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // Exception information
1555ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  int exception_type_;
1565ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  int exception_code_;
15761e88c7ad7eb072977b4d4d26bcf8929b75af2d4ted.mielczarek  int exception_subcode_;
1585ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  mach_port_t exception_thread_;
159de2fd15db9a480c807ba337690669538a97756a4ladderbreaker  mach_port_t crashing_task_;
160de2fd15db9a480c807ba337690669538a97756a4ladderbreaker  mach_port_t handler_thread_;
161de2fd15db9a480c807ba337690669538a97756a4ladderbreaker
1625ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  // System information
1635ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  static char build_string_[16];
1645ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  static int os_major_version_;
1655ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  static int os_minor_version_;
1665ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis  static int os_build_number_;
167de2fd15db9a480c807ba337690669538a97756a4ladderbreaker
168de2fd15db9a480c807ba337690669538a97756a4ladderbreaker  // Information about dynamically loaded code
169de2fd15db9a480c807ba337690669538a97756a4ladderbreaker  DynamicImages *dynamic_images_;
1704621ee06914b2ebe963c93ea78fabf982cf670dfted.mielczarek
1714621ee06914b2ebe963c93ea78fabf982cf670dfted.mielczarek  // PageAllocator makes it possible to allocate memory
1724621ee06914b2ebe963c93ea78fabf982cf670dfted.mielczarek  // directly from the system, even while handling an exception.
1734621ee06914b2ebe963c93ea78fabf982cf670dfted.mielczarek  mutable PageAllocator allocator_;
1744621ee06914b2ebe963c93ea78fabf982cf670dfted.mielczarek
1754621ee06914b2ebe963c93ea78fabf982cf670dfted.mielczarek  // Blocks of memory written to the dump. These are all currently
1764621ee06914b2ebe963c93ea78fabf982cf670dfted.mielczarek  // written while writing the thread list stream, but saved here
1774621ee06914b2ebe963c93ea78fabf982cf670dfted.mielczarek  // so a memory list stream can be written afterwards.
1784621ee06914b2ebe963c93ea78fabf982cf670dfted.mielczarek  wasteful_vector<MDMemoryDescriptor> memory_blocks_;
1795ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis};
1805ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
181e5dc60822e5938fea2ae892ccddb906641ba174emmentovai}  // namespace google_breakpad
1825ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis
1835ac2b9a569890f165478f91670dcdd553ce2d10ewaylonis#endif  // CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
184