1// Copyright (c) 2007, 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// Interface file between the Breakpad.framework and
31// the Inspector process.
32
33#include "common/simple_string_dictionary.h"
34
35#import <Foundation/Foundation.h>
36#include <mach/mach.h>
37
38#import "client/mac/crash_generation/ConfigFile.h"
39#import "client/mac/handler/minidump_generator.h"
40
41
42// Types of mach messsages (message IDs)
43enum {
44  kMsgType_InspectorInitialInfo = 0,    // data is InspectorInfo
45  kMsgType_InspectorKeyValuePair = 1,   // data is KeyValueMessageData
46  kMsgType_InspectorAcknowledgement = 2 // no data sent
47};
48
49// Initial information sent from the crashed process by
50// Breakpad.framework to the Inspector process
51// The mach message with this struct as data will also include
52// several descriptors for sending mach port rights to the crashed
53// task, etc.
54struct InspectorInfo {
55  int           exception_type;
56  int           exception_code;
57  int           exception_subcode;
58  unsigned int  parameter_count;  // key-value pairs
59};
60
61// Key/value message data to be sent to the Inspector
62struct KeyValueMessageData {
63 public:
64  KeyValueMessageData() {}
65  explicit KeyValueMessageData(
66      const google_breakpad::SimpleStringDictionary::Entry &inEntry) {
67    strlcpy(key, inEntry.key, sizeof(key) );
68    strlcpy(value, inEntry.value, sizeof(value) );
69  }
70
71  char key[google_breakpad::SimpleStringDictionary::key_size];
72  char value[google_breakpad::SimpleStringDictionary::value_size];
73};
74
75using std::string;
76using google_breakpad::MinidumpGenerator;
77
78namespace google_breakpad {
79
80//=============================================================================
81class MinidumpLocation {
82 public:
83  MinidumpLocation(NSString *minidumpDir) {
84    // Ensure that the path exists.  Fallback to /tmp if unable to locate path.
85    assert(minidumpDir);
86    if (!EnsureDirectoryPathExists(minidumpDir)) {
87      minidumpDir = @"/tmp";
88    }
89
90    strlcpy(minidump_dir_path_, [minidumpDir fileSystemRepresentation],
91            sizeof(minidump_dir_path_));
92
93    // now generate a unique ID
94    string dump_path(minidump_dir_path_);
95    string next_minidump_id;
96
97    string next_minidump_path_ =
98      (MinidumpGenerator::UniqueNameInDirectory(dump_path, &next_minidump_id));
99
100    strlcpy(minidump_id_, next_minidump_id.c_str(), sizeof(minidump_id_));
101  };
102
103  const char *GetPath() { return minidump_dir_path_; }
104  const char *GetID() { return minidump_id_; }
105
106 private:
107  char minidump_dir_path_[PATH_MAX];             // Path to minidump directory
108  char minidump_id_[128];
109};
110
111//=============================================================================
112class Inspector {
113 public:
114  Inspector() {};
115
116  // given a bootstrap service name, receives mach messages
117  // from a crashed process, then inspects it, creates a minidump file
118  // and asks the user if he wants to upload it to a server.
119  void            Inspect(const char *receive_port_name);
120
121 private:
122  // The Inspector is invoked with its bootstrap port set to the bootstrap
123  // subset established in OnDemandServer.mm OnDemandServer::Initialize.
124  // For proper communication with the system, the sender (which will inherit
125  // the Inspector's bootstrap port) needs the per-session bootstrap namespace
126  // available directly in its bootstrap port. OnDemandServer stashed this
127  // port into the subset namespace under a special name. ResetBootstrapPort
128  // recovers this port and switches this task to use it as its own bootstrap
129  // (ensuring that children like the sender will inherit it), and saves the
130  // subset in bootstrap_subset_port_ for use by ServiceCheckIn and
131  // ServiceCheckOut.
132  kern_return_t   ResetBootstrapPort();
133
134  kern_return_t   ServiceCheckIn(const char *receive_port_name);
135  kern_return_t   ServiceCheckOut(const char *receive_port_name);
136
137  kern_return_t   ReadMessages();
138
139  bool            InspectTask();
140  kern_return_t   SendAcknowledgement();
141
142  // The bootstrap port in which the inspector is registered and into which it
143  // must check in.
144  mach_port_t     bootstrap_subset_port_;
145
146  mach_port_t     service_rcv_port_;
147
148  int             exception_type_;
149  int             exception_code_;
150  int             exception_subcode_;
151  mach_port_t     remote_task_;
152  mach_port_t     crashing_thread_;
153  mach_port_t     handler_thread_;
154  mach_port_t     ack_port_;
155
156  SimpleStringDictionary config_params_;
157
158  ConfigFile      config_file_;
159};
160
161
162} // namespace google_breakpad
163