From 2d2d70641ec67593d09ee8264072fb0d11a11317 Mon Sep 17 00:00:00 2001 From: Derek Parker Date: Tue, 13 Jan 2015 20:37:10 -0600 Subject: [PATCH] (Mostly) working on OS X --- _fixtures/testprog.go | 5 + dwarf/frame/entries.go | 40 +- dwarf/frame/entries_test.go | 2 +- proctl/breakpoints.go | 132 +++ proctl/breakpoints_darwin_amd64.go | 13 + proctl/breakpoints_linux_amd64.go | 149 +--- proctl/exc.defs | 119 +++ proctl/exc.h | 283 +++++++ proctl/excServer.c | 766 +++++++++++++++++ proctl/excUser.c | 768 +++++++++++++++++ proctl/mach_exc.defs | 119 +++ proctl/mach_exc.h | 283 +++++++ proctl/mach_excServer.c | 771 ++++++++++++++++++ proctl/mach_excUser.c | 768 +++++++++++++++++ proctl/proctl.go | 303 ++----- proctl/proctl_darwin.c | 204 +++++ proctl/proctl_darwin.go | 223 +++++ proctl/proctl_darwin.h | 41 + proctl/proctl_linux.go | 367 +++++++++ proctl/proctl_linux_amd64.go | 158 ---- proctl/proctl_test.go | 49 +- proctl/ptrace_darwin.go | 23 + proctl/ptrace_linux.go | 33 + proctl/registers_darwin_amd64.go | 27 + ...inux_amd64.go => registers_linux_amd64.go} | 12 - proctl/threads.go | 61 +- proctl/threads_darwin.c | 115 +++ proctl/threads_darwin.go | 81 ++ proctl/threads_darwin.h | 23 + proctl/threads_linux.go | 47 ++ proctl/variables.go | 2 +- test_darwin | 4 + 32 files changed, 5337 insertions(+), 654 deletions(-) create mode 100644 proctl/breakpoints.go create mode 100644 proctl/breakpoints_darwin_amd64.go create mode 100644 proctl/exc.defs create mode 100644 proctl/exc.h create mode 100644 proctl/excServer.c create mode 100644 proctl/excUser.c create mode 100644 proctl/mach_exc.defs create mode 100644 proctl/mach_exc.h create mode 100644 proctl/mach_excServer.c create mode 100644 proctl/mach_excUser.c create mode 100644 proctl/proctl_darwin.c create mode 100644 proctl/proctl_darwin.go create mode 100644 proctl/proctl_darwin.h create mode 100644 proctl/proctl_linux.go delete mode 100644 proctl/proctl_linux_amd64.go create mode 100644 proctl/ptrace_darwin.go create mode 100644 proctl/ptrace_linux.go create mode 100644 proctl/registers_darwin_amd64.go rename proctl/{threads_linux_amd64.go => registers_linux_amd64.go} (59%) create mode 100644 proctl/threads_darwin.c create mode 100644 proctl/threads_darwin.go create mode 100644 proctl/threads_darwin.h create mode 100644 proctl/threads_linux.go create mode 100755 test_darwin diff --git a/_fixtures/testprog.go b/_fixtures/testprog.go index ebb49163..5715241c 100644 --- a/_fixtures/testprog.go +++ b/_fixtures/testprog.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "runtime" "time" ) @@ -19,3 +20,7 @@ func main() { helloworld() } } + +func init() { + runtime.LockOSThread() +} diff --git a/dwarf/frame/entries.go b/dwarf/frame/entries.go index e7081d8f..0abaac76 100644 --- a/dwarf/frame/entries.go +++ b/dwarf/frame/entries.go @@ -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 - } - 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) + }) + if idx == len(fdes) { + return nil, fmt.Errorf("could not find FDE for PC %#v", pc) } - return nil + fmt.Println("fin") + return fdes[idx], nil } func (frame *FrameDescriptionEntry) Less(pc uint64) bool { diff --git a/dwarf/frame/entries_test.go b/dwarf/frame/entries_test.go index 7440133e..68250e1c 100644 --- a/dwarf/frame/entries_test.go +++ b/dwarf/frame/entries_test.go @@ -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 { diff --git a/proctl/breakpoints.go b/proctl/breakpoints.go new file mode 100644 index 00000000..e9912188 --- /dev/null +++ b/proctl/breakpoints.go @@ -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) +} diff --git a/proctl/breakpoints_darwin_amd64.go b/proctl/breakpoints_darwin_amd64.go new file mode 100644 index 00000000..c5f7a6da --- /dev/null +++ b/proctl/breakpoints_darwin_amd64.go @@ -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") +} diff --git a/proctl/breakpoints_linux_amd64.go b/proctl/breakpoints_linux_amd64.go index 2b972aa3..7f42c027 100644 --- a/proctl/breakpoints_linux_amd64.go +++ b/proctl/breakpoints_linux_amd64.go @@ -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) +} diff --git a/proctl/exc.defs b/proctl/exc.defs new file mode 100644 index 00000000..de6aee7b --- /dev/null +++ b/proctl/exc.defs @@ -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 +#include + +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 : */ diff --git a/proctl/exc.h b/proctl/exc.h new file mode 100644 index 00000000..c5c43869 --- /dev/null +++ b/proctl/exc.h @@ -0,0 +1,283 @@ +#ifndef _exc_user_ +#define _exc_user_ + +/* Module exc */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BEGIN VOUCHER CODE */ + +#ifndef KERNEL +#if defined(__has_include) +#if __has_include() +#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() +#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 +#include +#include +#include + +#ifdef __BeforeMigUserHeader +__BeforeMigUserHeader +#endif /* __BeforeMigUserHeader */ + +#include +__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_ */ diff --git a/proctl/excServer.c b/proctl/excServer.c new file mode 100644 index 00000000..27e71f2c --- /dev/null +++ b/proctl/excServer.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* BEGIN VOUCHER CODE */ + +#ifndef KERNEL +#if defined(__has_include) +#if __has_include() +#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() +#endif // __has_include +#endif // !KERNEL + +/* END VOUCHER CODE */ + + +#include +#include +#include +#include + +#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; +} diff --git a/proctl/excUser.c b/proctl/excUser.c new file mode 100644 index 00000000..bd2e6896 --- /dev/null +++ b/proctl/excUser.c @@ -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; +} diff --git a/proctl/mach_exc.defs b/proctl/mach_exc.defs new file mode 100644 index 00000000..00fae285 --- /dev/null +++ b/proctl/mach_exc.defs @@ -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 +#include + +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 : */ diff --git a/proctl/mach_exc.h b/proctl/mach_exc.h new file mode 100644 index 00000000..b5f6dfcb --- /dev/null +++ b/proctl/mach_exc.h @@ -0,0 +1,283 @@ +#ifndef _mach_exc_user_ +#define _mach_exc_user_ + +/* Module mach_exc */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BEGIN VOUCHER CODE */ + +#ifndef KERNEL +#if defined(__has_include) +#if __has_include() +#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() +#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 +#include +#include +#include + +#ifdef __BeforeMigUserHeader +__BeforeMigUserHeader +#endif /* __BeforeMigUserHeader */ + +#include +__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_ */ diff --git a/proctl/mach_excServer.c b/proctl/mach_excServer.c new file mode 100644 index 00000000..ab487186 --- /dev/null +++ b/proctl/mach_excServer.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BEGIN VOUCHER CODE */ + +#ifndef KERNEL +#if defined(__has_include) +#if __has_include() +#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() +#endif // __has_include +#endif // !KERNEL + +/* END VOUCHER CODE */ + + +#include +#include +#include +#include + +#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; +} diff --git a/proctl/mach_excUser.c b/proctl/mach_excUser.c new file mode 100644 index 00000000..e4758087 --- /dev/null +++ b/proctl/mach_excUser.c @@ -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; +} diff --git a/proctl/proctl.go b/proctl/proctl.go index 72a42b4d..057cb733 100644 --- a/proctl/proctl.go +++ b/proctl/proctl.go @@ -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, ok := dbp.Threads[pid] + if !ok { + return fmt.Errorf("could not find thread for %d", pid) } -} -func handleBreakPoint(dbp *DebuggedProcess, pid int) error { - thread := dbp.Threads[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) } diff --git a/proctl/proctl_darwin.c b/proctl/proctl_darwin.c new file mode 100644 index 00000000..a1772567 --- /dev/null +++ b/proctl/proctl_darwin.c @@ -0,0 +1,204 @@ +#include "proctl_darwin.h" + + +static const unsigned char info_plist[] +__attribute__ ((section ("__TEXT,__info_plist"),used)) = + "\n" + "\n" + "\n" + "\n" + " CFBundleIdentifier\n" + " org.dlv\n" + " CFBundleName\n" + " delve\n" + " CFBundleVersion\n" + " 1.0\n" + " SecTaskAccess\n" + " \n" + " allowed\n" + " debug\n" + " \n" + "\n" + "\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; +} diff --git a/proctl/proctl_darwin.go b/proctl/proctl_darwin.go new file mode 100644 index 00000000..f6c39b61 --- /dev/null +++ b/proctl/proctl_darwin.go @@ -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 +} diff --git a/proctl/proctl_darwin.h b/proctl/proctl_darwin.h new file mode 100644 index 00000000..0a359800 --- /dev/null +++ b/proctl/proctl_darwin.h @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#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); diff --git a/proctl/proctl_linux.go b/proctl/proctl_linux.go new file mode 100644 index 00000000..267587b7 --- /dev/null +++ b/proctl/proctl_linux.go @@ -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//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 +} diff --git a/proctl/proctl_linux_amd64.go b/proctl/proctl_linux_amd64.go deleted file mode 100644 index bd5ebf65..00000000 --- a/proctl/proctl_linux_amd64.go +++ /dev/null @@ -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//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 -} diff --git a/proctl/proctl_test.go b/proctl/proctl_test.go index 42f5746e..b178201a 100644 --- a/proctl/proctl_test.go +++ b/proctl/proctl_test.go @@ -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) } }) } diff --git a/proctl/ptrace_darwin.go b/proctl/ptrace_darwin.go new file mode 100644 index 00000000..ff09541b --- /dev/null +++ b/proctl/ptrace_darwin.go @@ -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 +} diff --git a/proctl/ptrace_linux.go b/proctl/ptrace_linux.go new file mode 100644 index 00000000..09334859 --- /dev/null +++ b/proctl/ptrace_linux.go @@ -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 +} diff --git a/proctl/registers_darwin_amd64.go b/proctl/registers_darwin_amd64.go new file mode 100644 index 00000000..616f9033 --- /dev/null +++ b/proctl/registers_darwin_amd64.go @@ -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 +} diff --git a/proctl/threads_linux_amd64.go b/proctl/registers_linux_amd64.go similarity index 59% rename from proctl/threads_linux_amd64.go rename to proctl/registers_linux_amd64.go index a508d934..ddb5f0da 100644 --- a/proctl/threads_linux_amd64.go +++ b/proctl/registers_linux_amd64.go @@ -27,15 +27,3 @@ func registers(tid int) (Registers, error) { } return &Regs{®s}, 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) -} diff --git a/proctl/threads.go b/proctl/threads.go index 117437b7..0cd66f08 100644 --- a/proctl/threads.go +++ b/proctl/threads.go @@ -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 diff --git a/proctl/threads_darwin.c b/proctl/threads_darwin.c new file mode 100644 index 00000000..b3c650cc --- /dev/null +++ b/proctl/threads_darwin.c @@ -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)®s, &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)®s, 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)®s, &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)®s, count); + if (kret != KERN_SUCCESS) { + puts("set state fail"); + puts(mach_error_string(kret)); + } + // TODO(dp) vm deallocate state? +} diff --git a/proctl/threads_darwin.go b/proctl/threads_darwin.go new file mode 100644 index 00000000..1f7f827d --- /dev/null +++ b/proctl/threads_darwin.go @@ -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 +} diff --git a/proctl/threads_darwin.h b/proctl/threads_darwin.h new file mode 100644 index 00000000..c0ce604f --- /dev/null +++ b/proctl/threads_darwin.h @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include + +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); diff --git a/proctl/threads_linux.go b/proctl/threads_linux.go new file mode 100644 index 00000000..5f356d00 --- /dev/null +++ b/proctl/threads_linux.go @@ -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) +} diff --git a/proctl/variables.go b/proctl/variables.go index 887f21dc..a5b60216 100644 --- a/proctl/variables.go +++ b/proctl/variables.go @@ -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 } diff --git a/test_darwin b/test_darwin new file mode 100755 index 00000000..a0c2ee9b --- /dev/null +++ b/test_darwin @@ -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 -- GitLab