Home | History | Annotate | Download | only in crash_generation
      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)
     43 enum {
     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.
     54 struct 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
     62 struct 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 
     75 using std::string;
     76 using google_breakpad::MinidumpGenerator;
     77 
     78 namespace google_breakpad {
     79 
     80 //=============================================================================
     81 class 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 //=============================================================================
    112 class 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