(Mostly) working on OS X

This commit is contained in:
Derek Parker 2015-01-13 20:37:10 -06:00
parent 533a534560
commit 2d2d70641e
32 changed files with 5338 additions and 655 deletions

@ -2,6 +2,7 @@ package main
import (
"fmt"
"runtime"
"time"
)
@ -19,3 +20,7 @@ func main() {
helloworld()
}
}
func init() {
runtime.LockOSThread()
}

@ -1,6 +1,9 @@
package frame
import "fmt"
import (
"fmt"
"sort"
)
// Represents a Common Information Entry in
// the Dwarf .debug_frame section.
@ -55,29 +58,22 @@ func NewFrameIndex() FrameDescriptionEntries {
}
func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) {
frame := find(fdes, pc)
if frame == nil {
return nil, fmt.Errorf("could not find FDE for %#v", pc)
}
return frame, nil
}
fmt.Println("fdes for pc")
idx := sort.Search(len(fdes), func(i int) bool {
if fdes[i].Cover(pc) {
return true
}
if fdes[i].More(pc) {
return false
}
return true
func find(fdes FrameDescriptionEntries, pc uint64) *FrameDescriptionEntry {
if len(fdes) == 0 {
return nil
})
if idx == len(fdes) {
return nil, fmt.Errorf("could not find FDE for PC %#v", pc)
}
idx := len(fdes) / 2
frame := fdes[idx]
if frame.Cover(pc) {
return frame
}
if frame.Less(pc) {
return find(fdes[:idx], pc)
}
if frame.More(pc) {
return find(fdes[idx:], pc)
}
return nil
fmt.Println("fin")
return fdes[idx], nil
}
func (frame *FrameDescriptionEntry) Less(pc uint64) bool {

@ -20,7 +20,7 @@ func TestFDEForPC(t *testing.T) {
node, err := frames.FDEForPC(35)
if err != nil {
t.Fatal("Could not find FDE")
t.Fatal(err)
}
if node != fde1 {

132
proctl/breakpoints.go Normal file

@ -0,0 +1,132 @@
package proctl
import (
"fmt"
"runtime"
)
// Represents a single breakpoint. Stores information on the break
// point including the byte of data that originally was stored at that
// address.
type BreakPoint struct {
FunctionName string
File string
Line int
Addr uint64
OriginalData []byte
ID int
temp bool
}
// Returned when trying to set a breakpoint at
// an address that already has a breakpoint set for it.
type BreakPointExistsError struct {
file string
line int
addr uint64
}
func (bpe BreakPointExistsError) Error() string {
return fmt.Sprintf("Breakpoint exists at %s:%d at %x", bpe.file, bpe.line, bpe.addr)
}
// InvalidAddressError represents the result of
// attempting to set a breakpoint at an invalid address.
type InvalidAddressError struct {
address uint64
}
func (iae InvalidAddressError) Error() string {
return fmt.Sprintf("Invalid address %#v\n", iae.address)
}
// Returns whether or not a breakpoint has been set for the given address.
func (dbp *DebuggedProcess) BreakpointExists(addr uint64) bool {
for _, bp := range dbp.HWBreakPoints {
// TODO(darwin)
if runtime.GOOS == "darwin" {
break
}
if bp != nil && bp.Addr == addr {
return true
}
}
if _, ok := dbp.BreakPoints[addr]; ok {
return true
}
return false
}
func (dbp *DebuggedProcess) newBreakpoint(fn, f string, l int, addr uint64, data []byte) *BreakPoint {
dbp.breakpointIDCounter++
return &BreakPoint{
FunctionName: fn,
File: f,
Line: l,
Addr: addr,
OriginalData: data,
ID: dbp.breakpointIDCounter,
}
}
func (dbp *DebuggedProcess) setBreakpoint(tid int, addr uint64) (*BreakPoint, error) {
var f, l, fn = dbp.GoSymTable.PCToLine(uint64(addr))
if fn == nil {
return nil, InvalidAddressError{address: addr}
}
if dbp.BreakpointExists(addr) {
return nil, BreakPointExistsError{f, l, addr}
}
// Try and set a hardware breakpoint.
for i, v := range dbp.HWBreakPoints {
// TODO(darwin)
if runtime.GOOS == "darwin" {
break
}
if v == nil {
if err := setHardwareBreakpoint(i, tid, addr); err != nil {
return nil, fmt.Errorf("could not set hardware breakpoint: %v", err)
}
dbp.HWBreakPoints[i] = dbp.newBreakpoint(fn.Name, f, l, addr, nil)
return dbp.HWBreakPoints[i], nil
}
}
// Fall back to software breakpoint. 0xCC is INT 3, software
// breakpoint trap interrupt.
thread := dbp.Threads[tid]
originalData := make([]byte, 1)
if _, err := readMemory(thread, uintptr(addr), originalData); err != nil {
return nil, err
}
if _, err := writeMemory(thread, uintptr(addr), []byte{0xCC}); err != nil {
return nil, err
}
dbp.BreakPoints[addr] = dbp.newBreakpoint(fn.Name, f, l, addr, originalData)
return dbp.BreakPoints[addr], nil
}
func (dbp *DebuggedProcess) clearBreakpoint(tid int, addr uint64) (*BreakPoint, error) {
// Check for hardware breakpoint
for i, bp := range dbp.HWBreakPoints {
if bp == nil {
continue
}
if bp.Addr == addr {
dbp.HWBreakPoints[i] = nil
if err := clearHardwareBreakpoint(i, tid); err != nil {
return nil, err
}
return bp, nil
}
}
// Check for software breakpoint
if bp, ok := dbp.BreakPoints[addr]; ok {
thread := dbp.Threads[tid]
if _, err := writeMemory(thread, uintptr(bp.Addr), bp.OriginalData); err != nil {
return nil, fmt.Errorf("could not clear breakpoint %s", err)
}
delete(dbp.BreakPoints, addr)
return bp, nil
}
return nil, fmt.Errorf("No breakpoint currently set for %#v", addr)
}

@ -0,0 +1,13 @@
package proctl
import "fmt"
// TODO(darwin)
func setHardwareBreakpoint(reg, tid int, addr uint64) error {
return fmt.Errorf("not implemented on darwin")
}
// TODO(darwin)
func clearHardwareBreakpoint(reg, tid int) error {
return fmt.Errorf("not implemented on darwin")
}

@ -15,147 +15,7 @@ int offset(int reg) {
*/
import "C"
import (
"fmt"
"syscall"
"unsafe"
sys "golang.org/x/sys/unix"
)
// Represents a single breakpoint. Stores information on the break
// point including the byte of data that originally was stored at that
// address.
type BreakPoint struct {
FunctionName string
File string
Line int
Addr uint64
OriginalData []byte
ID int
temp bool
}
// Returned when trying to set a breakpoint at
// an address that already has a breakpoint set for it.
type BreakPointExistsError struct {
file string
line int
addr uint64
}
func (bpe BreakPointExistsError) Error() string {
return fmt.Sprintf("Breakpoint exists at %s:%d at %x", bpe.file, bpe.line, bpe.addr)
}
// InvalidAddressError represents the result of
// attempting to set a breakpoint at an invalid address.
type InvalidAddressError struct {
address uint64
}
func (iae InvalidAddressError) Error() string {
return fmt.Sprintf("Invalid address %#v\n", iae.address)
}
func PtracePokeUser(tid int, off, addr uintptr) error {
_, _, err := sys.Syscall6(sys.SYS_PTRACE, sys.PTRACE_POKEUSR, uintptr(tid), uintptr(off), uintptr(addr), 0, 0)
if err != syscall.Errno(0) {
return err
}
return nil
}
func PtracePeekUser(tid int, off uintptr) (uintptr, error) {
var val uintptr
_, _, err := syscall.Syscall6(syscall.SYS_PTRACE, syscall.PTRACE_PEEKUSR, uintptr(tid), uintptr(off), uintptr(unsafe.Pointer(&val)), 0, 0)
if err != syscall.Errno(0) {
return 0, err
}
return val, nil
}
// Returns whether or not a breakpoint has been set for the given address.
func (dbp *DebuggedProcess) BreakpointExists(addr uint64) bool {
for _, bp := range dbp.HWBreakPoints {
if bp != nil && bp.Addr == addr {
return true
}
}
if _, ok := dbp.BreakPoints[addr]; ok {
return true
}
return false
}
func (dbp *DebuggedProcess) setBreakpoint(tid int, addr uint64) (*BreakPoint, error) {
var f, l, fn = dbp.GoSymTable.PCToLine(uint64(addr))
if fn == nil {
return nil, InvalidAddressError{address: addr}
}
if dbp.BreakpointExists(addr) {
return nil, BreakPointExistsError{f, l, addr}
}
// Try and set a hardware breakpoint.
for i, v := range dbp.HWBreakPoints {
if v == nil {
if err := setHardwareBreakpoint(i, tid, addr); err != nil {
return nil, fmt.Errorf("could not set hardware breakpoint: %v", err)
}
dbp.HWBreakPoints[i] = dbp.newBreakpoint(fn.Name, f, l, addr, nil)
return dbp.HWBreakPoints[i], nil
}
}
// Fall back to software breakpoint. 0xCC is INT 3, software
// breakpoint trap interrupt.
originalData := make([]byte, 1)
if _, err := readMemory(tid, uintptr(addr), originalData); err != nil {
return nil, err
}
_, err := writeMemory(tid, uintptr(addr), []byte{0xCC})
if err != nil {
return nil, err
}
dbp.BreakPoints[addr] = dbp.newBreakpoint(fn.Name, f, l, addr, originalData)
return dbp.BreakPoints[addr], nil
}
func (dbp *DebuggedProcess) clearBreakpoint(tid int, addr uint64) (*BreakPoint, error) {
// Check for hardware breakpoint
for i, bp := range dbp.HWBreakPoints {
if bp == nil {
continue
}
if bp.Addr == addr {
dbp.HWBreakPoints[i] = nil
if err := clearHardwareBreakpoint(i, tid); err != nil {
return nil, err
}
return bp, nil
}
}
// Check for software breakpoint
if bp, ok := dbp.BreakPoints[addr]; ok {
if _, err := writeMemory(tid, uintptr(bp.Addr), bp.OriginalData); err != nil {
return nil, fmt.Errorf("could not clear breakpoint %s", err)
}
delete(dbp.BreakPoints, addr)
return bp, nil
}
return nil, fmt.Errorf("No breakpoint currently set for %#v", addr)
}
func (dbp *DebuggedProcess) newBreakpoint(fn, f string, l int, addr uint64, data []byte) *BreakPoint {
dbp.breakpointIDCounter++
return &BreakPoint{
FunctionName: fn,
File: f,
Line: l,
Addr: addr,
OriginalData: data,
ID: dbp.breakpointIDCounter,
}
}
import "fmt"
// Sets a hardware breakpoint by setting the contents of the
// debug register `reg` with the address of the instruction
@ -208,3 +68,10 @@ func setHardwareBreakpoint(reg, tid int, addr uint64) error {
// an instruction stored in dr0-dr3.
return PtracePokeUser(tid, dr7off, dr7)
}
// Clears a hardware breakpoint. Essentially sets
// the debug reg to 0 and clears the control register
// flags for that reg.
func clearHardwareBreakpoint(reg, tid int) error {
return setHardwareBreakpoint(reg, tid, 0)
}

119
proctl/exc.defs Normal file

@ -0,0 +1,119 @@
/*
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
/*
* Abstract:
* MiG definitions file for Mach exception interface.
*/
subsystem
#if KERNEL_USER
KernelUser
#endif
exc 2401;
#include <mach/std_types.defs>
#include <mach/mach_types.defs>
ServerPrefix catch_;
type exception_data_t = array[*:2] of integer_t;
type exception_type_t = int;
routine exception_raise(
#if KERNEL_USER
exception_port : mach_port_move_send_t;
thread : mach_port_move_send_t;
task : mach_port_move_send_t;
#else /* KERNEL_USER */
exception_port : mach_port_t;
thread : mach_port_t;
task : mach_port_t;
#endif /* KERNEL_USER */
exception : exception_type_t;
code : exception_data_t
);
routine exception_raise_state(
#if KERNEL_USER
exception_port : mach_port_move_send_t;
#else /* KERNEL_USER */
exception_port : mach_port_t;
#endif /* KERNEL_USER */
exception : exception_type_t;
code : exception_data_t, const;
inout flavor : int;
old_state : thread_state_t, const;
out new_state : thread_state_t);
routine exception_raise_state_identity(
#if KERNEL_USER
exception_port : mach_port_move_send_t;
thread : mach_port_move_send_t;
task : mach_port_move_send_t;
#else /* KERNEL_USER */
exception_port : mach_port_t;
thread : mach_port_t;
task : mach_port_t;
#endif /* KERNEL_USER */
exception : exception_type_t;
code : exception_data_t;
inout flavor : int;
old_state : thread_state_t;
out new_state : thread_state_t);
/* vim: set ft=c : */

283
proctl/exc.h Normal file

@ -0,0 +1,283 @@
#ifndef _exc_user_
#define _exc_user_
/* Module exc */
#include <string.h>
#include <mach/ndr.h>
#include <mach/boolean.h>
#include <mach/kern_return.h>
#include <mach/notify.h>
#include <mach/mach_types.h>
#include <mach/message.h>
#include <mach/mig_errors.h>
#include <mach/port.h>
/* BEGIN VOUCHER CODE */
#ifndef KERNEL
#if defined(__has_include)
#if __has_include(<mach/mig_voucher_support.h>)
#ifndef USING_VOUCHERS
#define USING_VOUCHERS
#endif
#ifndef __VOUCHER_FORWARD_TYPE_DECLS__
#define __VOUCHER_FORWARD_TYPE_DECLS__
#ifdef __cplusplus
extern "C" {
#endif
extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));
#ifdef __cplusplus
}
#endif
#endif // __VOUCHER_FORWARD_TYPE_DECLS__
#endif // __has_include(<mach/mach_voucher_types.h>)
#endif // __has_include
#endif // !KERNEL
/* END VOUCHER CODE */
#ifdef AUTOTEST
#ifndef FUNCTION_PTR_T
#define FUNCTION_PTR_T
typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t);
typedef struct {
char *name;
function_ptr_t function;
} function_table_entry;
typedef function_table_entry *function_table_t;
#endif /* FUNCTION_PTR_T */
#endif /* AUTOTEST */
#ifndef exc_MSG_COUNT
#define exc_MSG_COUNT 3
#endif /* exc_MSG_COUNT */
#include <mach/std_types.h>
#include <mach/mig.h>
#include <mach/mig.h>
#include <mach/mach_types.h>
#ifdef __BeforeMigUserHeader
__BeforeMigUserHeader
#endif /* __BeforeMigUserHeader */
#include <sys/cdefs.h>
__BEGIN_DECLS
/* Routine exception_raise */
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
kern_return_t exception_raise
(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
exception_data_t code,
mach_msg_type_number_t codeCnt
);
/* Routine exception_raise_state */
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
kern_return_t exception_raise_state
(
mach_port_t exception_port,
exception_type_t exception,
const exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
const thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt
);
/* Routine exception_raise_state_identity */
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
kern_return_t exception_raise_state_identity
(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt
);
__END_DECLS
/********************** Caution **************************/
/* The following data types should be used to calculate */
/* maximum message sizes only. The actual message may be */
/* smaller, and the position of the arguments within the */
/* message layout may vary from what is presented here. */
/* For example, if any of the arguments are variable- */
/* sized, and less than the maximum is sent, the data */
/* will be packed tight in the actual message to reduce */
/* the presence of holes. */
/********************** Caution **************************/
/* typedefs for all requests */
#ifndef __Request__exc_subsystem__defined
#define __Request__exc_subsystem__defined
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
} __Request__exception_raise_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
} __Request__exception_raise_state_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
} __Request__exception_raise_state_identity_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#endif /* !__Request__exc_subsystem__defined */
/* union of all requests */
#ifndef __RequestUnion__exc_subsystem__defined
#define __RequestUnion__exc_subsystem__defined
union __RequestUnion__exc_subsystem {
__Request__exception_raise_t Request_exception_raise;
__Request__exception_raise_state_t Request_exception_raise_state;
__Request__exception_raise_state_identity_t Request_exception_raise_state_identity;
};
#endif /* !__RequestUnion__exc_subsystem__defined */
/* typedefs for all replies */
#ifndef __Reply__exc_subsystem__defined
#define __Reply__exc_subsystem__defined
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
} __Reply__exception_raise_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
} __Reply__exception_raise_state_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
} __Reply__exception_raise_state_identity_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#endif /* !__Reply__exc_subsystem__defined */
/* union of all replies */
#ifndef __ReplyUnion__exc_subsystem__defined
#define __ReplyUnion__exc_subsystem__defined
union __ReplyUnion__exc_subsystem {
__Reply__exception_raise_t Reply_exception_raise;
__Reply__exception_raise_state_t Reply_exception_raise_state;
__Reply__exception_raise_state_identity_t Reply_exception_raise_state_identity;
};
#endif /* !__RequestUnion__exc_subsystem__defined */
#ifndef subsystem_to_name_map_exc
#define subsystem_to_name_map_exc \
{ "exception_raise", 2401 },\
{ "exception_raise_state", 2402 },\
{ "exception_raise_state_identity", 2403 }
#endif
#ifdef __AfterMigUserHeader
__AfterMigUserHeader
#endif /* __AfterMigUserHeader */
#endif /* _exc_user_ */

766
proctl/excServer.c Normal file

@ -0,0 +1,766 @@
/*
* IDENTIFICATION:
* stub generated Sun Feb 22 20:54:31 2015
* with a MiG generated by bootstrap_cmds-91
* OPTIONS:
*/
/* Module exc */
#define __MIG_check__Request__exc_subsystem__ 1
#include <string.h>
#include <mach/ndr.h>
#include <mach/boolean.h>
#include <mach/kern_return.h>
#include <mach/notify.h>
#include <mach/mach_types.h>
#include <mach/message.h>
#include <mach/mig_errors.h>
#include <mach/port.h>
/* BEGIN VOUCHER CODE */
#ifndef KERNEL
#if defined(__has_include)
#if __has_include(<mach/mig_voucher_support.h>)
#ifndef USING_VOUCHERS
#define USING_VOUCHERS
#endif
#ifndef __VOUCHER_FORWARD_TYPE_DECLS__
#define __VOUCHER_FORWARD_TYPE_DECLS__
#ifdef __cplusplus
extern "C" {
#endif
extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));
#ifdef __cplusplus
}
#endif
#endif // __VOUCHER_FORWARD_TYPE_DECLS__
#endif // __has_include(<mach/mach_voucher_types.h>)
#endif // __has_include
#endif // !KERNEL
/* END VOUCHER CODE */
#include <mach/std_types.h>
#include <mach/mig.h>
#include <mach/mig.h>
#include <mach/mach_types.h>
#ifndef mig_internal
#define mig_internal static __inline__
#endif /* mig_internal */
#ifndef mig_external
#define mig_external
#endif /* mig_external */
#if !defined(__MigTypeCheck) && defined(TypeCheck)
#define __MigTypeCheck TypeCheck /* Legacy setting */
#endif /* !defined(__MigTypeCheck) */
#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)
#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */
#endif /* !defined(__MigKernelSpecificCode) */
#ifndef LimitCheck
#define LimitCheck 0
#endif /* LimitCheck */
#ifndef min
#define min(a,b) ( ((a) < (b))? (a): (b) )
#endif /* min */
#if !defined(_WALIGN_)
#define _WALIGN_(x) (((x) + 3) & ~3)
#endif /* !defined(_WALIGN_) */
#if !defined(_WALIGNSZ_)
#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))
#endif /* !defined(_WALIGNSZ_) */
#ifndef UseStaticTemplates
#define UseStaticTemplates 0
#endif /* UseStaticTemplates */
#ifndef __DeclareRcvRpc
#define __DeclareRcvRpc(_NUM_, _NAME_)
#endif /* __DeclareRcvRpc */
#ifndef __BeforeRcvRpc
#define __BeforeRcvRpc(_NUM_, _NAME_)
#endif /* __BeforeRcvRpc */
#ifndef __AfterRcvRpc
#define __AfterRcvRpc(_NUM_, _NAME_)
#endif /* __AfterRcvRpc */
#ifndef __DeclareRcvSimple
#define __DeclareRcvSimple(_NUM_, _NAME_)
#endif /* __DeclareRcvSimple */
#ifndef __BeforeRcvSimple
#define __BeforeRcvSimple(_NUM_, _NAME_)
#endif /* __BeforeRcvSimple */
#ifndef __AfterRcvSimple
#define __AfterRcvSimple(_NUM_, _NAME_)
#endif /* __AfterRcvSimple */
#define novalue void
#define msgh_request_port msgh_local_port
#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits)
#define msgh_reply_port msgh_remote_port
#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits)
#define MIG_RETURN_ERROR(X, code) {\
((mig_reply_error_t *)X)->RetCode = code;\
((mig_reply_error_t *)X)->NDR = NDR_record;\
return;\
}
/* typedefs for all requests */
#ifndef __Request__exc_subsystem__defined
#define __Request__exc_subsystem__defined
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
} __Request__exception_raise_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
} __Request__exception_raise_state_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
} __Request__exception_raise_state_identity_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#endif /* !__Request__exc_subsystem__defined */
/* typedefs for all replies */
#ifndef __Reply__exc_subsystem__defined
#define __Reply__exc_subsystem__defined
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
} __Reply__exception_raise_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
} __Reply__exception_raise_state_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
} __Reply__exception_raise_state_identity_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#endif /* !__Reply__exc_subsystem__defined */
/* union of all replies */
#ifndef __ReplyUnion__catch_exc_subsystem__defined
#define __ReplyUnion__catch_exc_subsystem__defined
union __ReplyUnion__catch_exc_subsystem {
__Reply__exception_raise_t Reply_exception_raise;
__Reply__exception_raise_state_t Reply_exception_raise_state;
__Reply__exception_raise_state_identity_t Reply_exception_raise_state_identity;
};
#endif /* __RequestUnion__catch_exc_subsystem__defined */
/* Forward Declarations */
mig_internal novalue _Xexception_raise
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
mig_internal novalue _Xexception_raise_state
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
mig_internal novalue _Xexception_raise_state_identity
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
#if ( __MigTypeCheck )
#if __MIG_check__Request__exc_subsystem__
#if !defined(__MIG_check__Request__exception_raise_t__defined)
#define __MIG_check__Request__exception_raise_t__defined
mig_internal kern_return_t __MIG_check__Request__exception_raise_t(__attribute__((__unused__)) __Request__exception_raise_t *In0P)
{
typedef __Request__exception_raise_t __Request;
#if __MigTypeCheck
unsigned int msgh_size;
#endif /* __MigTypeCheck */
#if __MigTypeCheck
msgh_size = In0P->Head.msgh_size;
if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
(In0P->msgh_body.msgh_descriptor_count != 2) ||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 8)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */
#if __MigTypeCheck
if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR ||
In0P->thread.disposition != 17)
return MIG_TYPE_ERROR;
#endif /* __MigTypeCheck */
#if __MigTypeCheck
if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR ||
In0P->task.disposition != 17)
return MIG_TYPE_ERROR;
#endif /* __MigTypeCheck */
#if defined(__NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined)
if (In0P->NDR.int_rep != NDR_record.int_rep)
__NDR_convert__int_rep__Request__exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined */
#if __MigTypeCheck
if ( In0P->codeCnt > 2 )
return MIG_BAD_ARGUMENTS;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 8)) / 4 < In0P->codeCnt) ||
(msgh_size != (mach_msg_size_t)(sizeof(__Request) - 8) + (4 * In0P->codeCnt)))
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */
return MACH_MSG_SUCCESS;
}
#endif /* !defined(__MIG_check__Request__exception_raise_t__defined) */
#endif /* __MIG_check__Request__exc_subsystem__ */
#endif /* ( __MigTypeCheck ) */
/* Routine exception_raise */
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
kern_return_t catch_exception_raise
(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
exception_data_t code,
mach_msg_type_number_t codeCnt
);
/* Routine exception_raise */
mig_internal novalue _Xexception_raise
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
mach_msg_trailer_t trailer;
} Request;
#ifdef __MigPackStructs
#pragma pack()
#endif
typedef __Request__exception_raise_t __Request;
typedef __Reply__exception_raise_t Reply;
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
Request *In0P = (Request *) InHeadP;
Reply *OutP = (Reply *) OutHeadP;
#ifdef __MIG_check__Request__exception_raise_t__defined
kern_return_t check_result;
#endif /* __MIG_check__Request__exception_raise_t__defined */
__DeclareRcvRpc(2401, "exception_raise")
__BeforeRcvRpc(2401, "exception_raise")
#if defined(__MIG_check__Request__exception_raise_t__defined)
check_result = __MIG_check__Request__exception_raise_t((__Request *)In0P);
if (check_result != MACH_MSG_SUCCESS)
{ MIG_RETURN_ERROR(OutP, check_result); }
#endif /* defined(__MIG_check__Request__exception_raise_t__defined) */
OutP->RetCode = catch_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt);
OutP->NDR = NDR_record;
__AfterRcvRpc(2401, "exception_raise")
}
#if ( __MigTypeCheck )
#if __MIG_check__Request__exc_subsystem__
#if !defined(__MIG_check__Request__exception_raise_state_t__defined)
#define __MIG_check__Request__exception_raise_state_t__defined
mig_internal kern_return_t __MIG_check__Request__exception_raise_state_t(__attribute__((__unused__)) __Request__exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__exception_raise_state_t **In1PP)
{
typedef __Request__exception_raise_state_t __Request;
__Request *In1P;
#if __MigTypeCheck
unsigned int msgh_size;
#endif /* __MigTypeCheck */
unsigned int msgh_size_delta;
#if __MigTypeCheck
msgh_size = In0P->Head.msgh_size;
if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 904)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */
#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined)
if (In0P->NDR.int_rep != NDR_record.int_rep)
__NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined */
msgh_size_delta = (4 * In0P->codeCnt);
#if __MigTypeCheck
if ( In0P->codeCnt > 2 )
return MIG_BAD_ARGUMENTS;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 904)) / 4 < In0P->codeCnt) ||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 904) + (4 * In0P->codeCnt)))
return MIG_BAD_ARGUMENTS;
msgh_size -= msgh_size_delta;
#endif /* __MigTypeCheck */
*In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 8);
#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined)
if (In0P->NDR.int_rep != NDR_record.int_rep)
__NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined */
#if __MigTypeCheck
if ( In1P->old_stateCnt > 224 )
return MIG_BAD_ARGUMENTS;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 904)) / 4 < In1P->old_stateCnt) ||
(msgh_size != (mach_msg_size_t)(sizeof(__Request) - 904) + (4 * In1P->old_stateCnt)))
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */
return MACH_MSG_SUCCESS;
}
#endif /* !defined(__MIG_check__Request__exception_raise_state_t__defined) */
#endif /* __MIG_check__Request__exc_subsystem__ */
#endif /* ( __MigTypeCheck ) */
/* Routine exception_raise_state */
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
kern_return_t catch_exception_raise_state
(
mach_port_t exception_port,
exception_type_t exception,
const exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
const thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt
);
/* Routine exception_raise_state */
mig_internal novalue _Xexception_raise_state
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
mach_msg_trailer_t trailer;
} Request;
#ifdef __MigPackStructs
#pragma pack()
#endif
typedef __Request__exception_raise_state_t __Request;
typedef __Reply__exception_raise_state_t Reply;
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
Request *In0P = (Request *) InHeadP;
Request *In1P;
Reply *OutP = (Reply *) OutHeadP;
#ifdef __MIG_check__Request__exception_raise_state_t__defined
kern_return_t check_result;
#endif /* __MIG_check__Request__exception_raise_state_t__defined */
__DeclareRcvRpc(2402, "exception_raise_state")
__BeforeRcvRpc(2402, "exception_raise_state")
#if defined(__MIG_check__Request__exception_raise_state_t__defined)
check_result = __MIG_check__Request__exception_raise_state_t((__Request *)In0P, (__Request **)&In1P);
if (check_result != MACH_MSG_SUCCESS)
{ MIG_RETURN_ERROR(OutP, check_result); }
#endif /* defined(__MIG_check__Request__exception_raise_state_t__defined) */
OutP->new_stateCnt = 224;
OutP->RetCode = catch_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt);
if (OutP->RetCode != KERN_SUCCESS) {
MIG_RETURN_ERROR(OutP, OutP->RetCode);
}
OutP->NDR = NDR_record;
OutP->flavor = In1P->flavor;
OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt)));
__AfterRcvRpc(2402, "exception_raise_state")
}
#if ( __MigTypeCheck )
#if __MIG_check__Request__exc_subsystem__
#if !defined(__MIG_check__Request__exception_raise_state_identity_t__defined)
#define __MIG_check__Request__exception_raise_state_identity_t__defined
mig_internal kern_return_t __MIG_check__Request__exception_raise_state_identity_t(__attribute__((__unused__)) __Request__exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__exception_raise_state_identity_t **In1PP)
{
typedef __Request__exception_raise_state_identity_t __Request;
__Request *In1P;
#if __MigTypeCheck
unsigned int msgh_size;
#endif /* __MigTypeCheck */
unsigned int msgh_size_delta;
#if __MigTypeCheck
msgh_size = In0P->Head.msgh_size;
if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
(In0P->msgh_body.msgh_descriptor_count != 2) ||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 904)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */
#if __MigTypeCheck
if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR ||
In0P->thread.disposition != 17)
return MIG_TYPE_ERROR;
#endif /* __MigTypeCheck */
#if __MigTypeCheck
if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR ||
In0P->task.disposition != 17)
return MIG_TYPE_ERROR;
#endif /* __MigTypeCheck */
#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined)
if (In0P->NDR.int_rep != NDR_record.int_rep)
__NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined */
msgh_size_delta = (4 * In0P->codeCnt);
#if __MigTypeCheck
if ( In0P->codeCnt > 2 )
return MIG_BAD_ARGUMENTS;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 904)) / 4 < In0P->codeCnt) ||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 904) + (4 * In0P->codeCnt)))
return MIG_BAD_ARGUMENTS;
msgh_size -= msgh_size_delta;
#endif /* __MigTypeCheck */
*In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 8);
#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined)
if (In0P->NDR.int_rep != NDR_record.int_rep)
__NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined */
#if __MigTypeCheck
if ( In1P->old_stateCnt > 224 )
return MIG_BAD_ARGUMENTS;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 904)) / 4 < In1P->old_stateCnt) ||
(msgh_size != (mach_msg_size_t)(sizeof(__Request) - 904) + (4 * In1P->old_stateCnt)))
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */
return MACH_MSG_SUCCESS;
}
#endif /* !defined(__MIG_check__Request__exception_raise_state_identity_t__defined) */
#endif /* __MIG_check__Request__exc_subsystem__ */
#endif /* ( __MigTypeCheck ) */
/* Routine exception_raise_state_identity */
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
kern_return_t catch_exception_raise_state_identity
(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt
);
/* Routine exception_raise_state_identity */
mig_internal novalue _Xexception_raise_state_identity
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
mach_msg_trailer_t trailer;
} Request;
#ifdef __MigPackStructs
#pragma pack()
#endif
typedef __Request__exception_raise_state_identity_t __Request;
typedef __Reply__exception_raise_state_identity_t Reply;
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
Request *In0P = (Request *) InHeadP;
Request *In1P;
Reply *OutP = (Reply *) OutHeadP;
#ifdef __MIG_check__Request__exception_raise_state_identity_t__defined
kern_return_t check_result;
#endif /* __MIG_check__Request__exception_raise_state_identity_t__defined */
__DeclareRcvRpc(2403, "exception_raise_state_identity")
__BeforeRcvRpc(2403, "exception_raise_state_identity")
#if defined(__MIG_check__Request__exception_raise_state_identity_t__defined)
check_result = __MIG_check__Request__exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P);
if (check_result != MACH_MSG_SUCCESS)
{ MIG_RETURN_ERROR(OutP, check_result); }
#endif /* defined(__MIG_check__Request__exception_raise_state_identity_t__defined) */
OutP->new_stateCnt = 224;
OutP->RetCode = catch_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt);
if (OutP->RetCode != KERN_SUCCESS) {
MIG_RETURN_ERROR(OutP, OutP->RetCode);
}
OutP->NDR = NDR_record;
OutP->flavor = In1P->flavor;
OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt)));
__AfterRcvRpc(2403, "exception_raise_state_identity")
}
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
mig_routine_t exc_server_routine(
mach_msg_header_t *InHeadP);
/* Description of this subsystem, for use in direct RPC */
const struct catch_exc_subsystem {
mig_server_routine_t server; /* Server routine */
mach_msg_id_t start; /* Min routine number */
mach_msg_id_t end; /* Max routine number + 1 */
unsigned int maxsize; /* Max msg size */
vm_address_t reserved; /* Reserved */
struct routine_descriptor /*Array of routine descriptors */
routine[3];
} catch_exc_subsystem = {
exc_server_routine,
2401,
2404,
(mach_msg_size_t)sizeof(union __ReplyUnion__catch_exc_subsystem),
(vm_address_t)0,
{
{ (mig_impl_routine_t) 0,
(mig_stub_routine_t) _Xexception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__exception_raise_t)},
{ (mig_impl_routine_t) 0,
(mig_stub_routine_t) _Xexception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__exception_raise_state_t)},
{ (mig_impl_routine_t) 0,
(mig_stub_routine_t) _Xexception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__exception_raise_state_identity_t)},
}
};
mig_external boolean_t exc_server
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
register mig_routine_t routine;
OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);
OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;
/* Minimal size: routine() will update it if different */
OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
OutHeadP->msgh_local_port = MACH_PORT_NULL;
OutHeadP->msgh_id = InHeadP->msgh_id + 100;
if ((InHeadP->msgh_id > 2403) || (InHeadP->msgh_id < 2401) ||
((routine = catch_exc_subsystem.routine[InHeadP->msgh_id - 2401].stub_routine) == 0)) {
((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;
((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;
return FALSE;
}
(*routine) (InHeadP, OutHeadP);
return TRUE;
}
mig_external mig_routine_t exc_server_routine
(mach_msg_header_t *InHeadP)
{
register int msgh_id;
msgh_id = InHeadP->msgh_id - 2401;
if ((msgh_id > 2) || (msgh_id < 0))
return 0;
return catch_exc_subsystem.routine[msgh_id].stub_routine;
}

768
proctl/excUser.c Normal file

@ -0,0 +1,768 @@
/*
* IDENTIFICATION:
* stub generated Sun Feb 22 20:54:31 2015
* with a MiG generated by bootstrap_cmds-91
* OPTIONS:
*/
#define __MIG_check__Reply__exc_subsystem__ 1
#include "exc.h"
#ifndef mig_internal
#define mig_internal static __inline__
#endif /* mig_internal */
#ifndef mig_external
#define mig_external
#endif /* mig_external */
#if !defined(__MigTypeCheck) && defined(TypeCheck)
#define __MigTypeCheck TypeCheck /* Legacy setting */
#endif /* !defined(__MigTypeCheck) */
#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)
#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */
#endif /* !defined(__MigKernelSpecificCode) */
#ifndef LimitCheck
#define LimitCheck 0
#endif /* LimitCheck */
#ifndef min
#define min(a,b) ( ((a) < (b))? (a): (b) )
#endif /* min */
#if !defined(_WALIGN_)
#define _WALIGN_(x) (((x) + 3) & ~3)
#endif /* !defined(_WALIGN_) */
#if !defined(_WALIGNSZ_)
#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))
#endif /* !defined(_WALIGNSZ_) */
#ifndef UseStaticTemplates
#define UseStaticTemplates 0
#endif /* UseStaticTemplates */
#ifndef __MachMsgErrorWithTimeout
#define __MachMsgErrorWithTimeout(_R_) { \
switch (_R_) { \
case MACH_SEND_INVALID_DATA: \
case MACH_SEND_INVALID_DEST: \
case MACH_SEND_INVALID_HEADER: \
mig_put_reply_port(InP->Head.msgh_reply_port); \
break; \
case MACH_SEND_TIMED_OUT: \
case MACH_RCV_TIMED_OUT: \
default: \
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
} \
}
#endif /* __MachMsgErrorWithTimeout */
#ifndef __MachMsgErrorWithoutTimeout
#define __MachMsgErrorWithoutTimeout(_R_) { \
switch (_R_) { \
case MACH_SEND_INVALID_DATA: \
case MACH_SEND_INVALID_DEST: \
case MACH_SEND_INVALID_HEADER: \
mig_put_reply_port(InP->Head.msgh_reply_port); \
break; \
default: \
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
} \
}
#endif /* __MachMsgErrorWithoutTimeout */
#ifndef __DeclareSendRpc
#define __DeclareSendRpc(_NUM_, _NAME_)
#endif /* __DeclareSendRpc */
#ifndef __BeforeSendRpc
#define __BeforeSendRpc(_NUM_, _NAME_)
#endif /* __BeforeSendRpc */
#ifndef __AfterSendRpc
#define __AfterSendRpc(_NUM_, _NAME_)
#endif /* __AfterSendRpc */
#ifndef __DeclareSendSimple
#define __DeclareSendSimple(_NUM_, _NAME_)
#endif /* __DeclareSendSimple */
#ifndef __BeforeSendSimple
#define __BeforeSendSimple(_NUM_, _NAME_)
#endif /* __BeforeSendSimple */
#ifndef __AfterSendSimple
#define __AfterSendSimple(_NUM_, _NAME_)
#endif /* __AfterSendSimple */
#define msgh_request_port msgh_remote_port
#define msgh_reply_port msgh_local_port
#if ( __MigTypeCheck )
#if __MIG_check__Reply__exc_subsystem__
#if !defined(__MIG_check__Reply__exception_raise_t__defined)
#define __MIG_check__Reply__exception_raise_t__defined
mig_internal kern_return_t __MIG_check__Reply__exception_raise_t(__Reply__exception_raise_t *Out0P)
{
typedef __Reply__exception_raise_t __Reply;
if (Out0P->Head.msgh_id != 2501) {
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
{ return MIG_SERVER_DIED; }
else
{ return MIG_REPLY_MISMATCH; }
}
#if __MigTypeCheck
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
(Out0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Reply)))
{ return MIG_TYPE_ERROR ; }
#endif /* __MigTypeCheck */
{
return Out0P->RetCode;
}
}
#endif /* !defined(__MIG_check__Reply__exception_raise_t__defined) */
#endif /* __MIG_check__Reply__exc_subsystem__ */
#endif /* ( __MigTypeCheck ) */
/* Routine exception_raise */
mig_external kern_return_t exception_raise
(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
exception_data_t code,
mach_msg_type_number_t codeCnt
)
{
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
} Request;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
mach_msg_trailer_t trailer;
} Reply;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
} __Reply;
#ifdef __MigPackStructs
#pragma pack()
#endif
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
union {
Request In;
Reply Out;
} Mess;
Request *InP = &Mess.In;
Reply *Out0P = &Mess.Out;
mach_msg_return_t msg_result;
unsigned int msgh_size;
#ifdef __MIG_check__Reply__exception_raise_t__defined
kern_return_t check_result;
#endif /* __MIG_check__Reply__exception_raise_t__defined */
__DeclareSendRpc(2401, "exception_raise")
#if UseStaticTemplates
const static mach_msg_port_descriptor_t threadTemplate = {
/* name = */ MACH_PORT_NULL,
/* pad1 = */ 0,
/* pad2 = */ 0,
/* disp = */ 19,
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
};
#endif /* UseStaticTemplates */
#if UseStaticTemplates
const static mach_msg_port_descriptor_t taskTemplate = {
/* name = */ MACH_PORT_NULL,
/* pad1 = */ 0,
/* pad2 = */ 0,
/* disp = */ 19,
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
};
#endif /* UseStaticTemplates */
InP->msgh_body.msgh_descriptor_count = 2;
#if UseStaticTemplates
InP->thread = threadTemplate;
InP->thread.name = thread;
#else /* UseStaticTemplates */
InP->thread.name = thread;
InP->thread.disposition = 19;
InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
#endif /* UseStaticTemplates */
#if UseStaticTemplates
InP->task = taskTemplate;
InP->task.name = task;
#else /* UseStaticTemplates */
InP->task.name = task;
InP->task.disposition = 19;
InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
#endif /* UseStaticTemplates */
InP->NDR = NDR_record;
InP->exception = exception;
if (codeCnt > 2) {
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) InP->code, (const char *) code, 4 * codeCnt);
InP->codeCnt = codeCnt;
msgh_size = (mach_msg_size_t)(sizeof(Request) - 8) + ((4 * codeCnt));
InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
/* msgh_size passed as argument */
InP->Head.msgh_request_port = exception_port;
InP->Head.msgh_reply_port = mig_get_reply_port();
InP->Head.msgh_id = 2401;
/* BEGIN VOUCHER CODE */
#ifdef USING_VOUCHERS
if (voucher_mach_msg_set != NULL) {
voucher_mach_msg_set(&InP->Head);
}
#endif // USING_VOUCHERS
/* END VOUCHER CODE */
__BeforeSendRpc(2401, "exception_raise")
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
__AfterSendRpc(2401, "exception_raise")
if (msg_result != MACH_MSG_SUCCESS) {
__MachMsgErrorWithoutTimeout(msg_result);
{ return msg_result; }
}
#if defined(__MIG_check__Reply__exception_raise_t__defined)
check_result = __MIG_check__Reply__exception_raise_t((__Reply__exception_raise_t *)Out0P);
if (check_result != MACH_MSG_SUCCESS)
{ return check_result; }
#endif /* defined(__MIG_check__Reply__exception_raise_t__defined) */
return KERN_SUCCESS;
}
#if ( __MigTypeCheck )
#if __MIG_check__Reply__exc_subsystem__
#if !defined(__MIG_check__Reply__exception_raise_state_t__defined)
#define __MIG_check__Reply__exception_raise_state_t__defined
mig_internal kern_return_t __MIG_check__Reply__exception_raise_state_t(__Reply__exception_raise_state_t *Out0P)
{
typedef __Reply__exception_raise_state_t __Reply;
#if __MigTypeCheck
unsigned int msgh_size;
#endif /* __MigTypeCheck */
if (Out0P->Head.msgh_id != 2502) {
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
{ return MIG_SERVER_DIED; }
else
{ return MIG_REPLY_MISMATCH; }
}
#if __MigTypeCheck
msgh_size = Out0P->Head.msgh_size;
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) &&
(msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
Out0P->RetCode == KERN_SUCCESS)))
{ return MIG_TYPE_ERROR ; }
#endif /* __MigTypeCheck */
if (Out0P->RetCode != KERN_SUCCESS) {
return ((mig_reply_error_t *)Out0P)->RetCode;
}
#if __MigTypeCheck
if ( Out0P->new_stateCnt > 224 )
return MIG_TYPE_ERROR;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) ||
(msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4))
{ return MIG_TYPE_ERROR ; }
#endif /* __MigTypeCheck */
return MACH_MSG_SUCCESS;
}
#endif /* !defined(__MIG_check__Reply__exception_raise_state_t__defined) */
#endif /* __MIG_check__Reply__exc_subsystem__ */
#endif /* ( __MigTypeCheck ) */
/* Routine exception_raise_state */
mig_external kern_return_t exception_raise_state
(
mach_port_t exception_port,
exception_type_t exception,
const exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
const thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt
)
{
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
} Request;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
mach_msg_trailer_t trailer;
} Reply;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
} __Reply;
#ifdef __MigPackStructs
#pragma pack()
#endif
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
union {
Request In;
Reply Out;
} Mess;
Request *InP = &Mess.In;
Reply *Out0P = &Mess.Out;
mach_msg_return_t msg_result;
unsigned int msgh_size;
unsigned int msgh_size_delta;
#ifdef __MIG_check__Reply__exception_raise_state_t__defined
kern_return_t check_result;
#endif /* __MIG_check__Reply__exception_raise_state_t__defined */
__DeclareSendRpc(2402, "exception_raise_state")
InP->NDR = NDR_record;
InP->exception = exception;
if (codeCnt > 2) {
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) InP->code, (const char *) code, 4 * codeCnt);
InP->codeCnt = codeCnt;
msgh_size_delta = (4 * codeCnt);
msgh_size = (mach_msg_size_t)(sizeof(Request) - 904) + msgh_size_delta;
InP = (Request *) ((pointer_t) InP + msgh_size_delta - 8);
InP->flavor = *flavor;
if (old_stateCnt > 224) {
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);
InP->old_stateCnt = old_stateCnt;
msgh_size += (4 * old_stateCnt);
InP = &Mess.In;
InP->Head.msgh_bits =
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
/* msgh_size passed as argument */
InP->Head.msgh_request_port = exception_port;
InP->Head.msgh_reply_port = mig_get_reply_port();
InP->Head.msgh_id = 2402;
/* BEGIN VOUCHER CODE */
#ifdef USING_VOUCHERS
if (voucher_mach_msg_set != NULL) {
voucher_mach_msg_set(&InP->Head);
}
#endif // USING_VOUCHERS
/* END VOUCHER CODE */
__BeforeSendRpc(2402, "exception_raise_state")
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
__AfterSendRpc(2402, "exception_raise_state")
if (msg_result != MACH_MSG_SUCCESS) {
__MachMsgErrorWithoutTimeout(msg_result);
{ return msg_result; }
}
#if defined(__MIG_check__Reply__exception_raise_state_t__defined)
check_result = __MIG_check__Reply__exception_raise_state_t((__Reply__exception_raise_state_t *)Out0P);
if (check_result != MACH_MSG_SUCCESS)
{ return check_result; }
#endif /* defined(__MIG_check__Reply__exception_raise_state_t__defined) */
*flavor = Out0P->flavor;
if (Out0P->new_stateCnt > 224) {
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224);
*new_stateCnt = Out0P->new_stateCnt;
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);
*new_stateCnt = Out0P->new_stateCnt;
return KERN_SUCCESS;
}
#if ( __MigTypeCheck )
#if __MIG_check__Reply__exc_subsystem__
#if !defined(__MIG_check__Reply__exception_raise_state_identity_t__defined)
#define __MIG_check__Reply__exception_raise_state_identity_t__defined
mig_internal kern_return_t __MIG_check__Reply__exception_raise_state_identity_t(__Reply__exception_raise_state_identity_t *Out0P)
{
typedef __Reply__exception_raise_state_identity_t __Reply;
#if __MigTypeCheck
unsigned int msgh_size;
#endif /* __MigTypeCheck */
if (Out0P->Head.msgh_id != 2503) {
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
{ return MIG_SERVER_DIED; }
else
{ return MIG_REPLY_MISMATCH; }
}
#if __MigTypeCheck
msgh_size = Out0P->Head.msgh_size;
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) &&
(msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
Out0P->RetCode == KERN_SUCCESS)))
{ return MIG_TYPE_ERROR ; }
#endif /* __MigTypeCheck */
if (Out0P->RetCode != KERN_SUCCESS) {
return ((mig_reply_error_t *)Out0P)->RetCode;
}
#if __MigTypeCheck
if ( Out0P->new_stateCnt > 224 )
return MIG_TYPE_ERROR;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) ||
(msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4))
{ return MIG_TYPE_ERROR ; }
#endif /* __MigTypeCheck */
return MACH_MSG_SUCCESS;
}
#endif /* !defined(__MIG_check__Reply__exception_raise_state_identity_t__defined) */
#endif /* __MIG_check__Reply__exc_subsystem__ */
#endif /* ( __MigTypeCheck ) */
/* Routine exception_raise_state_identity */
mig_external kern_return_t exception_raise_state_identity
(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt
)
{
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
} Request;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
mach_msg_trailer_t trailer;
} Reply;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
} __Reply;
#ifdef __MigPackStructs
#pragma pack()
#endif
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
union {
Request In;
Reply Out;
} Mess;
Request *InP = &Mess.In;
Reply *Out0P = &Mess.Out;
mach_msg_return_t msg_result;
unsigned int msgh_size;
unsigned int msgh_size_delta;
#ifdef __MIG_check__Reply__exception_raise_state_identity_t__defined
kern_return_t check_result;
#endif /* __MIG_check__Reply__exception_raise_state_identity_t__defined */
__DeclareSendRpc(2403, "exception_raise_state_identity")
#if UseStaticTemplates
const static mach_msg_port_descriptor_t threadTemplate = {
/* name = */ MACH_PORT_NULL,
/* pad1 = */ 0,
/* pad2 = */ 0,
/* disp = */ 19,
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
};
#endif /* UseStaticTemplates */
#if UseStaticTemplates
const static mach_msg_port_descriptor_t taskTemplate = {
/* name = */ MACH_PORT_NULL,
/* pad1 = */ 0,
/* pad2 = */ 0,
/* disp = */ 19,
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
};
#endif /* UseStaticTemplates */
InP->msgh_body.msgh_descriptor_count = 2;
#if UseStaticTemplates
InP->thread = threadTemplate;
InP->thread.name = thread;
#else /* UseStaticTemplates */
InP->thread.name = thread;
InP->thread.disposition = 19;
InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
#endif /* UseStaticTemplates */
#if UseStaticTemplates
InP->task = taskTemplate;
InP->task.name = task;
#else /* UseStaticTemplates */
InP->task.name = task;
InP->task.disposition = 19;
InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
#endif /* UseStaticTemplates */
InP->NDR = NDR_record;
InP->exception = exception;
if (codeCnt > 2) {
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) InP->code, (const char *) code, 4 * codeCnt);
InP->codeCnt = codeCnt;
msgh_size_delta = (4 * codeCnt);
msgh_size = (mach_msg_size_t)(sizeof(Request) - 904) + msgh_size_delta;
InP = (Request *) ((pointer_t) InP + msgh_size_delta - 8);
InP->flavor = *flavor;
if (old_stateCnt > 224) {
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);
InP->old_stateCnt = old_stateCnt;
msgh_size += (4 * old_stateCnt);
InP = &Mess.In;
InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
/* msgh_size passed as argument */
InP->Head.msgh_request_port = exception_port;
InP->Head.msgh_reply_port = mig_get_reply_port();
InP->Head.msgh_id = 2403;
/* BEGIN VOUCHER CODE */
#ifdef USING_VOUCHERS
if (voucher_mach_msg_set != NULL) {
voucher_mach_msg_set(&InP->Head);
}
#endif // USING_VOUCHERS
/* END VOUCHER CODE */
__BeforeSendRpc(2403, "exception_raise_state_identity")
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
__AfterSendRpc(2403, "exception_raise_state_identity")
if (msg_result != MACH_MSG_SUCCESS) {
__MachMsgErrorWithoutTimeout(msg_result);
{ return msg_result; }
}
#if defined(__MIG_check__Reply__exception_raise_state_identity_t__defined)
check_result = __MIG_check__Reply__exception_raise_state_identity_t((__Reply__exception_raise_state_identity_t *)Out0P);
if (check_result != MACH_MSG_SUCCESS)
{ return check_result; }
#endif /* defined(__MIG_check__Reply__exception_raise_state_identity_t__defined) */
*flavor = Out0P->flavor;
if (Out0P->new_stateCnt > 224) {
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224);
*new_stateCnt = Out0P->new_stateCnt;
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);
*new_stateCnt = Out0P->new_stateCnt;
return KERN_SUCCESS;
}

119
proctl/mach_exc.defs Normal file

@ -0,0 +1,119 @@
/*
* Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
/*
* Abstract:
* MiG definitions file for Mach exception interface.
*/
subsystem
#if KERNEL_USER
KernelUser
#endif
mach_exc 2405;
#include <mach/std_types.defs>
#include <mach/mach_types.defs>
ServerPrefix catch_;
type mach_exception_data_t = array[*:2] of int64_t;
type exception_type_t = int;
routine mach_exception_raise(
#if KERNEL_USER
exception_port : mach_port_move_send_t;
thread : mach_port_move_send_t;
task : mach_port_move_send_t;
#else /* KERNEL_USER */
exception_port : mach_port_t;
thread : mach_port_t;
task : mach_port_t;
#endif /* KERNEL_USER */
exception : exception_type_t;
code : mach_exception_data_t
);
routine mach_exception_raise_state(
#if KERNEL_USER
exception_port : mach_port_move_send_t;
#else /* KERNEL_USER */
exception_port : mach_port_t;
#endif /* KERNEL_USER */
exception : exception_type_t;
code : mach_exception_data_t, const;
inout flavor : int;
old_state : thread_state_t, const;
out new_state : thread_state_t);
routine mach_exception_raise_state_identity(
#if KERNEL_USER
exception_port : mach_port_move_send_t;
thread : mach_port_move_send_t;
task : mach_port_move_send_t;
#else /* KERNEL_USER */
exception_port : mach_port_t;
thread : mach_port_t;
task : mach_port_t;
#endif /* KERNEL_USER */
exception : exception_type_t;
code : mach_exception_data_t;
inout flavor : int;
old_state : thread_state_t;
out new_state : thread_state_t);
/* vim: set ft=c : */

283
proctl/mach_exc.h Normal file

@ -0,0 +1,283 @@
#ifndef _mach_exc_user_
#define _mach_exc_user_
/* Module mach_exc */
#include <string.h>
#include <mach/ndr.h>
#include <mach/boolean.h>
#include <mach/kern_return.h>
#include <mach/notify.h>
#include <mach/mach_types.h>
#include <mach/message.h>
#include <mach/mig_errors.h>
#include <mach/port.h>
/* BEGIN VOUCHER CODE */
#ifndef KERNEL
#if defined(__has_include)
#if __has_include(<mach/mig_voucher_support.h>)
#ifndef USING_VOUCHERS
#define USING_VOUCHERS
#endif
#ifndef __VOUCHER_FORWARD_TYPE_DECLS__
#define __VOUCHER_FORWARD_TYPE_DECLS__
#ifdef __cplusplus
extern "C" {
#endif
extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));
#ifdef __cplusplus
}
#endif
#endif // __VOUCHER_FORWARD_TYPE_DECLS__
#endif // __has_include(<mach/mach_voucher_types.h>)
#endif // __has_include
#endif // !KERNEL
/* END VOUCHER CODE */
#ifdef AUTOTEST
#ifndef FUNCTION_PTR_T
#define FUNCTION_PTR_T
typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t);
typedef struct {
char *name;
function_ptr_t function;
} function_table_entry;
typedef function_table_entry *function_table_t;
#endif /* FUNCTION_PTR_T */
#endif /* AUTOTEST */
#ifndef mach_exc_MSG_COUNT
#define mach_exc_MSG_COUNT 3
#endif /* mach_exc_MSG_COUNT */
#include <mach/std_types.h>
#include <mach/mig.h>
#include <mach/mig.h>
#include <mach/mach_types.h>
#ifdef __BeforeMigUserHeader
__BeforeMigUserHeader
#endif /* __BeforeMigUserHeader */
#include <sys/cdefs.h>
__BEGIN_DECLS
/* Routine mach_exception_raise */
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
kern_return_t mach_exception_raise
(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
mach_exception_data_t code,
mach_msg_type_number_t codeCnt
);
/* Routine mach_exception_raise_state */
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
kern_return_t mach_exception_raise_state
(
mach_port_t exception_port,
exception_type_t exception,
const mach_exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
const thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt
);
/* Routine mach_exception_raise_state_identity */
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
kern_return_t mach_exception_raise_state_identity
(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
mach_exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt
);
__END_DECLS
/********************** Caution **************************/
/* The following data types should be used to calculate */
/* maximum message sizes only. The actual message may be */
/* smaller, and the position of the arguments within the */
/* message layout may vary from what is presented here. */
/* For example, if any of the arguments are variable- */
/* sized, and less than the maximum is sent, the data */
/* will be packed tight in the actual message to reduce */
/* the presence of holes. */
/********************** Caution **************************/
/* typedefs for all requests */
#ifndef __Request__mach_exc_subsystem__defined
#define __Request__mach_exc_subsystem__defined
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
} __Request__mach_exception_raise_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
} __Request__mach_exception_raise_state_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
} __Request__mach_exception_raise_state_identity_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#endif /* !__Request__mach_exc_subsystem__defined */
/* union of all requests */
#ifndef __RequestUnion__mach_exc_subsystem__defined
#define __RequestUnion__mach_exc_subsystem__defined
union __RequestUnion__mach_exc_subsystem {
__Request__mach_exception_raise_t Request_mach_exception_raise;
__Request__mach_exception_raise_state_t Request_mach_exception_raise_state;
__Request__mach_exception_raise_state_identity_t Request_mach_exception_raise_state_identity;
};
#endif /* !__RequestUnion__mach_exc_subsystem__defined */
/* typedefs for all replies */
#ifndef __Reply__mach_exc_subsystem__defined
#define __Reply__mach_exc_subsystem__defined
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
} __Reply__mach_exception_raise_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
} __Reply__mach_exception_raise_state_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
} __Reply__mach_exception_raise_state_identity_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#endif /* !__Reply__mach_exc_subsystem__defined */
/* union of all replies */
#ifndef __ReplyUnion__mach_exc_subsystem__defined
#define __ReplyUnion__mach_exc_subsystem__defined
union __ReplyUnion__mach_exc_subsystem {
__Reply__mach_exception_raise_t Reply_mach_exception_raise;
__Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state;
__Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity;
};
#endif /* !__RequestUnion__mach_exc_subsystem__defined */
#ifndef subsystem_to_name_map_mach_exc
#define subsystem_to_name_map_mach_exc \
{ "mach_exception_raise", 2401 },\
{ "mach_exception_raise_state", 2402 },\
{ "mach_exception_raise_state_identity", 2403 }
#endif
#ifdef __AfterMigUserHeader
__AfterMigUserHeader
#endif /* __AfterMigUserHeader */
#endif /* _mach_exc_user_ */

771
proctl/mach_excServer.c Normal file

@ -0,0 +1,771 @@
/*
* IDENTIFICATION:
* stub generated Sat Feb 21 18:10:52 2015
* with a MiG generated by bootstrap_cmds-91
* OPTIONS:
*/
/* Module mach_exc */
#define __MIG_check__Request__mach_exc_subsystem__ 1
#include <stdio.h>
#include <string.h>
#include <mach/ndr.h>
#include <mach/boolean.h>
#include <mach/kern_return.h>
#include <mach/notify.h>
#include <mach/mach_types.h>
#include <mach/message.h>
#include <mach/mig_errors.h>
#include <mach/port.h>
/* BEGIN VOUCHER CODE */
#ifndef KERNEL
#if defined(__has_include)
#if __has_include(<mach/mig_voucher_support.h>)
#ifndef USING_VOUCHERS
#define USING_VOUCHERS
#endif
#ifndef __VOUCHER_FORWARD_TYPE_DECLS__
#define __VOUCHER_FORWARD_TYPE_DECLS__
#ifdef __cplusplus
extern "C" {
#endif
extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));
#ifdef __cplusplus
}
#endif
#endif // __VOUCHER_FORWARD_TYPE_DECLS__
#endif // __has_include(<mach/mach_voucher_types.h>)
#endif // __has_include
#endif // !KERNEL
/* END VOUCHER CODE */
#include <mach/std_types.h>
#include <mach/mig.h>
#include <mach/mig.h>
#include <mach/mach_types.h>
#ifndef mig_internal
#define mig_internal static __inline__
#endif /* mig_internal */
#ifndef mig_external
#define mig_external
#endif /* mig_external */
#if !defined(__MigTypeCheck) && defined(TypeCheck)
#define __MigTypeCheck TypeCheck /* Legacy setting */
#endif /* !defined(__MigTypeCheck) */
#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)
#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */
#endif /* !defined(__MigKernelSpecificCode) */
#ifndef LimitCheck
#define LimitCheck 0
#endif /* LimitCheck */
#ifndef min
#define min(a,b) ( ((a) < (b))? (a): (b) )
#endif /* min */
#if !defined(_WALIGN_)
#define _WALIGN_(x) (((x) + 3) & ~3)
#endif /* !defined(_WALIGN_) */
#if !defined(_WALIGNSZ_)
#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))
#endif /* !defined(_WALIGNSZ_) */
#ifndef UseStaticTemplates
#define UseStaticTemplates 0
#endif /* UseStaticTemplates */
#ifndef __DeclareRcvRpc
#define __DeclareRcvRpc(_NUM_, _NAME_)
#endif /* __DeclareRcvRpc */
#ifndef __BeforeRcvRpc
#define __BeforeRcvRpc(_NUM_, _NAME_)
#endif /* __BeforeRcvRpc */
#ifndef __AfterRcvRpc
#define __AfterRcvRpc(_NUM_, _NAME_)
#endif /* __AfterRcvRpc */
#ifndef __DeclareRcvSimple
#define __DeclareRcvSimple(_NUM_, _NAME_)
#endif /* __DeclareRcvSimple */
#ifndef __BeforeRcvSimple
#define __BeforeRcvSimple(_NUM_, _NAME_)
#endif /* __BeforeRcvSimple */
#ifndef __AfterRcvSimple
#define __AfterRcvSimple(_NUM_, _NAME_)
#endif /* __AfterRcvSimple */
#define novalue void
#define msgh_request_port msgh_local_port
#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits)
#define msgh_reply_port msgh_remote_port
#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits)
#define MIG_RETURN_ERROR(X, code) {\
((mig_reply_error_t *)X)->RetCode = code;\
((mig_reply_error_t *)X)->NDR = NDR_record;\
return;\
}
/* typedefs for all requests */
#ifndef __Request__mach_exc_subsystem__defined
#define __Request__mach_exc_subsystem__defined
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
} __Request__mach_exception_raise_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
} __Request__mach_exception_raise_state_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
} __Request__mach_exception_raise_state_identity_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#endif /* !__Request__mach_exc_subsystem__defined */
/* typedefs for all replies */
#ifndef __Reply__mach_exc_subsystem__defined
#define __Reply__mach_exc_subsystem__defined
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
} __Reply__mach_exception_raise_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
} __Reply__mach_exception_raise_state_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
} __Reply__mach_exception_raise_state_identity_t;
#ifdef __MigPackStructs
#pragma pack()
#endif
#endif /* !__Reply__mach_exc_subsystem__defined */
/* union of all replies */
#ifndef __ReplyUnion__catch_mach_exc_subsystem__defined
#define __ReplyUnion__catch_mach_exc_subsystem__defined
union __ReplyUnion__catch_mach_exc_subsystem {
__Reply__mach_exception_raise_t Reply_mach_exception_raise;
__Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state;
__Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity;
};
#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */
/* Forward Declarations */
mig_internal novalue _Xmach_exception_raise
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
mig_internal novalue _Xmach_exception_raise_state
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
mig_internal novalue _Xmach_exception_raise_state_identity
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
#if ( __MigTypeCheck )
#if __MIG_check__Request__mach_exc_subsystem__
#if !defined(__MIG_check__Request__mach_exception_raise_t__defined)
#define __MIG_check__Request__mach_exception_raise_t__defined
mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_t(__attribute__((__unused__)) __Request__mach_exception_raise_t *In0P)
{
typedef __Request__mach_exception_raise_t __Request;
#if __MigTypeCheck
unsigned int msgh_size;
#endif /* __MigTypeCheck */
#if __MigTypeCheck
msgh_size = In0P->Head.msgh_size;
if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
(In0P->msgh_body.msgh_descriptor_count != 2) ||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 16)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */
#if __MigTypeCheck
if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR ||
In0P->thread.disposition != 17)
return MIG_TYPE_ERROR;
#endif /* __MigTypeCheck */
#if __MigTypeCheck
if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR ||
In0P->task.disposition != 17)
return MIG_TYPE_ERROR;
#endif /* __MigTypeCheck */
#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined)
if (In0P->NDR.int_rep != NDR_record.int_rep)
__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined */
#if __MigTypeCheck
if ( In0P->codeCnt > 2 )
return MIG_BAD_ARGUMENTS;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 16)) / 8 < In0P->codeCnt) ||
(msgh_size != (mach_msg_size_t)(sizeof(__Request) - 16) + (8 * In0P->codeCnt)))
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */
return MACH_MSG_SUCCESS;
}
#endif /* !defined(__MIG_check__Request__mach_exception_raise_t__defined) */
#endif /* __MIG_check__Request__mach_exc_subsystem__ */
#endif /* ( __MigTypeCheck ) */
/* Routine mach_exception_raise */
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
kern_return_t catch_mach_exception_raise
(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
mach_exception_data_t code,
mach_msg_type_number_t codeCnt
);
/* Routine mach_exception_raise */
mig_internal novalue _Xmach_exception_raise
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
mach_msg_trailer_t trailer;
} Request;
#ifdef __MigPackStructs
#pragma pack()
#endif
typedef __Request__mach_exception_raise_t __Request;
typedef __Reply__mach_exception_raise_t Reply;
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
Request *In0P = (Request *) InHeadP;
Reply *OutP = (Reply *) OutHeadP;
#ifdef __MIG_check__Request__mach_exception_raise_t__defined
kern_return_t check_result;
#endif /* __MIG_check__Request__mach_exception_raise_t__defined */
__DeclareRcvRpc(2405, "mach_exception_raise")
__BeforeRcvRpc(2405, "mach_exception_raise")
#if defined(__MIG_check__Request__mach_exception_raise_t__defined)
check_result = __MIG_check__Request__mach_exception_raise_t((__Request *)In0P);
if (check_result != MACH_MSG_SUCCESS)
{ MIG_RETURN_ERROR(OutP, check_result); }
#endif /* defined(__MIG_check__Request__mach_exception_raise_t__defined) */
OutP->RetCode = catch_mach_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt);
OutP->NDR = NDR_record;
__AfterRcvRpc(2405, "mach_exception_raise")
}
#if ( __MigTypeCheck )
#if __MIG_check__Request__mach_exc_subsystem__
#if !defined(__MIG_check__Request__mach_exception_raise_state_t__defined)
#define __MIG_check__Request__mach_exception_raise_state_t__defined
mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_t **In1PP)
{
typedef __Request__mach_exception_raise_state_t __Request;
__Request *In1P;
#if __MigTypeCheck
unsigned int msgh_size;
#endif /* __MigTypeCheck */
unsigned int msgh_size_delta;
#if __MigTypeCheck
msgh_size = In0P->Head.msgh_size;
if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */
#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined)
if (In0P->NDR.int_rep != NDR_record.int_rep)
__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined */
msgh_size_delta = (8 * In0P->codeCnt);
#if __MigTypeCheck
if ( In0P->codeCnt > 2 )
return MIG_BAD_ARGUMENTS;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) ||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt)))
return MIG_BAD_ARGUMENTS;
msgh_size -= msgh_size_delta;
#endif /* __MigTypeCheck */
*In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16);
#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined)
if (In0P->NDR.int_rep != NDR_record.int_rep)
__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined */
#if __MigTypeCheck
if ( In1P->old_stateCnt > 224 )
return MIG_BAD_ARGUMENTS;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) ||
(msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt)))
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */
return MACH_MSG_SUCCESS;
}
#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */
#endif /* __MIG_check__Request__mach_exc_subsystem__ */
#endif /* ( __MigTypeCheck ) */
/* Routine mach_exception_raise_state */
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
kern_return_t catch_mach_exception_raise_state
(
mach_port_t exception_port,
exception_type_t exception,
const mach_exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
const thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt
);
/* Routine mach_exception_raise_state */
mig_internal novalue _Xmach_exception_raise_state
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
mach_msg_trailer_t trailer;
} Request;
#ifdef __MigPackStructs
#pragma pack()
#endif
typedef __Request__mach_exception_raise_state_t __Request;
typedef __Reply__mach_exception_raise_state_t Reply;
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
Request *In0P = (Request *) InHeadP;
Request *In1P;
Reply *OutP = (Reply *) OutHeadP;
#ifdef __MIG_check__Request__mach_exception_raise_state_t__defined
kern_return_t check_result;
#endif /* __MIG_check__Request__mach_exception_raise_state_t__defined */
__DeclareRcvRpc(2406, "mach_exception_raise_state")
__BeforeRcvRpc(2406, "mach_exception_raise_state")
#if defined(__MIG_check__Request__mach_exception_raise_state_t__defined)
check_result = __MIG_check__Request__mach_exception_raise_state_t((__Request *)In0P, (__Request **)&In1P);
if (check_result != MACH_MSG_SUCCESS)
{ MIG_RETURN_ERROR(OutP, check_result); }
#endif /* defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */
OutP->new_stateCnt = 224;
OutP->RetCode = catch_mach_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt);
if (OutP->RetCode != KERN_SUCCESS) {
MIG_RETURN_ERROR(OutP, OutP->RetCode);
}
OutP->NDR = NDR_record;
OutP->flavor = In1P->flavor;
OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt)));
__AfterRcvRpc(2406, "mach_exception_raise_state")
}
#if ( __MigTypeCheck )
#if __MIG_check__Request__mach_exc_subsystem__
#if !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined)
#define __MIG_check__Request__mach_exception_raise_state_identity_t__defined
mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_identity_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t **In1PP)
{
typedef __Request__mach_exception_raise_state_identity_t __Request;
__Request *In1P;
#if __MigTypeCheck
unsigned int msgh_size;
#endif /* __MigTypeCheck */
unsigned int msgh_size_delta;
#if __MigTypeCheck
msgh_size = In0P->Head.msgh_size;
if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
(In0P->msgh_body.msgh_descriptor_count != 2) ||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */
#if __MigTypeCheck
if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR ||
In0P->thread.disposition != 17)
return MIG_TYPE_ERROR;
#endif /* __MigTypeCheck */
#if __MigTypeCheck
if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR ||
In0P->task.disposition != 17)
return MIG_TYPE_ERROR;
#endif /* __MigTypeCheck */
#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined)
if (In0P->NDR.int_rep != NDR_record.int_rep)
__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined */
msgh_size_delta = (8 * In0P->codeCnt);
#if __MigTypeCheck
if ( In0P->codeCnt > 2 )
return MIG_BAD_ARGUMENTS;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) ||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt)))
return MIG_BAD_ARGUMENTS;
msgh_size -= msgh_size_delta;
#endif /* __MigTypeCheck */
*In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16);
#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined)
if (In0P->NDR.int_rep != NDR_record.int_rep)
__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined */
#if __MigTypeCheck
if ( In1P->old_stateCnt > 224 )
return MIG_BAD_ARGUMENTS;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) ||
(msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt)))
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */
return MACH_MSG_SUCCESS;
}
#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */
#endif /* __MIG_check__Request__mach_exc_subsystem__ */
#endif /* ( __MigTypeCheck ) */
/* Routine mach_exception_raise_state_identity */
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
kern_return_t catch_mach_exception_raise_state_identity
(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
mach_exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt
);
/* Routine mach_exception_raise_state_identity */
mig_internal novalue _Xmach_exception_raise_state_identity
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
mach_msg_trailer_t trailer;
} Request;
#ifdef __MigPackStructs
#pragma pack()
#endif
typedef __Request__mach_exception_raise_state_identity_t __Request;
typedef __Reply__mach_exception_raise_state_identity_t Reply;
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
Request *In0P = (Request *) InHeadP;
Request *In1P;
Reply *OutP = (Reply *) OutHeadP;
#ifdef __MIG_check__Request__mach_exception_raise_state_identity_t__defined
kern_return_t check_result;
#endif /* __MIG_check__Request__mach_exception_raise_state_identity_t__defined */
__DeclareRcvRpc(2407, "mach_exception_raise_state_identity")
__BeforeRcvRpc(2407, "mach_exception_raise_state_identity")
#if defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined)
check_result = __MIG_check__Request__mach_exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P);
if (check_result != MACH_MSG_SUCCESS)
{ MIG_RETURN_ERROR(OutP, check_result); }
#endif /* defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */
OutP->new_stateCnt = 224;
OutP->RetCode = catch_mach_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt);
if (OutP->RetCode != KERN_SUCCESS) {
MIG_RETURN_ERROR(OutP, OutP->RetCode);
}
OutP->NDR = NDR_record;
OutP->flavor = In1P->flavor;
OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt)));
__AfterRcvRpc(2407, "mach_exception_raise_state_identity")
}
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
mig_routine_t mach_exc_server_routine(
mach_msg_header_t *InHeadP);
/* Description of this subsystem, for use in direct RPC */
const struct catch_mach_exc_subsystem {
mig_server_routine_t server; /* Server routine */
mach_msg_id_t start; /* Min routine number */
mach_msg_id_t end; /* Max routine number + 1 */
unsigned int maxsize; /* Max msg size */
vm_address_t reserved; /* Reserved */
struct routine_descriptor /*Array of routine descriptors */
routine[3];
} catch_mach_exc_subsystem = {
mach_exc_server_routine,
2405,
2408,
(mach_msg_size_t)sizeof(union __ReplyUnion__catch_mach_exc_subsystem),
(vm_address_t)0,
{
{ (mig_impl_routine_t) 0,
(mig_stub_routine_t) _Xmach_exception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_t)},
{ (mig_impl_routine_t) 0,
(mig_stub_routine_t) _Xmach_exception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_t)},
{ (mig_impl_routine_t) 0,
(mig_stub_routine_t) _Xmach_exception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_identity_t)},
}
};
mig_external boolean_t mach_exc_server
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
register mig_routine_t routine;
OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);
OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;
/* Minimal size: routine() will update it if different */
OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
OutHeadP->msgh_local_port = MACH_PORT_NULL;
OutHeadP->msgh_id = InHeadP->msgh_id + 100;
#if TARGET_OSX_USE_64BIT_EXCEPTIONS
puts("64 bit");
#endif
if ((InHeadP->msgh_id > 2407) || (InHeadP->msgh_id < 2405) ||
((routine = catch_mach_exc_subsystem.routine[InHeadP->msgh_id - 2405].stub_routine) == 0)) {
((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;
((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;
printf("msgh_id %d\n", InHeadP->msgh_id);
return FALSE;
}
(*routine) (InHeadP, OutHeadP);
return TRUE;
}
mig_external mig_routine_t mach_exc_server_routine
(mach_msg_header_t *InHeadP)
{
register int msgh_id;
msgh_id = InHeadP->msgh_id - 2405;
if ((msgh_id > 2) || (msgh_id < 0))
return 0;
return catch_mach_exc_subsystem.routine[msgh_id].stub_routine;
}

768
proctl/mach_excUser.c Normal file

@ -0,0 +1,768 @@
/*
* IDENTIFICATION:
* stub generated Sat Feb 21 18:10:52 2015
* with a MiG generated by bootstrap_cmds-91
* OPTIONS:
*/
#define __MIG_check__Reply__mach_exc_subsystem__ 1
#include "mach_exc.h"
#ifndef mig_internal
#define mig_internal static __inline__
#endif /* mig_internal */
#ifndef mig_external
#define mig_external
#endif /* mig_external */
#if !defined(__MigTypeCheck) && defined(TypeCheck)
#define __MigTypeCheck TypeCheck /* Legacy setting */
#endif /* !defined(__MigTypeCheck) */
#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)
#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */
#endif /* !defined(__MigKernelSpecificCode) */
#ifndef LimitCheck
#define LimitCheck 0
#endif /* LimitCheck */
#ifndef min
#define min(a,b) ( ((a) < (b))? (a): (b) )
#endif /* min */
#if !defined(_WALIGN_)
#define _WALIGN_(x) (((x) + 3) & ~3)
#endif /* !defined(_WALIGN_) */
#if !defined(_WALIGNSZ_)
#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))
#endif /* !defined(_WALIGNSZ_) */
#ifndef UseStaticTemplates
#define UseStaticTemplates 0
#endif /* UseStaticTemplates */
#ifndef __MachMsgErrorWithTimeout
#define __MachMsgErrorWithTimeout(_R_) { \
switch (_R_) { \
case MACH_SEND_INVALID_DATA: \
case MACH_SEND_INVALID_DEST: \
case MACH_SEND_INVALID_HEADER: \
mig_put_reply_port(InP->Head.msgh_reply_port); \
break; \
case MACH_SEND_TIMED_OUT: \
case MACH_RCV_TIMED_OUT: \
default: \
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
} \
}
#endif /* __MachMsgErrorWithTimeout */
#ifndef __MachMsgErrorWithoutTimeout
#define __MachMsgErrorWithoutTimeout(_R_) { \
switch (_R_) { \
case MACH_SEND_INVALID_DATA: \
case MACH_SEND_INVALID_DEST: \
case MACH_SEND_INVALID_HEADER: \
mig_put_reply_port(InP->Head.msgh_reply_port); \
break; \
default: \
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
} \
}
#endif /* __MachMsgErrorWithoutTimeout */
#ifndef __DeclareSendRpc
#define __DeclareSendRpc(_NUM_, _NAME_)
#endif /* __DeclareSendRpc */
#ifndef __BeforeSendRpc
#define __BeforeSendRpc(_NUM_, _NAME_)
#endif /* __BeforeSendRpc */
#ifndef __AfterSendRpc
#define __AfterSendRpc(_NUM_, _NAME_)
#endif /* __AfterSendRpc */
#ifndef __DeclareSendSimple
#define __DeclareSendSimple(_NUM_, _NAME_)
#endif /* __DeclareSendSimple */
#ifndef __BeforeSendSimple
#define __BeforeSendSimple(_NUM_, _NAME_)
#endif /* __BeforeSendSimple */
#ifndef __AfterSendSimple
#define __AfterSendSimple(_NUM_, _NAME_)
#endif /* __AfterSendSimple */
#define msgh_request_port msgh_remote_port
#define msgh_reply_port msgh_local_port
#if ( __MigTypeCheck )
#if __MIG_check__Reply__mach_exc_subsystem__
#if !defined(__MIG_check__Reply__mach_exception_raise_t__defined)
#define __MIG_check__Reply__mach_exception_raise_t__defined
mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_t(__Reply__mach_exception_raise_t *Out0P)
{
typedef __Reply__mach_exception_raise_t __Reply;
if (Out0P->Head.msgh_id != 2505) {
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
{ return MIG_SERVER_DIED; }
else
{ return MIG_REPLY_MISMATCH; }
}
#if __MigTypeCheck
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
(Out0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Reply)))
{ return MIG_TYPE_ERROR ; }
#endif /* __MigTypeCheck */
{
return Out0P->RetCode;
}
}
#endif /* !defined(__MIG_check__Reply__mach_exception_raise_t__defined) */
#endif /* __MIG_check__Reply__mach_exc_subsystem__ */
#endif /* ( __MigTypeCheck ) */
/* Routine mach_exception_raise */
mig_external kern_return_t mach_exception_raise
(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
mach_exception_data_t code,
mach_msg_type_number_t codeCnt
)
{
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
} Request;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
mach_msg_trailer_t trailer;
} Reply;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
} __Reply;
#ifdef __MigPackStructs
#pragma pack()
#endif
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
union {
Request In;
Reply Out;
} Mess;
Request *InP = &Mess.In;
Reply *Out0P = &Mess.Out;
mach_msg_return_t msg_result;
unsigned int msgh_size;
#ifdef __MIG_check__Reply__mach_exception_raise_t__defined
kern_return_t check_result;
#endif /* __MIG_check__Reply__mach_exception_raise_t__defined */
__DeclareSendRpc(2405, "mach_exception_raise")
#if UseStaticTemplates
const static mach_msg_port_descriptor_t threadTemplate = {
/* name = */ MACH_PORT_NULL,
/* pad1 = */ 0,
/* pad2 = */ 0,
/* disp = */ 19,
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
};
#endif /* UseStaticTemplates */
#if UseStaticTemplates
const static mach_msg_port_descriptor_t taskTemplate = {
/* name = */ MACH_PORT_NULL,
/* pad1 = */ 0,
/* pad2 = */ 0,
/* disp = */ 19,
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
};
#endif /* UseStaticTemplates */
InP->msgh_body.msgh_descriptor_count = 2;
#if UseStaticTemplates
InP->thread = threadTemplate;
InP->thread.name = thread;
#else /* UseStaticTemplates */
InP->thread.name = thread;
InP->thread.disposition = 19;
InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
#endif /* UseStaticTemplates */
#if UseStaticTemplates
InP->task = taskTemplate;
InP->task.name = task;
#else /* UseStaticTemplates */
InP->task.name = task;
InP->task.disposition = 19;
InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
#endif /* UseStaticTemplates */
InP->NDR = NDR_record;
InP->exception = exception;
if (codeCnt > 2) {
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);
InP->codeCnt = codeCnt;
msgh_size = (mach_msg_size_t)(sizeof(Request) - 16) + ((8 * codeCnt));
InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
/* msgh_size passed as argument */
InP->Head.msgh_request_port = exception_port;
InP->Head.msgh_reply_port = mig_get_reply_port();
InP->Head.msgh_id = 2405;
/* BEGIN VOUCHER CODE */
#ifdef USING_VOUCHERS
if (voucher_mach_msg_set != NULL) {
voucher_mach_msg_set(&InP->Head);
}
#endif // USING_VOUCHERS
/* END VOUCHER CODE */
__BeforeSendRpc(2405, "mach_exception_raise")
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
__AfterSendRpc(2405, "mach_exception_raise")
if (msg_result != MACH_MSG_SUCCESS) {
__MachMsgErrorWithoutTimeout(msg_result);
{ return msg_result; }
}
#if defined(__MIG_check__Reply__mach_exception_raise_t__defined)
check_result = __MIG_check__Reply__mach_exception_raise_t((__Reply__mach_exception_raise_t *)Out0P);
if (check_result != MACH_MSG_SUCCESS)
{ return check_result; }
#endif /* defined(__MIG_check__Reply__mach_exception_raise_t__defined) */
return KERN_SUCCESS;
}
#if ( __MigTypeCheck )
#if __MIG_check__Reply__mach_exc_subsystem__
#if !defined(__MIG_check__Reply__mach_exception_raise_state_t__defined)
#define __MIG_check__Reply__mach_exception_raise_state_t__defined
mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_state_t(__Reply__mach_exception_raise_state_t *Out0P)
{
typedef __Reply__mach_exception_raise_state_t __Reply;
#if __MigTypeCheck
unsigned int msgh_size;
#endif /* __MigTypeCheck */
if (Out0P->Head.msgh_id != 2506) {
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
{ return MIG_SERVER_DIED; }
else
{ return MIG_REPLY_MISMATCH; }
}
#if __MigTypeCheck
msgh_size = Out0P->Head.msgh_size;
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) &&
(msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
Out0P->RetCode == KERN_SUCCESS)))
{ return MIG_TYPE_ERROR ; }
#endif /* __MigTypeCheck */
if (Out0P->RetCode != KERN_SUCCESS) {
return ((mig_reply_error_t *)Out0P)->RetCode;
}
#if __MigTypeCheck
if ( Out0P->new_stateCnt > 224 )
return MIG_TYPE_ERROR;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) ||
(msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4))
{ return MIG_TYPE_ERROR ; }
#endif /* __MigTypeCheck */
return MACH_MSG_SUCCESS;
}
#endif /* !defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) */
#endif /* __MIG_check__Reply__mach_exc_subsystem__ */
#endif /* ( __MigTypeCheck ) */
/* Routine mach_exception_raise_state */
mig_external kern_return_t mach_exception_raise_state
(
mach_port_t exception_port,
exception_type_t exception,
const mach_exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
const thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt
)
{
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
} Request;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
mach_msg_trailer_t trailer;
} Reply;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
} __Reply;
#ifdef __MigPackStructs
#pragma pack()
#endif
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
union {
Request In;
Reply Out;
} Mess;
Request *InP = &Mess.In;
Reply *Out0P = &Mess.Out;
mach_msg_return_t msg_result;
unsigned int msgh_size;
unsigned int msgh_size_delta;
#ifdef __MIG_check__Reply__mach_exception_raise_state_t__defined
kern_return_t check_result;
#endif /* __MIG_check__Reply__mach_exception_raise_state_t__defined */
__DeclareSendRpc(2406, "mach_exception_raise_state")
InP->NDR = NDR_record;
InP->exception = exception;
if (codeCnt > 2) {
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);
InP->codeCnt = codeCnt;
msgh_size_delta = (8 * codeCnt);
msgh_size = (mach_msg_size_t)(sizeof(Request) - 912) + msgh_size_delta;
InP = (Request *) ((pointer_t) InP + msgh_size_delta - 16);
InP->flavor = *flavor;
if (old_stateCnt > 224) {
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);
InP->old_stateCnt = old_stateCnt;
msgh_size += (4 * old_stateCnt);
InP = &Mess.In;
InP->Head.msgh_bits =
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
/* msgh_size passed as argument */
InP->Head.msgh_request_port = exception_port;
InP->Head.msgh_reply_port = mig_get_reply_port();
InP->Head.msgh_id = 2406;
/* BEGIN VOUCHER CODE */
#ifdef USING_VOUCHERS
if (voucher_mach_msg_set != NULL) {
voucher_mach_msg_set(&InP->Head);
}
#endif // USING_VOUCHERS
/* END VOUCHER CODE */
__BeforeSendRpc(2406, "mach_exception_raise_state")
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
__AfterSendRpc(2406, "mach_exception_raise_state")
if (msg_result != MACH_MSG_SUCCESS) {
__MachMsgErrorWithoutTimeout(msg_result);
{ return msg_result; }
}
#if defined(__MIG_check__Reply__mach_exception_raise_state_t__defined)
check_result = __MIG_check__Reply__mach_exception_raise_state_t((__Reply__mach_exception_raise_state_t *)Out0P);
if (check_result != MACH_MSG_SUCCESS)
{ return check_result; }
#endif /* defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) */
*flavor = Out0P->flavor;
if (Out0P->new_stateCnt > 224) {
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224);
*new_stateCnt = Out0P->new_stateCnt;
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);
*new_stateCnt = Out0P->new_stateCnt;
return KERN_SUCCESS;
}
#if ( __MigTypeCheck )
#if __MIG_check__Reply__mach_exc_subsystem__
#if !defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined)
#define __MIG_check__Reply__mach_exception_raise_state_identity_t__defined
mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_state_identity_t(__Reply__mach_exception_raise_state_identity_t *Out0P)
{
typedef __Reply__mach_exception_raise_state_identity_t __Reply;
#if __MigTypeCheck
unsigned int msgh_size;
#endif /* __MigTypeCheck */
if (Out0P->Head.msgh_id != 2507) {
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
{ return MIG_SERVER_DIED; }
else
{ return MIG_REPLY_MISMATCH; }
}
#if __MigTypeCheck
msgh_size = Out0P->Head.msgh_size;
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) &&
(msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
Out0P->RetCode == KERN_SUCCESS)))
{ return MIG_TYPE_ERROR ; }
#endif /* __MigTypeCheck */
if (Out0P->RetCode != KERN_SUCCESS) {
return ((mig_reply_error_t *)Out0P)->RetCode;
}
#if __MigTypeCheck
if ( Out0P->new_stateCnt > 224 )
return MIG_TYPE_ERROR;
if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) ||
(msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4))
{ return MIG_TYPE_ERROR ; }
#endif /* __MigTypeCheck */
return MACH_MSG_SUCCESS;
}
#endif /* !defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) */
#endif /* __MIG_check__Reply__mach_exc_subsystem__ */
#endif /* ( __MigTypeCheck ) */
/* Routine mach_exception_raise_state_identity */
mig_external kern_return_t mach_exception_raise_state_identity
(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
mach_exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt
)
{
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
/* start of the kernel processed data */
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
/* end of the kernel processed data */
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[224];
} Request;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
mach_msg_trailer_t trailer;
} Reply;
#ifdef __MigPackStructs
#pragma pack()
#endif
#ifdef __MigPackStructs
#pragma pack(4)
#endif
typedef struct {
mach_msg_header_t Head;
NDR_record_t NDR;
kern_return_t RetCode;
int flavor;
mach_msg_type_number_t new_stateCnt;
natural_t new_state[224];
} __Reply;
#ifdef __MigPackStructs
#pragma pack()
#endif
/*
* typedef struct {
* mach_msg_header_t Head;
* NDR_record_t NDR;
* kern_return_t RetCode;
* } mig_reply_error_t;
*/
union {
Request In;
Reply Out;
} Mess;
Request *InP = &Mess.In;
Reply *Out0P = &Mess.Out;
mach_msg_return_t msg_result;
unsigned int msgh_size;
unsigned int msgh_size_delta;
#ifdef __MIG_check__Reply__mach_exception_raise_state_identity_t__defined
kern_return_t check_result;
#endif /* __MIG_check__Reply__mach_exception_raise_state_identity_t__defined */
__DeclareSendRpc(2407, "mach_exception_raise_state_identity")
#if UseStaticTemplates
const static mach_msg_port_descriptor_t threadTemplate = {
/* name = */ MACH_PORT_NULL,
/* pad1 = */ 0,
/* pad2 = */ 0,
/* disp = */ 19,
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
};
#endif /* UseStaticTemplates */
#if UseStaticTemplates
const static mach_msg_port_descriptor_t taskTemplate = {
/* name = */ MACH_PORT_NULL,
/* pad1 = */ 0,
/* pad2 = */ 0,
/* disp = */ 19,
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
};
#endif /* UseStaticTemplates */
InP->msgh_body.msgh_descriptor_count = 2;
#if UseStaticTemplates
InP->thread = threadTemplate;
InP->thread.name = thread;
#else /* UseStaticTemplates */
InP->thread.name = thread;
InP->thread.disposition = 19;
InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
#endif /* UseStaticTemplates */
#if UseStaticTemplates
InP->task = taskTemplate;
InP->task.name = task;
#else /* UseStaticTemplates */
InP->task.name = task;
InP->task.disposition = 19;
InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
#endif /* UseStaticTemplates */
InP->NDR = NDR_record;
InP->exception = exception;
if (codeCnt > 2) {
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);
InP->codeCnt = codeCnt;
msgh_size_delta = (8 * codeCnt);
msgh_size = (mach_msg_size_t)(sizeof(Request) - 912) + msgh_size_delta;
InP = (Request *) ((pointer_t) InP + msgh_size_delta - 16);
InP->flavor = *flavor;
if (old_stateCnt > 224) {
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);
InP->old_stateCnt = old_stateCnt;
msgh_size += (4 * old_stateCnt);
InP = &Mess.In;
InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
/* msgh_size passed as argument */
InP->Head.msgh_request_port = exception_port;
InP->Head.msgh_reply_port = mig_get_reply_port();
InP->Head.msgh_id = 2407;
/* BEGIN VOUCHER CODE */
#ifdef USING_VOUCHERS
if (voucher_mach_msg_set != NULL) {
voucher_mach_msg_set(&InP->Head);
}
#endif // USING_VOUCHERS
/* END VOUCHER CODE */
__BeforeSendRpc(2407, "mach_exception_raise_state_identity")
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
__AfterSendRpc(2407, "mach_exception_raise_state_identity")
if (msg_result != MACH_MSG_SUCCESS) {
__MachMsgErrorWithoutTimeout(msg_result);
{ return msg_result; }
}
#if defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined)
check_result = __MIG_check__Reply__mach_exception_raise_state_identity_t((__Reply__mach_exception_raise_state_identity_t *)Out0P);
if (check_result != MACH_MSG_SUCCESS)
{ return check_result; }
#endif /* defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) */
*flavor = Out0P->flavor;
if (Out0P->new_stateCnt > 224) {
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224);
*new_stateCnt = Out0P->new_stateCnt;
{ return MIG_ARRAY_TOO_LARGE; }
}
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);
*new_stateCnt = Out0P->new_stateCnt;
return KERN_SUCCESS;
}

@ -12,7 +12,6 @@ import (
"strconv"
"strings"
"syscall"
"time"
sys "golang.org/x/sys/unix"
@ -32,6 +31,7 @@ type DebuggedProcess struct {
BreakPoints map[uint64]*BreakPoint
Threads map[int]*ThreadContext
CurrentThread *ThreadContext
os *OSProcessDetails
breakpointIDCounter int
running bool
halt bool
@ -52,19 +52,9 @@ func Attach(pid int) (*DebuggedProcess, error) {
return nil, err
}
// Attach to all currently active threads.
allm, err := dbp.CurrentThread.AllM()
if err != nil {
if err := dbp.updateThreadList(); err != nil {
return nil, err
}
for _, m := range allm {
if m.procid == 0 {
continue
}
_, err := dbp.AttachThread(m.procid)
if err != nil {
return nil, err
}
}
return dbp, nil
}
@ -90,70 +80,6 @@ func Launch(cmd []string) (*DebuggedProcess, error) {
return newDebugProcess(proc.Process.Pid, false)
}
// Returns a new DebuggedProcess struct with sensible defaults.
func newDebugProcess(pid int, attach bool) (*DebuggedProcess, error) {
dbp := DebuggedProcess{
Pid: pid,
Threads: make(map[int]*ThreadContext),
BreakPoints: make(map[uint64]*BreakPoint),
}
if attach {
thread, err := dbp.AttachThread(pid)
if err != nil {
return nil, err
}
dbp.CurrentThread = thread
} else {
thread, err := dbp.addThread(pid)
if err != nil {
return nil, err
}
dbp.CurrentThread = thread
}
proc, err := os.FindProcess(pid)
if err != nil {
return nil, err
}
dbp.Process = proc
err = dbp.LoadInformation()
if err != nil {
return nil, err
}
return &dbp, nil
}
// Attach to a newly created thread, and store that thread in our list of
// known threads.
func (dbp *DebuggedProcess) AttachThread(tid int) (*ThreadContext, error) {
if thread, ok := dbp.Threads[tid]; ok {
return thread, nil
}
err := sys.PtraceAttach(tid)
if err != nil && err != sys.EPERM {
// Do not return err if err == EPERM,
// we may already be tracing this thread due to
// PTRACE_O_TRACECLONE. We will surely blow up later
// if we truly don't have permissions.
return nil, fmt.Errorf("could not attach to new thread %d %s", tid, err)
}
pid, status, err := wait(tid, 0)
if err != nil {
return nil, err
}
if status.Exited() {
return nil, fmt.Errorf("thread already exited %d", pid)
}
return dbp.addThread(tid)
}
// Returns whether or not Delve thinks the debugged
// process is currently executing.
func (dbp *DebuggedProcess) Running() bool {
@ -219,18 +145,22 @@ func (dbp *DebuggedProcess) FindLocation(str string) (uint64, error) {
func (dbp *DebuggedProcess) RequestManualStop() {
dbp.halt = true
for _, th := range dbp.Threads {
if stopped(th.Id) {
continue
}
sys.Tgkill(dbp.Pid, th.Id, sys.SIGSTOP)
th.Halt()
}
dbp.running = false
}
// Sets a breakpoint, adding it to our list of known breakpoints. Uses
// the "current thread" when setting the breakpoint.
// Sets a breakpoint at addr, and stores it in the process wide
// break point table. Setting a break point must be thread specific due to
// ptrace actions needing the thread to be in a signal-delivery-stop.
//
// Depending on hardware support, Delve will choose to either
// set a hardware or software breakpoint. Essentially, if the
// hardware supports it, and there are free debug registers, Delve
// will set a hardware breakpoint. Otherwise we fall back to software
// breakpoints, which are a bit more work for us.
func (dbp *DebuggedProcess) Break(addr uint64) (*BreakPoint, error) {
return dbp.CurrentThread.Break(addr)
return dbp.setBreakpoint(dbp.CurrentThread.Id, addr)
}
// Sets a breakpoint by location string (function, file+line, address)
@ -239,12 +169,12 @@ func (dbp *DebuggedProcess) BreakByLocation(loc string) (*BreakPoint, error) {
if err != nil {
return nil, err
}
return dbp.CurrentThread.Break(addr)
return dbp.Break(addr)
}
// Clears a breakpoint in the current thread.
func (dbp *DebuggedProcess) Clear(addr uint64) (*BreakPoint, error) {
return dbp.CurrentThread.Clear(addr)
return dbp.clearBreakpoint(dbp.CurrentThread.Id, addr)
}
// Clears a breakpoint by location (function, file+line, address, breakpoint id)
@ -253,7 +183,7 @@ func (dbp *DebuggedProcess) ClearByLocation(loc string) (*BreakPoint, error) {
if err != nil {
return nil, err
}
return dbp.CurrentThread.Clear(addr)
return dbp.Clear(addr)
}
// Returns the status of the current main thread context.
@ -272,62 +202,16 @@ func (dbp *DebuggedProcess) PrintThreadInfo() error {
return nil
}
// Steps through process.
func (dbp *DebuggedProcess) Step() (err error) {
var (
th *ThreadContext
ok bool
)
allm, err := dbp.CurrentThread.AllM()
if err != nil {
return err
}
fn := func() error {
for _, m := range allm {
th, ok = dbp.Threads[m.procid]
if !ok {
th = dbp.Threads[dbp.Pid]
}
if m.blocked == 0 {
err := th.Step()
if err != nil {
return err
}
}
}
return nil
}
return dbp.run(fn)
}
// Step over function calls.
func (dbp *DebuggedProcess) Next() error {
var (
th *ThreadContext
ok bool
)
var runnable []*ThreadContext
fn := func() error {
allm, err := dbp.CurrentThread.AllM()
if err != nil {
return err
}
for _, m := range allm {
th, ok = dbp.Threads[m.procid]
if !ok {
th = dbp.Threads[dbp.Pid]
}
if m.blocked == 1 {
// Continue any blocked M so that the
// scheduler can continue to do its'
// job correctly.
for _, th := range dbp.Threads {
// Continue any blocked M so that the
// scheduler can continue to do its'
// job correctly.
if th.blocked() {
err := th.Continue()
if err != nil {
return err
@ -335,12 +219,15 @@ func (dbp *DebuggedProcess) Next() error {
continue
}
runnable = append(runnable, th)
}
for _, th := range runnable {
err := th.Next()
if err != nil && err != sys.ESRCH {
return err
}
}
return stopTheWorld(dbp)
return dbp.Halt()
}
return dbp.run(fn)
}
@ -364,6 +251,24 @@ func (dbp *DebuggedProcess) Continue() error {
return dbp.run(fn)
}
// Steps through process.
func (dbp *DebuggedProcess) Step() (err error) {
fn := func() error {
for _, th := range dbp.Threads {
if th.blocked() {
continue
}
err := th.Step()
if err != nil {
return err
}
}
return nil
}
return dbp.run(fn)
}
// Obtains register values from what Delve considers to be the current
// thread of the traced process.
func (dbp *DebuggedProcess) Registers() (Registers, error) {
@ -404,47 +309,20 @@ func (pe ProcessExitedError) Error() string {
return fmt.Sprintf("process %d has exited", pe.pid)
}
func trapWait(dbp *DebuggedProcess, pid int) (int, *sys.WaitStatus, error) {
for {
wpid, status, err := wait(pid, 0)
if err != nil {
return -1, nil, fmt.Errorf("wait err %s %d", err, pid)
}
if wpid == 0 {
continue
}
if th, ok := dbp.Threads[wpid]; ok {
th.Status = status
}
if status.Exited() && wpid == dbp.Pid {
return -1, status, ProcessExitedError{wpid}
}
if status.StopSignal() == sys.SIGTRAP && status.TrapCause() == sys.PTRACE_EVENT_CLONE {
err = addNewThread(dbp, wpid)
if err != nil {
return -1, nil, err
}
continue
}
if status.StopSignal() == sys.SIGTRAP {
return wpid, status, nil
}
if status.StopSignal() == sys.SIGSTOP && dbp.halt {
return -1, nil, ManualStopError{}
}
}
}
func handleBreakPoint(dbp *DebuggedProcess, pid int) error {
thread := dbp.Threads[pid]
thread, ok := dbp.Threads[pid]
if !ok {
return fmt.Errorf("could not find thread for %d", pid)
}
if pid != dbp.CurrentThread.Id {
fmt.Printf("thread context changed from %d to %d\n", dbp.CurrentThread.Id, pid)
fmt.Printf("thread context changed from %d to %d\n", dbp.CurrentThread.Id, thread.Id)
dbp.CurrentThread = thread
}
pc, err := thread.CurrentPC()
if err != nil {
return fmt.Errorf("could not get current pc %s", err)
return err
}
// Check to see if we hit a runtime.breakpoint
@ -457,15 +335,15 @@ func handleBreakPoint(dbp *DebuggedProcess, pid int) error {
return err
}
}
stopTheWorld(dbp)
dbp.Halt()
return nil
}
// Check for hardware breakpoint
for _, bp := range dbp.HWBreakPoints {
if bp.Addr == pc {
if bp != nil && bp.Addr == pc {
if !bp.temp {
stopTheWorld(dbp)
return dbp.Halt()
}
return nil
}
@ -473,81 +351,10 @@ func handleBreakPoint(dbp *DebuggedProcess, pid int) error {
// Check to see if we have hit a software breakpoint.
if bp, ok := dbp.BreakPoints[pc-1]; ok {
if !bp.temp {
stopTheWorld(dbp)
return dbp.Halt()
}
return nil
}
return fmt.Errorf("did not hit recognized breakpoint")
}
// Ensure execution of every traced thread is halted.
func stopTheWorld(dbp *DebuggedProcess) error {
// Loop through all threads and ensure that we
// stop the rest of them, so that by the time
// we return control to the user, all threads
// are inactive. We send SIGSTOP and ensure all
// threads are in in signal-delivery-stop mode.
for _, th := range dbp.Threads {
if stopped(th.Id) {
continue
}
err := sys.Tgkill(dbp.Pid, th.Id, sys.SIGSTOP)
if err != nil {
return err
}
pid, _, err := wait(th.Id, sys.WNOHANG)
if err != nil {
return fmt.Errorf("wait err %s %d", err, pid)
}
}
return nil
}
func addNewThread(dbp *DebuggedProcess, pid int) error {
// A traced thread has cloned a new thread, grab the pid and
// add it to our list of traced threads.
msg, err := sys.PtraceGetEventMsg(pid)
if err != nil {
return fmt.Errorf("could not get event message: %s", err)
}
fmt.Println("new thread spawned", msg)
_, err = dbp.addThread(int(msg))
if err != nil {
return err
}
err = sys.PtraceCont(int(msg), 0)
if err != nil {
return fmt.Errorf("could not continue new thread %d %s", msg, err)
}
// Here we loop for a while to ensure that the once we continue
// the newly created thread, we allow enough time for the runtime
// to assign m->procid. This is important because we rely on
// looping through runtime.allm in other parts of the code, so
// we require that this is set before we do anything else.
// TODO(dp): we might be able to eliminate this loop by telling
// the CPU to emit a breakpoint exception on write to this location
// in memory. That way we prevent having to loop, and can be
// notified as soon as m->procid is set.
th := dbp.Threads[pid]
for {
allm, _ := th.AllM()
for _, m := range allm {
if m.procid == int(msg) {
// Continue the thread that cloned
return sys.PtraceCont(pid, 0)
}
}
time.Sleep(time.Millisecond)
}
}
func wait(pid, options int) (int, *sys.WaitStatus, error) {
var status sys.WaitStatus
wpid, err := sys.Wait4(pid, &status, sys.WALL|options, nil)
return wpid, &status, err
return fmt.Errorf("unrecognized breakpoint %#v", pc)
}

204
proctl/proctl_darwin.c Normal file

@ -0,0 +1,204 @@
#include "proctl_darwin.h"
static const unsigned char info_plist[]
__attribute__ ((section ("__TEXT,__info_plist"),used)) =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\""
" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
"<plist version=\"1.0\">\n"
"<dict>\n"
" <key>CFBundleIdentifier</key>\n"
" <string>org.dlv</string>\n"
" <key>CFBundleName</key>\n"
" <string>delve</string>\n"
" <key>CFBundleVersion</key>\n"
" <string>1.0</string>\n"
" <key>SecTaskAccess</key>\n"
" <array>\n"
" <string>allowed</string>\n"
" <string>debug</string>\n"
" </array>\n"
"</dict>\n"
"</plist>\n";
static thread_act_t _global_thread;
kern_return_t
acquire_mach_task(int tid, mach_port_name_t *task, mach_port_t *exception_port) {
kern_return_t kret;
mach_port_t self = mach_task_self();
kret = task_for_pid(self, tid, task);
if (kret != KERN_SUCCESS) return kret;
kret = mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, exception_port);
if (kret != KERN_SUCCESS) return kret;
kret = mach_port_insert_right(self, *exception_port, *exception_port, MACH_MSG_TYPE_MAKE_SEND);
if (kret != KERN_SUCCESS) return kret;
// Set exception port
return task_set_exception_ports(*task, EXC_MASK_BREAKPOINT|EXC_MASK_SOFTWARE, *exception_port,
EXCEPTION_DEFAULT, THREAD_STATE_NONE);
}
char *
find_executable(int pid) {
static char pathbuf[PATH_MAX];
proc_pidpath(pid, pathbuf, PATH_MAX);
return pathbuf;
}
kern_return_t
get_threads(task_t task, void *slice) {
kern_return_t kret;
thread_act_array_t list;
mach_msg_type_number_t count;
kret = task_threads(task, &list, &count);
if (kret != KERN_SUCCESS) {
return kret;
}
memcpy(slice, (void*)list, count*sizeof(list[0]));
return (kern_return_t)0;
}
int
thread_count(task_t task) {
kern_return_t kret;
thread_act_array_t list;
mach_msg_type_number_t count;
// TODO(dp) vm_deallocate list
kret = task_threads(task, &list, &count);
if (kret != KERN_SUCCESS) return -1;
return count;
}
typedef struct exc_msg {
mach_msg_header_t Head;
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
mach_msg_port_descriptor_t task;
NDR_record_t NDR;
exception_type_t exception;
mach_msg_type_number_t codeCnt;
exception_data_t code;
char pad[512];
} exc_msg_t;
thread_act_t
mach_port_wait(mach_port_t port) {
puts("begin mach wait");
mach_msg_return_t msg = mach_msg_server_once(exc_server, sizeof(exc_msg_t), port, MACH_MSG_TIMEOUT_NONE);
if (msg != MACH_MSG_SUCCESS) {
}
puts("fin mach wait");
return _global_thread;
}
// 64 bit exception handlers
kern_return_t
catch_mach_exception_raise(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
mach_exception_data_t code,
mach_msg_type_number_t codeCnt)
{
puts("caught exception raise");
fprintf(stderr, "My exception handler was called by exception_raise()\n");
return KERN_SUCCESS;
}
kern_return_t
catch_mach_exception_raise_state(
mach_port_t exception_port,
exception_type_t exception,
const mach_exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
const thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt)
{
puts("caught raise state");
fprintf(stderr, "My exception handler was called by exception_raise()\n");
return KERN_SUCCESS;
}
kern_return_t
catch_mach_exception_raise_state_identity(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
mach_exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt)
{
puts("caught identity");
fprintf(stderr, "My exception handler was called by exception_raise()\n");
return KERN_SUCCESS;
}
// 32 bit exception handlers
kern_return_t
catch_exception_raise(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
mach_exception_data_t code,
mach_msg_type_number_t codeCnt)
{
_global_thread = (thread_act_t)thread;
thread_suspend(thread);
return KERN_SUCCESS;
}
kern_return_t
catch_exception_raise_state(
mach_port_t exception_port,
exception_type_t exception,
const mach_exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
const thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt)
{
puts("caught raise state");
fprintf(stderr, "My exception handler was called by exception_raise()\n");
return KERN_SUCCESS;
}
kern_return_t
catch_exception_raise_state_identity(
mach_port_t exception_port,
mach_port_t thread,
mach_port_t task,
exception_type_t exception,
mach_exception_data_t code,
mach_msg_type_number_t codeCnt,
int *flavor,
thread_state_t old_state,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state,
mach_msg_type_number_t *new_stateCnt)
{
puts("caught identity");
fprintf(stderr, "My exception handler was called by exception_raise()\n");
return KERN_SUCCESS;
}

223
proctl/proctl_darwin.go Normal file

@ -0,0 +1,223 @@
package proctl
// #include "proctl_darwin.h"
import "C"
import (
"debug/gosym"
"debug/macho"
"fmt"
"os"
"sync"
"unsafe"
"github.com/derekparker/delve/dwarf/frame"
sys "golang.org/x/sys/unix"
)
type OSProcessDetails struct {
task C.mach_port_name_t
exceptionPort C.mach_port_t
}
func (dbp *DebuggedProcess) Halt() (err error) {
for _, th := range dbp.Threads {
err := th.Halt()
if err != nil {
return err
}
}
return nil
}
// Finds the executable and then uses it
// to parse the following information:
// * Dwarf .debug_frame section
// * Dwarf .debug_line section
// * Go symbol table.
func (dbp *DebuggedProcess) LoadInformation() error {
var (
wg sync.WaitGroup
exe *macho.File
err error
)
if err := dbp.acquireMachTask(); err != nil {
return fmt.Errorf("could not acquire mach task")
}
exe, err = dbp.findExecutable()
if err != nil {
return err
}
data, err := exe.DWARF()
if err != nil {
return err
}
dbp.Dwarf = data
wg.Add(2)
go dbp.parseDebugFrame(exe, &wg)
go dbp.obtainGoSymbols(exe, &wg)
wg.Wait()
return nil
}
// Returns a new DebuggedProcess struct.
func newDebugProcess(pid int, attach bool) (*DebuggedProcess, error) {
dbp := DebuggedProcess{
Pid: pid,
Threads: make(map[int]*ThreadContext),
BreakPoints: make(map[uint64]*BreakPoint),
os: new(OSProcessDetails),
}
proc, err := os.FindProcess(pid)
if err != nil {
return nil, err
}
dbp.Process = proc
err = dbp.LoadInformation()
if err != nil {
return nil, err
}
if err := dbp.updateThreadList(); err != nil {
return nil, err
}
return &dbp, nil
}
func (dbp *DebuggedProcess) updateThreadList() error {
var (
err error
kret C.kern_return_t
th *ThreadContext
count = C.thread_count(C.task_t(dbp.os.task))
list = make([]uint32, count)
)
// TODO(dp) might be better to malloc mem in C and them free it here
// instead of getting count above and passing in a slice
kret = C.get_threads(C.task_t(dbp.os.task), unsafe.Pointer(&list[0]))
if kret != C.KERN_SUCCESS {
return fmt.Errorf("could not get thread list")
}
if count < 0 {
return fmt.Errorf("could not get thread list")
}
for _, port := range list {
th, err = dbp.addThread(int(port), false)
if err != nil {
return err
}
}
// TODO(dp) account for GOMAXPROCS=1 or attaching to pid
if count == 1 {
dbp.CurrentThread = th
}
return nil
}
func (dbp *DebuggedProcess) acquireMachTask() error {
if ret := C.acquire_mach_task(C.int(dbp.Pid), &dbp.os.task, &dbp.os.exceptionPort); ret != C.KERN_SUCCESS {
return fmt.Errorf("could not acquire mach task %d", ret)
}
return nil
}
// export addThread
func (dbp *DebuggedProcess) addThread(port int, attach bool) (*ThreadContext, error) {
thread := &ThreadContext{
Id: port,
Process: dbp,
os: new(OSSpecificDetails),
}
dbp.Threads[port] = thread
thread.os.thread_act = C.thread_act_t(port)
return thread, nil
}
func (dbp *DebuggedProcess) parseDebugFrame(exe *macho.File, wg *sync.WaitGroup) {
defer wg.Done()
if sec := exe.Section("__debug_frame"); sec != nil {
debugFrame, err := exe.Section("__debug_frame").Data()
if err != nil {
fmt.Println("could not get __debug_frame section", err)
os.Exit(1)
}
dbp.FrameEntries = frame.Parse(debugFrame)
} else {
fmt.Println("could not find __debug_frame section in binary")
os.Exit(1)
}
}
func (dbp *DebuggedProcess) obtainGoSymbols(exe *macho.File, wg *sync.WaitGroup) {
defer wg.Done()
var (
symdat []byte
pclndat []byte
err error
)
if sec := exe.Section("__gosymtab"); sec != nil {
symdat, err = sec.Data()
if err != nil {
fmt.Println("could not get .gosymtab section", err)
os.Exit(1)
}
}
if sec := exe.Section("__gopclntab"); sec != nil {
pclndat, err = sec.Data()
if err != nil {
fmt.Println("could not get .gopclntab section", err)
os.Exit(1)
}
}
pcln := gosym.NewLineTable(pclndat, exe.Section("__text").Addr)
tab, err := gosym.NewTable(symdat, pcln)
if err != nil {
fmt.Println("could not get initialize line table", err)
os.Exit(1)
}
dbp.GoSymTable = tab
}
// TODO(darwin) IMPLEMENT ME
func stopped(pid int) bool {
return false
}
func (dbp *DebuggedProcess) findExecutable() (*macho.File, error) {
pathptr, err := C.find_executable(C.int(dbp.Pid))
if err != nil {
return nil, err
}
return macho.Open(C.GoString(pathptr))
}
func trapWait(dbp *DebuggedProcess, pid int) (int, *sys.WaitStatus, error) {
port := C.mach_port_wait(dbp.os.exceptionPort)
if port == 0 {
return -1, nil, fmt.Errorf("mach port wait error")
}
dbp.updateThreadList()
return int(port), nil, nil
}
func wait(pid, options int) (int, *sys.WaitStatus, error) {
var status sys.WaitStatus
wpid, err := sys.Wait4(pid, &status, options, nil)
return wpid, &status, err
}

41
proctl/proctl_darwin.h Normal file

@ -0,0 +1,41 @@
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <libproc.h>
#include <mach/mach.h>
#include <mach/mach_vm.h>
#include "mach_exc.h"
#include "exc.h"
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
boolean_t exc_server(
mach_msg_header_t *InHeadP,
mach_msg_header_t *OutHeadP);
#ifdef mig_external
mig_external
#else
extern
#endif /* mig_external */
boolean_t mach_exc_server(
mach_msg_header_t *InHeadP,
mach_msg_header_t *OutHeadP);
kern_return_t
acquire_mach_task(int, mach_port_name_t *, mach_port_t *);
char *
find_executable(int pid);
kern_return_t
get_threads(task_t task, void *);
int
thread_count(task_t task);
thread_act_t
mach_port_wait(mach_port_t);

367
proctl/proctl_linux.go Normal file

@ -0,0 +1,367 @@
package proctl
import (
"debug/elf"
"debug/gosym"
"fmt"
"os"
"sync"
"syscall"
"time"
sys "golang.org/x/sys/unix"
"github.com/derekparker/delve/dwarf/frame"
)
const (
STATUS_SLEEPING = 'S'
STATUS_RUNNING = 'R'
STATUS_TRACE_STOP = 't'
)
// Not actually needed for Linux.
type OSProcessDetails interface{}
func (dbp *DebuggedProcess) Halt() (err error) {
for _, th := range dbp.Threads {
err := th.Halt()
if err != nil {
return err
}
}
return nil
}
// Steps through process.
func (dbp *DebuggedProcess) Step() (err error) {
var (
th *ThreadContext
ok bool
)
allm, err := dbp.CurrentThread.AllM()
if err != nil {
return err
}
fn := func() error {
for _, m := range allm {
th, ok = dbp.Threads[m.procid]
fmt.Println(ok, m.procid)
if !ok {
if m.procid == 0 {
// TODO(dp) might not work for linux
th = dbp.Threads[dbp.CurrentThread.Id]
}
return fmt.Errorf("m->procid is invalid port")
}
if m.blocked == 0 {
err := th.Step()
if err != nil {
return err
}
}
}
return nil
}
return dbp.run(fn)
}
// Finds the executable from /proc/<pid>/exe and then
// uses that to parse the following information:
// * Dwarf .debug_frame section
// * Dwarf .debug_line section
// * Go symbol table.
func (dbp *DebuggedProcess) LoadInformation() error {
var (
wg sync.WaitGroup
exe *elf.File
err error
)
exe, err = dbp.findExecutable()
if err != nil {
return err
}
wg.Add(2)
go dbp.parseDebugFrame(exe, &wg)
go dbp.obtainGoSymbols(exe, &wg)
wg.Wait()
return nil
}
// Attach to a newly created thread, and store that thread in our list of
// known threads.
func (dbp *DebuggedProcess) addThread(tid int, attach bool) (*ThreadContext, error) {
if thread, ok := dbp.Threads[tid]; ok {
return thread, nil
}
if attach {
err := sys.PtraceAttach(tid)
if err != nil && err != sys.EPERM {
// Do not return err if err == EPERM,
// we may already be tracing this thread due to
// PTRACE_O_TRACECLONE. We will surely blow up later
// if we truly don't have permissions.
return nil, fmt.Errorf("could not attach to new thread %d %s", tid, err)
}
pid, status, err := wait(tid, 0)
if err != nil {
return nil, err
}
if status.Exited() {
return nil, fmt.Errorf("thread already exited %d", pid)
}
}
err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE)
if err == syscall.ESRCH {
_, _, err = wait(tid, 0)
if err != nil {
return nil, fmt.Errorf("error while waiting after adding thread: %d %s", tid, err)
}
err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE)
if err != nil {
return nil, fmt.Errorf("could not set options for new traced thread %d %s", tid, err)
}
}
dbp.Threads[tid] = &ThreadContext{
Id: tid,
Process: dbp,
}
return dbp.Threads[tid], nil
}
func (dbp *DebuggedProcess) refreshThreadList() error {
allm, err := dbp.CurrentThread.AllM()
if err != nil {
return err
}
for _, m := range allm {
if tid == 0 {
continue
}
if _, err := dbp.addThread(m.procid, false); err != nil {
return err
}
}
}
func (dbp *DebuggedProcess) findExecutable() (*elf.File, error) {
procpath := fmt.Sprintf("/proc/%d/exe", dbp.Pid)
f, err := os.OpenFile(procpath, 0, os.ModePerm)
if err != nil {
return nil, err
}
elffile, err := elf.NewFile(f)
if err != nil {
return nil, err
}
data, err := elffile.DWARF()
if err != nil {
return nil, err
}
dbp.Dwarf = data
return elffile, nil
}
func (dbp *DebuggedProcess) parseDebugFrame(exe *elf.File, wg *sync.WaitGroup) {
defer wg.Done()
if sec := exe.Section(".debug_frame"); sec != nil {
debugFrame, err := exe.Section(".debug_frame").Data()
if err != nil {
fmt.Println("could not get .debug_frame section", err)
os.Exit(1)
}
dbp.FrameEntries = frame.Parse(debugFrame)
} else {
fmt.Println("could not find .debug_frame section in binary")
os.Exit(1)
}
}
func (dbp *DebuggedProcess) obtainGoSymbols(exe *elf.File, wg *sync.WaitGroup) {
defer wg.Done()
var (
symdat []byte
pclndat []byte
err error
)
if sec := exe.Section(".gosymtab"); sec != nil {
symdat, err = sec.Data()
if err != nil {
fmt.Println("could not get .gosymtab section", err)
os.Exit(1)
}
}
if sec := exe.Section(".gopclntab"); sec != nil {
pclndat, err = sec.Data()
if err != nil {
fmt.Println("could not get .gopclntab section", err)
os.Exit(1)
}
}
pcln := gosym.NewLineTable(pclndat, exe.Section(".text").Addr)
tab, err := gosym.NewTable(symdat, pcln)
if err != nil {
fmt.Println("could not get initialize line table", err)
os.Exit(1)
}
dbp.GoSymTable = tab
}
func newDebugProcess(pid int, attach bool) (*DebuggedProcess, error) {
dbp := DebuggedProcess{
Pid: pid,
Threads: make(map[int]*ThreadContext),
BreakPoints: make(map[uint64]*BreakPoint),
os: new(OSProcessDetails),
}
if attach {
thread, err := dbp.AttachThread(pid)
if err != nil {
return nil, err
}
dbp.CurrentThread = thread
} else {
thread, err := dbp.addThread(pid)
if err != nil {
return nil, err
}
dbp.CurrentThread = thread
}
proc, err := os.FindProcess(pid)
if err != nil {
return nil, err
}
dbp.Process = proc
err = dbp.LoadInformation()
if err != nil {
return nil, err
}
return &dbp, nil
}
func addNewThread(dbp *DebuggedProcess, cloner, cloned int) error {
fmt.Println("new thread spawned", cloned)
th, err := dbp.addThread(cloned)
if err != nil {
return err
}
err = th.Continue()
if err != nil {
return fmt.Errorf("could not continue new thread %d %s", cloned, err)
}
// Here we loop for a while to ensure that the once we continue
// the newly created thread, we allow enough time for the runtime
// to assign m->procid. This is important because we rely on
// looping through runtime.allm in other parts of the code, so
// we require that this is set before we do anything else.
// TODO(dp): we might be able to eliminate this loop by telling
// the CPU to emit a breakpoint exception on write to this location
// in memory. That way we prevent having to loop, and can be
// notified as soon as m->procid is set.
// TODO(dp) get rid of this hack
th = dbp.Threads[cloner]
for {
allm, _ := th.AllM()
for _, m := range allm {
if m.procid == cloned {
// Continue the thread that cloned
return th.Continue()
}
}
time.Sleep(time.Millisecond)
}
}
func stopped(pid int) bool {
f, err := os.Open(fmt.Sprintf("/proc/%d/stat", pid))
if err != nil {
return false
}
defer f.Close()
var (
p int
comm string
state rune
)
fmt.Fscanf(f, "%d %s %c", &p, &comm, &state)
if state == STATUS_TRACE_STOP {
return true
}
return false
}
func trapWait(dbp *DebuggedProcess, pid int) (int, *sys.WaitStatus, error) {
for {
wpid, status, err := wait(pid, 0)
if err != nil {
return -1, nil, fmt.Errorf("wait err %s %d", err, pid)
}
if wpid == 0 {
continue
}
if th, ok := dbp.Threads[wpid]; ok {
th.Status = status
}
if status.Exited() && wpid == dbp.Pid {
return -1, status, ProcessExitedError{wpid}
}
if status.StopSignal() == sys.SIGTRAP && status.TrapCause() == sys.PTRACE_EVENT_CLONE {
// A traced thread has cloned a new thread, grab the pid and
// add it to our list of traced threads.
tid, err := sys.PtraceGetEventMsg(wpid)
if err != nil {
return -1, nil, fmt.Errorf("could not get event message: %s", err)
}
err = addNewThread(dbp, wpid, int(tid))
if err != nil {
return -1, nil, err
}
continue
}
if status.StopSignal() == sys.SIGTRAP {
return wpid, status, nil
}
if status.StopSignal() == sys.SIGSTOP && dbp.halt {
return -1, nil, ManualStopError{}
}
}
}
func wait(pid, options int) (int, *sys.WaitStatus, error) {
var status sys.WaitStatus
wpid, err := sys.Wait4(pid, &status, sys.WALL|options, nil)
return wpid, &status, err
}

@ -1,158 +0,0 @@
package proctl
import (
"debug/elf"
"debug/gosym"
"fmt"
"os"
"sync"
"syscall"
"github.com/derekparker/delve/dwarf/frame"
)
const (
STATUS_SLEEPING = 'S'
STATUS_RUNNING = 'R'
STATUS_TRACE_STOP = 't'
)
func (dbp *DebuggedProcess) addThread(tid int) (*ThreadContext, error) {
err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE)
if err == syscall.ESRCH {
_, _, err = wait(tid, 0)
if err != nil {
return nil, fmt.Errorf("error while waiting after adding thread: %d %s", tid, err)
}
err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE)
if err != nil {
return nil, fmt.Errorf("could not set options for new traced thread %d %s", tid, err)
}
}
dbp.Threads[tid] = &ThreadContext{
Id: tid,
Process: dbp,
}
return dbp.Threads[tid], nil
}
func stopped(pid int) bool {
f, err := os.Open(fmt.Sprintf("/proc/%d/stat", pid))
if err != nil {
return false
}
defer f.Close()
var (
p int
comm string
state rune
)
fmt.Fscanf(f, "%d %s %c", &p, &comm, &state)
if state == STATUS_TRACE_STOP {
return true
}
return false
}
// Finds the executable from /proc/<pid>/exe and then
// uses that to parse the following information:
// * Dwarf .debug_frame section
// * Dwarf .debug_line section
// * Go symbol table.
func (dbp *DebuggedProcess) LoadInformation() error {
var (
wg sync.WaitGroup
exe *elf.File
err error
)
exe, err = dbp.findExecutable()
if err != nil {
return err
}
wg.Add(2)
go dbp.parseDebugFrame(exe, &wg)
go dbp.obtainGoSymbols(exe, &wg)
wg.Wait()
return nil
}
func (dbp *DebuggedProcess) findExecutable() (*elf.File, error) {
procpath := fmt.Sprintf("/proc/%d/exe", dbp.Pid)
f, err := os.OpenFile(procpath, 0, os.ModePerm)
if err != nil {
return nil, err
}
elffile, err := elf.NewFile(f)
if err != nil {
return nil, err
}
data, err := elffile.DWARF()
if err != nil {
return nil, err
}
dbp.Dwarf = data
return elffile, nil
}
func (dbp *DebuggedProcess) parseDebugFrame(exe *elf.File, wg *sync.WaitGroup) {
defer wg.Done()
if sec := exe.Section(".debug_frame"); sec != nil {
debugFrame, err := exe.Section(".debug_frame").Data()
if err != nil {
fmt.Println("could not get .debug_frame section", err)
os.Exit(1)
}
dbp.FrameEntries = frame.Parse(debugFrame)
} else {
fmt.Println("could not find .debug_frame section in binary")
os.Exit(1)
}
}
func (dbp *DebuggedProcess) obtainGoSymbols(exe *elf.File, wg *sync.WaitGroup) {
defer wg.Done()
var (
symdat []byte
pclndat []byte
err error
)
if sec := exe.Section(".gosymtab"); sec != nil {
symdat, err = sec.Data()
if err != nil {
fmt.Println("could not get .gosymtab section", err)
os.Exit(1)
}
}
if sec := exe.Section(".gopclntab"); sec != nil {
pclndat, err = sec.Data()
if err != nil {
fmt.Println("could not get .gopclntab section", err)
os.Exit(1)
}
}
pcln := gosym.NewLineTable(pclndat, exe.Section(".text").Addr)
tab, err := gosym.NewTable(symdat, pcln)
if err != nil {
fmt.Println("could not get initialize line table", err)
os.Exit(1)
}
dbp.GoSymTable = tab
}

@ -3,6 +3,7 @@ package proctl
import (
"bytes"
"encoding/binary"
"fmt"
"os"
"os/exec"
"path/filepath"
@ -37,9 +38,9 @@ func getRegisters(p *DebuggedProcess, t *testing.T) Registers {
return regs
}
func dataAtAddr(pid int, addr uint64) ([]byte, error) {
func dataAtAddr(thread *ThreadContext, addr uint64) ([]byte, error) {
data := make([]byte, 1)
_, err := readMemory(pid, uintptr(addr), data)
_, err := readMemory(thread, uintptr(addr), data)
if err != nil {
return nil, err
}
@ -78,12 +79,16 @@ func TestStep(t *testing.T) {
_, err := p.Break(helloworldaddr)
assertNoError(err, t, "Break()")
fmt.Println("continue")
assertNoError(p.Continue(), t, "Continue()")
fmt.Println("fin continue")
regs := getRegisters(p, t)
rip := regs.PC()
fmt.Println("begin step")
err = p.Step()
fmt.Println("fin step")
assertNoError(err, t, "Step()")
regs = getRegisters(p, t)
@ -110,36 +115,21 @@ func TestContinue(t *testing.T) {
func TestBreakPoint(t *testing.T) {
withTestProcess("../_fixtures/testprog", t, func(p *DebuggedProcess) {
sleepytimefunc := p.GoSymTable.LookupFunc("main.helloworld")
sleepyaddr := sleepytimefunc.Entry
helloworldfunc := p.GoSymTable.LookupFunc("main.helloworld")
helloworldaddr := helloworldfunc.Entry
bp, err := p.Break(sleepyaddr)
bp, err := p.Break(helloworldaddr)
assertNoError(err, t, "Break()")
breakpc := bp.Addr
err = p.Continue()
assertNoError(err, t, "Continue()")
assertNoError(p.Continue(), t, "Continue()")
pc, err := p.CurrentPC()
if err != nil {
t.Fatal(err)
}
if pc != breakpc {
if pc-1 != bp.Addr {
f, l, _ := p.GoSymTable.PCToLine(pc)
t.Fatalf("Break not respected:\nPC:%#v %s:%d\nFN:%#v \n", pc, f, l, breakpc)
}
err = p.Step()
assertNoError(err, t, "Step()")
pc, err = p.CurrentPC()
if err != nil {
t.Fatal(err)
}
if pc == breakpc {
t.Fatalf("Step not respected:\nPC:%d\nFN:%d\n", pc, breakpc)
t.Fatalf("Break not respected:\nPC:%#v %s:%d\nFN:%#v \n", pc, f, l, bp.Addr)
}
})
}
@ -151,6 +141,7 @@ func TestBreakPointInSeperateGoRoutine(t *testing.T) {
t.Fatal("No fn exists")
}
fmt.Printf("pid is %d set breakpoint for fn at %d\n", p.Pid, fn.Entry)
_, err := p.Break(fn.Entry)
if err != nil {
t.Fatal(err)
@ -191,7 +182,7 @@ func TestClearBreakPoint(t *testing.T) {
bp, err = p.Clear(fn.Entry)
assertNoError(err, t, "Clear()")
data, err := dataAtAddr(p.Pid, bp.Addr)
data, err := dataAtAddr(p.CurrentThread, bp.Addr)
if err != nil {
t.Fatal(err)
}
@ -249,6 +240,7 @@ func TestNext(t *testing.T) {
f, ln := currentLineNumber(p, t)
for _, tc := range testcases {
fmt.Println("BEGIN-----------------", tc.begin)
if ln != tc.begin {
t.Fatalf("Program not stopped at correct spot expected %d was %s:%d", tc.begin, f, ln)
}
@ -316,12 +308,13 @@ func TestFindReturnAddress(t *testing.T) {
addr := uint64(int64(regs.SP()) + ret)
data := make([]byte, 8)
readMemory(p.Pid, uintptr(addr), data)
readMemory(p.CurrentThread, uintptr(addr), data)
addr = binary.LittleEndian.Uint64(data)
expected := uint64(0x400fbc)
if addr != expected {
t.Fatalf("return address not found correctly, expected %#v got %#v", expected, addr)
linuxExpected := uint64(0x400fbc)
darwinExpected := uint64(0x23bc)
if addr != linuxExpected && addr != darwinExpected {
t.Fatalf("return address not found correctly, expected (linux) %#v or (darwin) %#v got %#v", linuxExpected, darwinExpected, addr)
}
})
}

23
proctl/ptrace_darwin.go Normal file

@ -0,0 +1,23 @@
package proctl
import (
"syscall"
sys "golang.org/x/sys/unix"
)
func PtraceCont(tid, sig int) error {
_, _, err := sys.Syscall6(sys.SYS_PTRACE, sys.PTRACE_CONT, uintptr(tid), 1, uintptr(sig), 0, 0)
if err != syscall.Errno(0) {
return err
}
return nil
}
func PtraceSingleStep(tid int) error {
_, _, err := sys.Syscall6(sys.SYS_PTRACE, sys.PT_STEP, uintptr(tid), 1, 0, 0, 0)
if err != syscall.Errno(0) {
return err
}
return nil
}

33
proctl/ptrace_linux.go Normal file

@ -0,0 +1,33 @@
package proctl
import (
"syscall"
"unsafe"
sys "golang.org/x/sys/unix"
)
func PtraceCont(tid, sig int) error {
return sys.PtraceCont(tid, sig)
}
func PtraceSingleStep(tid int) error {
return sys.PtraceSingleStep(tid)
}
func PtracePokeUser(tid int, off, addr uintptr) error {
_, _, err := sys.Syscall6(sys.SYS_PTRACE, sys.PTRACE_POKEUSR, uintptr(tid), uintptr(off), uintptr(addr), 0, 0)
if err != syscall.Errno(0) {
return err
}
return nil
}
func PtracePeekUser(tid int, off uintptr) (uintptr, error) {
var val uintptr
_, _, err := syscall.Syscall6(syscall.SYS_PTRACE, syscall.PTRACE_PEEKUSR, uintptr(tid), uintptr(off), uintptr(unsafe.Pointer(&val)), 0, 0)
if err != syscall.Errno(0) {
return 0, err
}
return val, nil
}

@ -0,0 +1,27 @@
package proctl
// #include "threads_darwin.h"
import "C"
type Regs struct {
pc, sp uint64
}
func (r *Regs) PC() uint64 {
return r.pc
}
func (r *Regs) SP() uint64 {
return r.sp
}
func (r *Regs) SetPC(thread *ThreadContext, pc uint64) error {
C.set_pc(thread.os.thread_act, C.uint64_t(pc))
return nil
}
func registers(thread *ThreadContext) (Registers, error) {
state := C.get_registers(C.mach_port_name_t(thread.os.thread_act))
regs := &Regs{pc: uint64(state.__rip), sp: uint64(state.__rsp)}
return regs, nil
}

@ -27,15 +27,3 @@ func registers(tid int) (Registers, error) {
}
return &Regs{&regs}, nil
}
func writeMemory(tid int, addr uintptr, data []byte) (int, error) {
return sys.PtracePokeData(tid, addr, data)
}
func readMemory(tid int, addr uintptr, data []byte) (int, error) {
return sys.PtracePeekData(tid, addr, data)
}
func clearHardwareBreakpoint(reg, tid int) error {
return setHardwareBreakpoint(reg, tid, 0)
}

@ -18,6 +18,7 @@ type ThreadContext struct {
Id int
Process *DebuggedProcess
Status *sys.WaitStatus
os *OSSpecificDetails
}
// An interface for a generic register type. The
@ -27,16 +28,15 @@ type ThreadContext struct {
type Registers interface {
PC() uint64
SP() uint64
SetPC(int, uint64) error
SetPC(*ThreadContext, uint64) error
}
// Obtains register values from the debugged process.
func (thread *ThreadContext) Registers() (Registers, error) {
regs, err := registers(thread.Id)
regs, err := registers(thread)
if err != nil {
return nil, fmt.Errorf("could not get registers %s", err)
}
return regs, nil
}
@ -46,7 +46,6 @@ func (thread *ThreadContext) CurrentPC() (uint64, error) {
if err != nil {
return 0, err
}
return regs.PC(), nil
}
@ -66,24 +65,6 @@ func (thread *ThreadContext) PrintInfo() error {
return nil
}
// Sets a breakpoint at addr, and stores it in the process wide
// break point table. Setting a break point must be thread specific due to
// ptrace actions needing the thread to be in a signal-delivery-stop.
//
// Depending on hardware support, Delve will choose to either
// set a hardware or software breakpoint. Essentially, if the
// hardware supports it, and there are free debug registers, Delve
// will set a hardware breakpoint. Otherwise we fall back to software
// breakpoints, which are a bit more work for us.
func (thread *ThreadContext) Break(addr uint64) (*BreakPoint, error) {
return thread.Process.setBreakpoint(thread.Id, addr)
}
// Clears a breakpoint, and removes it from the process level break point table.
func (thread *ThreadContext) Clear(addr uint64) (*BreakPoint, error) {
return thread.Process.clearBreakpoint(thread.Id, addr)
}
// Continue the execution of this thread. This method takes
// software breakpoints into consideration and ensures that
// we step over any breakpoints. It will restore the instruction,
@ -103,7 +84,7 @@ func (thread *ThreadContext) Continue() error {
}
}
return sys.PtraceCont(thread.Id, 0)
return thread.cont()
}
// Single steps this thread a single instruction, ensuring that
@ -117,29 +98,28 @@ func (thread *ThreadContext) Step() (err error) {
bp, ok := thread.Process.BreakPoints[regs.PC()-1]
if ok {
// Clear the breakpoint so that we can continue execution.
_, err = thread.Clear(bp.Addr)
_, err = thread.Process.Clear(bp.Addr)
if err != nil {
return err
}
// Reset program counter to our restored instruction.
err = regs.SetPC(thread.Id, bp.Addr)
err = regs.SetPC(thread, bp.Addr)
if err != nil {
return fmt.Errorf("could not set registers %s", err)
}
// Restore breakpoint now that we have passed it.
defer func() {
_, err = thread.Break(bp.Addr)
_, err = thread.Process.Break(bp.Addr)
}()
}
err = sys.PtraceSingleStep(thread.Id)
err = thread.singleStep()
if err != nil {
return fmt.Errorf("step failed: %s", err.Error())
}
_, _, err = wait(thread.Id, 0)
return err
}
@ -197,13 +177,9 @@ func (thread *ThreadContext) Next() (err error) {
func (thread *ThreadContext) continueToReturnAddress(pc uint64, fde *frame.FrameDescriptionEntry) error {
for !fde.Cover(pc) {
// Our offset here is be 0 because we
// have stepped into the first instruction
// of this function. Therefore the function
// has not had a chance to modify its' stack
// and change our offset.
// Offset is 0 because we have just stepped into this function.
addr := thread.ReturnAddressFromOffset(0)
bp, err := thread.Break(addr)
bp, err := thread.Process.Break(addr)
if err != nil {
if _, ok := err.(BreakPointExistsError); !ok {
return err
@ -218,11 +194,7 @@ func (thread *ThreadContext) continueToReturnAddress(pc uint64, fde *frame.Frame
if err != nil {
return err
}
// We wait on -1 here because once we continue this
// thread, it's very possible the scheduler could of
// change the goroutine context on us, we there is
// no guarantee that waiting on this tid will ever
// return.
// Wait on -1, just in case scheduler switches threads for this G.
wpid, _, err := trapWait(thread.Process, -1)
if err != nil {
return err
@ -230,7 +202,10 @@ func (thread *ThreadContext) continueToReturnAddress(pc uint64, fde *frame.Frame
if wpid != thread.Id {
thread = thread.Process.Threads[wpid]
}
pc, _ = thread.CurrentPC()
pc, err = thread.CurrentPC()
if err != nil {
return err
}
if (pc-1) == bp.Addr || pc == bp.Addr {
break
}
@ -250,7 +225,7 @@ func (thread *ThreadContext) ReturnAddressFromOffset(offset int64) uint64 {
retaddr := int64(regs.SP()) + offset
data := make([]byte, 8)
readMemory(thread.Id, uintptr(retaddr), data)
readMemory(thread, uintptr(retaddr), data)
return binary.LittleEndian.Uint64(data)
}
@ -259,7 +234,7 @@ func (thread *ThreadContext) clearTempBreakpoint(pc uint64) error {
if _, ok := thread.Process.BreakPoints[pc]; ok {
software = true
}
if _, err := thread.Clear(pc); err != nil {
if _, err := thread.Process.Clear(pc); err != nil {
return err
}
if software {
@ -269,7 +244,7 @@ func (thread *ThreadContext) clearTempBreakpoint(pc uint64) error {
return err
}
return regs.SetPC(thread.Id, pc)
return regs.SetPC(thread, pc)
}
return nil

115
proctl/threads_darwin.c Normal file

@ -0,0 +1,115 @@
#include "threads_darwin.h"
int
write_memory(mach_port_name_t task, mach_vm_address_t addr, void *d, mach_msg_type_number_t len) {
kern_return_t kret;
pointer_t data;
memcpy((void *)&data, d, len);
// Set permissions to enable writting to this memory location
kret = mach_vm_protect(task, addr, len, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY);
if (kret != KERN_SUCCESS) return -1;
kret = mach_vm_write((vm_map_t)task, addr, (vm_offset_t)&data, len);
if (kret != KERN_SUCCESS) return -1;
// Restore virtual memory permissions
// TODO(dp) this should take into account original permissions somehow
kret = mach_vm_protect(task, addr, len, FALSE, VM_PROT_READ | VM_PROT_EXECUTE);
if (kret != KERN_SUCCESS) return -1;
return 0;
}
int
read_memory(mach_port_name_t task, mach_vm_address_t addr, void *d, mach_msg_type_number_t len) {
kern_return_t kret;
pointer_t data;
mach_msg_type_number_t count;
kret = mach_vm_read((vm_map_t)task, addr, len, &data, &count);
if (kret != KERN_SUCCESS) return -1;
// TODO(dp) possible memory leak - vm_deallocate data
memcpy(d, (void *)data, len);
return count;
}
x86_thread_state64_t
get_registers(mach_port_name_t task) {
kern_return_t kret;
x86_thread_state64_t state;
mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT;
// TODO(dp) - possible memory leak - vm_deallocate state
kret = thread_get_state(task, x86_THREAD_STATE64, (thread_state_t)&state, &stateCount);
if (kret != KERN_SUCCESS) printf("SOMETHING WENT WRONG-------------- %d\n", kret);
if (kret == KERN_INVALID_ARGUMENT) puts("INAVLID ARGUMENT");
return state;
}
// TODO(dp) this should return kret instead of void
void
set_pc(thread_act_t task, uint64_t pc) {
kern_return_t kret;
x86_thread_state64_t state;
mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT;
kret = thread_get_state(task, x86_THREAD_STATE64, (thread_state_t)&state, &stateCount);
if (kret != KERN_SUCCESS) puts(mach_error_string(kret));
state.__rip = pc;
kret = thread_set_state(task, x86_THREAD_STATE64, (thread_state_t)&state, stateCount);
if (kret != KERN_SUCCESS) puts(mach_error_string(kret));
// TODO(dp) - possible memory leak - vm_deallocate state
}
// TODO(dp) this should return kret instead of void
void
single_step(thread_act_t thread) {
kern_return_t kret;
x86_thread_state64_t regs;
mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
kret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)&regs, &count);
if (kret != KERN_SUCCESS) {
puts("get state fail");
puts(mach_error_string(kret));
}
// Set trap bit in rflags
regs.__rflags |= 0x100UL;
kret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)&regs, count);
if (kret != KERN_SUCCESS) {
puts("set state fail");
puts(mach_error_string(kret));
}
// TODO(dp) vm deallocate state?
// Continue here until we've fully decremented suspend_count
for (;;) {
kret = thread_resume(thread);
if (kret != KERN_SUCCESS) break;
}
}
void
clear_trap_flag(thread_act_t thread) {
kern_return_t kret;
x86_thread_state64_t regs;
mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
kret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)&regs, &count);
if (kret != KERN_SUCCESS) {
puts("get state fail");
puts(mach_error_string(kret));
}
// Clear trap bit in rflags
regs.__rflags ^= 0x100UL;
kret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)&regs, count);
if (kret != KERN_SUCCESS) {
puts("set state fail");
puts(mach_error_string(kret));
}
// TODO(dp) vm deallocate state?
}

81
proctl/threads_darwin.go Normal file

@ -0,0 +1,81 @@
package proctl
// #include "threads_darwin.h"
import "C"
import (
"fmt"
"unsafe"
)
type OSSpecificDetails struct {
thread_act C.thread_act_t
}
func (t *ThreadContext) Halt() error {
// TODO(dp) may be able to just task_suspend instead of suspending individual threads
var kret C.kern_return_t
kret = C.thread_suspend(t.os.thread_act)
if kret != C.KERN_SUCCESS {
return fmt.Errorf("could not suspend task %d", t.Id)
}
return nil
}
func (t *ThreadContext) singleStep() error {
C.single_step(t.os.thread_act)
trapWait(t.Process, 0)
C.clear_trap_flag(t.os.thread_act)
return nil
}
func (t *ThreadContext) cont() error {
// debug.PrintStack()
// TODO(dp) set flag for ptrace stops
if err := PtraceCont(t.Process.Pid, 0); err == nil {
return nil
}
for {
if C.thread_resume(t.os.thread_act) != C.KERN_SUCCESS {
break
}
}
return nil
}
func (t *ThreadContext) blocked() bool {
// TODO(dp) cache the func pc to remove this lookup
// TODO(dp) check err
pc, _ := t.CurrentPC()
fn := t.Process.GoSymTable.PCToFunc(pc)
if fn != nil && ((fn.Name == "runtime.mach_semaphore_wait") || (fn.Name == "runtime.usleep")) {
return true
}
return false
}
func writeMemory(thread *ThreadContext, addr uintptr, data []byte) (int, error) {
var (
vm_data = unsafe.Pointer(&data[0])
vm_addr = C.mach_vm_address_t(addr)
length = C.mach_msg_type_number_t(len(data))
)
if ret := C.write_memory(thread.Process.os.task, vm_addr, vm_data, length); ret < 0 {
return 0, fmt.Errorf("could not write memory")
}
return len(data), nil
}
func readMemory(thread *ThreadContext, addr uintptr, data []byte) (int, error) {
var (
vm_data = unsafe.Pointer(&data[0])
vm_addr = C.mach_vm_address_t(addr)
length = C.mach_msg_type_number_t(len(data))
)
ret := C.read_memory(thread.Process.os.task, vm_addr, vm_data, length)
if ret < 0 {
return 0, fmt.Errorf("could not read memory")
}
return len(data), nil
}

23
proctl/threads_darwin.h Normal file

@ -0,0 +1,23 @@
#include <stdio.h>
#include <sys/types.h>
#include <mach/mach.h>
#include <mach/mach_vm.h>
#include <mach/thread_info.h>
int
write_memory(mach_port_name_t, mach_vm_address_t, void *, mach_msg_type_number_t);
int
read_memory(mach_port_name_t, mach_vm_address_t, void *, mach_msg_type_number_t);
x86_thread_state64_t
get_registers(mach_port_name_t);
void
set_pc(thread_act_t, uint64_t);
void
single_step(thread_act_t);
void
clear_trap_flag(thread_act_t thread);

47
proctl/threads_linux.go Normal file

@ -0,0 +1,47 @@
package proctl
import (
"fmt"
sys "golang.org/x/sys/unix"
)
// Not actually used, but necessary
// to be defined.
type OSSpecificDetails interface{}
func (t *ThreadContext) Halt() error {
if stopped(t.Id) {
return nil
}
err := sys.Tgkill(t.Process.Pid, t.Id, sys.SIGSTOP)
if err != nil {
return fmt.Errorf("Halt err %s %d", err, pid)
}
pid, _, err := wait(th.Id, sys.WNOHANG)
if err != nil {
return fmt.Errorf("wait err %s %d", err, pid)
}
return nil
}
func (t *ThreadContext) cont() error {
return PtraceCont(thread.Id, 0)
}
func (t *ThreadContext) singleStep() error {
err := sys.PtraceSingleStep(t.Id)
if err != nill {
return err
}
_, _, err = wait(thread.Id, 0)
return err
}
func writeMemory(tid int, addr uintptr, data []byte) (int, error) {
return sys.PtracePokeData(tid, addr, data)
}
func readMemory(tid int, addr uintptr, data []byte) (int, error) {
return sys.PtracePeekData(tid, addr, data)
}

@ -912,7 +912,7 @@ func (thread *ThreadContext) readFunctionPtr(addr uintptr) (string, error) {
func (thread *ThreadContext) readMemory(addr uintptr, size uintptr) ([]byte, error) {
buf := make([]byte, size)
_, err := readMemory(thread.Id, addr, buf)
_, err := readMemory(thread, addr, buf)
if err != nil {
return nil, err
}

4
test_darwin Executable file

@ -0,0 +1,4 @@
#!/bin/sh
go test -c && codesign -s dbg-cert ./proctl.test && ./proctl.test -test.v -test.run "$1"
rm ./proctl.test