13ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Copyright (c) 2007, Google Inc.
23ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// All rights reserved.
33ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
43ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Redistribution and use in source and binary forms, with or without
53ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// modification, are permitted provided that the following conditions are
63ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// met:
73ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
83ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//     * Redistributions of source code must retain the above copyright
93ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// notice, this list of conditions and the following disclaimer.
103ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//     * Redistributions in binary form must reproduce the above
113ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// copyright notice, this list of conditions and the following disclaimer
123ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// in the documentation and/or other materials provided with the
133ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// distribution.
143ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//     * Neither the name of Google Inc. nor the names of its
153ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// contributors may be used to endorse or promote products derived from
163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// this software without specific prior written permission.
173ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
193ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
203ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
213ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
223ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
233ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
243ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
253ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
263ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
273ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
283ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
293ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
303ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Interface file between the Breakpad.framework and
313ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// the Inspector process.
323ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
33303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org#include "common/simple_string_dictionary.h"
343ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
353ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#import <Foundation/Foundation.h>
361e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org#include <mach/mach.h>
371e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org
3800936cf4ad413ec012b81c814319467c206d7447qsr@chromium.org#import "client/mac/crash_generation/ConfigFile.h"
393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#import "client/mac/handler/minidump_generator.h"
403ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
413ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
423ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Types of mach messsages (message IDs)
433ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidenum {
443ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kMsgType_InspectorInitialInfo = 0,    // data is InspectorInfo
453ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kMsgType_InspectorKeyValuePair = 1,   // data is KeyValueMessageData
463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kMsgType_InspectorAcknowledgement = 2 // no data sent
473ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Initial information sent from the crashed process by
503ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Breakpad.framework to the Inspector process
513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// The mach message with this struct as data will also include
523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// several descriptors for sending mach port rights to the crashed
533ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// task, etc.
543ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidstruct InspectorInfo {
553ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  int           exception_type;
563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  int           exception_code;
5761e88c7ad7eb072977b4d4d26bcf8929b75af2d4ted.mielczarek  int           exception_subcode;
583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  unsigned int  parameter_count;  // key-value pairs
593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
603ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
613ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Key/value message data to be sent to the Inspector
623ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidstruct KeyValueMessageData {
633ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
643ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  KeyValueMessageData() {}
65c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  explicit KeyValueMessageData(
66c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      const google_breakpad::SimpleStringDictionary::Entry &inEntry) {
67c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    strlcpy(key, inEntry.key, sizeof(key) );
68c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    strlcpy(value, inEntry.value, sizeof(value) );
693ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
703ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
71c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  char key[google_breakpad::SimpleStringDictionary::key_size];
72c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  char value[google_breakpad::SimpleStringDictionary::value_size];
733ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
743ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
753ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidusing std::string;
763ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidusing google_breakpad::MinidumpGenerator;
773ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
783ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidnamespace google_breakpad {
793ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
803ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//=============================================================================
813ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidclass MinidumpLocation {
823ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
83ba5ee2c8f51c481db23a1ce848368ec69dabac48mark@chromium.org  MinidumpLocation(NSString *minidumpDir) {
843ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    // Ensure that the path exists.  Fallback to /tmp if unable to locate path.
85a3d4c973369987e14cc0c05964e288ea0eac11dcnealsid    assert(minidumpDir);
863ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    if (!EnsureDirectoryPathExists(minidumpDir)) {
873ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid      minidumpDir = @"/tmp";
883ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    }
893ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
903ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    strlcpy(minidump_dir_path_, [minidumpDir fileSystemRepresentation],
913ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid            sizeof(minidump_dir_path_));
923ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
933ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    // now generate a unique ID
943ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    string dump_path(minidump_dir_path_);
953ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    string next_minidump_id;
963ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
973ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    string next_minidump_path_ =
983ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid      (MinidumpGenerator::UniqueNameInDirectory(dump_path, &next_minidump_id));
993ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1003ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    strlcpy(minidump_id_, next_minidump_id.c_str(), sizeof(minidump_id_));
1013ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  };
1023ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1033ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  const char *GetPath() { return minidump_dir_path_; }
1043ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  const char *GetID() { return minidump_id_; }
1053ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1063ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid private:
1073ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  char minidump_dir_path_[PATH_MAX];             // Path to minidump directory
1083ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  char minidump_id_[128];
1093ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
1103ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1113ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//=============================================================================
1123ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidclass Inspector {
1133ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
1143ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  Inspector() {};
1153ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // given a bootstrap service name, receives mach messages
1173ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // from a crashed process, then inspects it, creates a minidump file
1183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // and asks the user if he wants to upload it to a server.
1193ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  void            Inspect(const char *receive_port_name);
1203ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1213ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid private:
1221e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  // The Inspector is invoked with its bootstrap port set to the bootstrap
1231e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  // subset established in OnDemandServer.mm OnDemandServer::Initialize.
1241e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  // For proper communication with the system, the sender (which will inherit
1251e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  // the Inspector's bootstrap port) needs the per-session bootstrap namespace
1261e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  // available directly in its bootstrap port. OnDemandServer stashed this
1271e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  // port into the subset namespace under a special name. ResetBootstrapPort
1281e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  // recovers this port and switches this task to use it as its own bootstrap
1291e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  // (ensuring that children like the sender will inherit it), and saves the
1301e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  // subset in bootstrap_subset_port_ for use by ServiceCheckIn and
1311e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  // ServiceCheckOut.
132405bb7aff734100b8d25adfd93d42d54a778b9a4mark@chromium.org  kern_return_t   ResetBootstrapPort();
1331e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org
1343ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kern_return_t   ServiceCheckIn(const char *receive_port_name);
1353ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kern_return_t   ServiceCheckOut(const char *receive_port_name);
1363ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1373ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kern_return_t   ReadMessages();
1383ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  bool            InspectTask();
1403ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  kern_return_t   SendAcknowledgement();
1413ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1421e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  // The bootstrap port in which the inspector is registered and into which it
1431e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  // must check in.
1441e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org  mach_port_t     bootstrap_subset_port_;
1451e9dbde88a0f7cdcaba556a24fa468627d5c7e84mark@chromium.org
1463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_port_t     service_rcv_port_;
1473ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  int             exception_type_;
1493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  int             exception_code_;
15061e88c7ad7eb072977b4d4d26bcf8929b75af2d4ted.mielczarek  int             exception_subcode_;
1513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_port_t     remote_task_;
1523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_port_t     crashing_thread_;
1533ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_port_t     handler_thread_;
1543ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  mach_port_t     ack_port_;
1553ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  SimpleStringDictionary config_params_;
1573ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  ConfigFile      config_file_;
1593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
1603ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1613ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1623ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid} // namespace google_breakpad
163