//===-- MachException.h -----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  Created by Greg Clayton on 6/18/07.
//
//===----------------------------------------------------------------------===//

#ifndef __MachException_h__
#define __MachException_h__

#include <mach/mach.h>
#include <vector>

class MachProcess;
class PThreadMutex;

typedef union MachMessageTag {
  mach_msg_header_t hdr;
  char data[1024];
} MachMessage;

class MachException {
public:
  struct PortInfo {
    exception_mask_t mask; // the exception mask for this device which may be a
                           // subset of EXC_MASK_ALL...
    exception_mask_t masks[EXC_TYPES_COUNT];
    mach_port_t ports[EXC_TYPES_COUNT];
    exception_behavior_t behaviors[EXC_TYPES_COUNT];
    thread_state_flavor_t flavors[EXC_TYPES_COUNT];
    mach_msg_type_number_t count;

    kern_return_t Save(task_t task);
    kern_return_t Restore(task_t task);
  };

  struct Data {
    task_t task_port;
    thread_t thread_port;
    exception_type_t exc_type;
    std::vector<mach_exception_data_type_t> exc_data;
    Data()
        : task_port(TASK_NULL), thread_port(THREAD_NULL), exc_type(0),
          exc_data() {}

    void Clear() {
      task_port = TASK_NULL;
      thread_port = THREAD_NULL;
      exc_type = 0;
      exc_data.clear();
    }
    bool IsValid() const {
      return task_port != TASK_NULL && thread_port != THREAD_NULL &&
             exc_type != 0;
    }
    // Return the SoftSignal for this MachException data, or zero if there is
    // none
    int SoftSignal() const {
      if (exc_type == EXC_SOFTWARE && exc_data.size() == 2 &&
          exc_data[0] == EXC_SOFT_SIGNAL)
        return static_cast<int>(exc_data[1]);
      return 0;
    }
    bool IsBreakpoint() const {
      return (exc_type == EXC_BREAKPOINT ||
              ((exc_type == EXC_SOFTWARE) && exc_data[0] == 1));
    }
    void AppendExceptionData(mach_exception_data_t Data,
                             mach_msg_type_number_t Count) {
      mach_exception_data_type_t Buf;
      for (mach_msg_type_number_t i = 0; i < Count; ++i) {
        // Perform an unaligned copy.
        memcpy(&Buf, Data + i, sizeof(mach_exception_data_type_t));
        exc_data.push_back(Buf);
      }
    }
    void Dump() const;
    void DumpStopReason() const;
    bool GetStopInfo(struct DNBThreadStopInfo *stop_info) const;
  };

  struct Message {
    MachMessage exc_msg;
    MachMessage reply_msg;
    Data state;

    Message() : state() {
      memset(&exc_msg, 0, sizeof(exc_msg));
      memset(&reply_msg, 0, sizeof(reply_msg));
    }
    bool CatchExceptionRaise(task_t task);
    void Dump() const;
    kern_return_t Reply(MachProcess *process, int signal);
    kern_return_t Receive(mach_port_t receive_port, mach_msg_option_t options,
                          mach_msg_timeout_t timeout,
                          mach_port_t notify_port = MACH_PORT_NULL);

    typedef std::vector<Message> collection;
    typedef collection::iterator iterator;
    typedef collection::const_iterator const_iterator;
  };

  enum {
    e_actionForward, // Forward signal to inferior process
    e_actionStop,    // Stop when this signal is received
  };
  struct Action {
    task_t task_port;          // Set to TASK_NULL for any TASK
    thread_t thread_port;      // Set to THREAD_NULL for any thread
    exception_type_t exc_mask; // Mach exception mask to watch for
    std::vector<mach_exception_data_type_t> exc_data_mask; // Mask to apply to
                                                           // exception data, or
                                                           // empty to ignore
                                                           // exc_data value for
                                                           // exception
    std::vector<mach_exception_data_type_t> exc_data_value; // Value to compare
                                                            // to exception data
                                                            // after masking, or
                                                            // empty to ignore
                                                            // exc_data value
                                                            // for exception
    uint8_t flags; // Action flags describing what to do with the exception
  };
  static const char *Name(exception_type_t exc_type);
};

#endif
