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_generator.h:  Create a minidump of the current MacOS process.
31 
32 #ifndef CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
33 #define CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
34 
35 #include <mach/mach.h>
36 
37 #include <string>
38 
39 #include "client/minidump_file_writer.h"
40 #include "google_breakpad/common/minidump_format.h"
41 #include "common/mac/macho_utilities.h"
42 
43 #include "dynamic_images.h"
44 
45 namespace google_breakpad {
46 
47 using std::string;
48 
49 #if TARGET_CPU_X86_64 || TARGET_CPU_PPC64
50 #define TOP_OF_THREAD0_STACK 0x00007fff5fbff000
51 #else
52 #define TOP_OF_THREAD0_STACK 0xbffff000
53 #endif
54 
55 #if TARGET_CPU_X86_64
56 typedef x86_thread_state64_t breakpad_thread_state_t;
57 typedef MDRawContextAMD64 MinidumpContext;
58 #elif TARGET_CPU_X86
59 typedef  i386_thread_state_t breakpad_thread_state_t;
60 typedef MDRawContextX86 MinidumpContext;
61 #elif TARGET_CPU_PPC64
62 typedef ppc_thread_state64_t breakpad_thread_state_t;
63 typedef MDRawContextPPC64 MinidumpContext;
64 #elif TARGET_CPU_PPC
65 typedef ppc_thread_state_t breakpad_thread_state_t;
66 typedef MDRawContextPPC MinidumpContext;
67 #endif
68 
69 // Use the REGISTER_FROM_THREADSTATE to access a register name from the
70 // breakpad_thread_state_t structure.
71 #if __DARWIN_UNIX03 || TARGET_CPU_X86_64 || TARGET_CPU_PPC64
72 // In The 10.5 SDK Headers Apple prepended __ to the variable names in the
73 // i386_thread_state_t structure.  There's no good way to tell what version of
74 // the SDK we're compiling against so we just toggle on the same preprocessor
75 // symbol Apple's headers use.
76 #define REGISTER_FROM_THREADSTATE(a, b) ((a)->__ ## b)
77 #else
78 #define REGISTER_FROM_THREADSTATE(a, b) (a->b)
79 #endif
80 
81 // Creates a minidump file of the current process.  If there is exception data,
82 // use SetExceptionInformation() to add this to the minidump.  The minidump
83 // file is generated by the Write() function.
84 // Usage:
85 // MinidumpGenerator minidump();
86 // minidump.Write("/tmp/minidump");
87 //
88 class MinidumpGenerator {
89  public:
90   MinidumpGenerator();
91   MinidumpGenerator(mach_port_t crashing_task, mach_port_t handler_thread);
92 
93   ~MinidumpGenerator();
94 
95   // Return <dir>/<unique_name>.dmp
96   // Sets |unique_name| (if requested) to the unique name for the minidump
97   static string UniqueNameInDirectory(const string &dir, string *unique_name);
98 
99   // Write out the minidump into |path|
100   // All of the components of |path| must exist and be writable
101   // Return true if successful, false otherwise
102   bool Write(const char *path);
103 
104   // Specify some exception information, if applicable
SetExceptionInformation(int type,int code,int subcode,mach_port_t thread_name)105   void SetExceptionInformation(int type, int code, int subcode,
106                                mach_port_t thread_name) {
107     exception_type_ = type;
108     exception_code_ = code;
109     exception_subcode_ = subcode;
110     exception_thread_ = thread_name;
111   }
112 
113   // Gather system information.  This should be call at least once before using
114   // the MinidumpGenerator class.
115   static void GatherSystemInformation();
116 
117  private:
118     typedef bool (MinidumpGenerator::*WriteStreamFN)(MDRawDirectory *);
119 
120   // Stream writers
121   bool WriteThreadListStream(MDRawDirectory *thread_list_stream);
122   bool WriteExceptionStream(MDRawDirectory *exception_stream);
123   bool WriteSystemInfoStream(MDRawDirectory *system_info_stream);
124   bool WriteModuleListStream(MDRawDirectory *module_list_stream);
125   bool WriteMiscInfoStream(MDRawDirectory *misc_info_stream);
126   bool WriteBreakpadInfoStream(MDRawDirectory *breakpad_info_stream);
127 
128   // Helpers
129   u_int64_t CurrentPCForStack(breakpad_thread_state_data_t state);
130   bool WriteStackFromStartAddress(mach_vm_address_t start_addr,
131                                   MDMemoryDescriptor *stack_location);
132   bool WriteStack(breakpad_thread_state_data_t state,
133                   MDMemoryDescriptor *stack_location);
134   bool WriteContext(breakpad_thread_state_data_t state,
135                     MDLocationDescriptor *register_location);
136   bool WriteThreadStream(mach_port_t thread_id, MDRawThread *thread);
137   bool WriteCVRecord(MDRawModule *module, int cpu_type,
138                      const char *module_path);
139   bool WriteModuleStream(unsigned int index, MDRawModule *module);
140 
141   size_t CalculateStackSize(mach_vm_address_t start_addr);
142 
143   int  FindExecutableModule();
144 
145   // disallow copy ctor and operator=
146   explicit MinidumpGenerator(const MinidumpGenerator &);
147   void operator=(const MinidumpGenerator &);
148 
149   // Use this writer to put the data to disk
150   MinidumpFileWriter writer_;
151 
152   // Exception information
153   int exception_type_;
154   int exception_code_;
155   int exception_subcode_;
156   mach_port_t exception_thread_;
157   mach_port_t crashing_task_;
158   mach_port_t handler_thread_;
159 
160   // System information
161   static char build_string_[16];
162   static int os_major_version_;
163   static int os_minor_version_;
164   static int os_build_number_;
165 
166   // Information about dynamically loaded code
167   DynamicImages *dynamic_images_;
168 };
169 
170 }  // namespace google_breakpad
171 
172 #endif  // CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
173