(Mostly) working on OS X
This commit is contained in:
parent
533a534560
commit
2d2d70641e
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -19,3 +20,7 @@ func main() {
|
||||
helloworld()
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package frame
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Represents a Common Information Entry in
|
||||
// the Dwarf .debug_frame section.
|
||||
@ -55,29 +58,22 @@ func NewFrameIndex() FrameDescriptionEntries {
|
||||
}
|
||||
|
||||
func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) {
|
||||
frame := find(fdes, pc)
|
||||
if frame == nil {
|
||||
return nil, fmt.Errorf("could not find FDE for %#v", pc)
|
||||
}
|
||||
return frame, nil
|
||||
}
|
||||
fmt.Println("fdes for pc")
|
||||
idx := sort.Search(len(fdes), func(i int) bool {
|
||||
if fdes[i].Cover(pc) {
|
||||
return true
|
||||
}
|
||||
if fdes[i].More(pc) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
func find(fdes FrameDescriptionEntries, pc uint64) *FrameDescriptionEntry {
|
||||
if len(fdes) == 0 {
|
||||
return nil
|
||||
})
|
||||
if idx == len(fdes) {
|
||||
return nil, fmt.Errorf("could not find FDE for PC %#v", pc)
|
||||
}
|
||||
idx := len(fdes) / 2
|
||||
frame := fdes[idx]
|
||||
if frame.Cover(pc) {
|
||||
return frame
|
||||
}
|
||||
if frame.Less(pc) {
|
||||
return find(fdes[:idx], pc)
|
||||
}
|
||||
if frame.More(pc) {
|
||||
return find(fdes[idx:], pc)
|
||||
}
|
||||
return nil
|
||||
fmt.Println("fin")
|
||||
return fdes[idx], nil
|
||||
}
|
||||
|
||||
func (frame *FrameDescriptionEntry) Less(pc uint64) bool {
|
||||
|
@ -20,7 +20,7 @@ func TestFDEForPC(t *testing.T) {
|
||||
|
||||
node, err := frames.FDEForPC(35)
|
||||
if err != nil {
|
||||
t.Fatal("Could not find FDE")
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if node != fde1 {
|
||||
|
132
proctl/breakpoints.go
Normal file
132
proctl/breakpoints.go
Normal file
@ -0,0 +1,132 @@
|
||||
package proctl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// Represents a single breakpoint. Stores information on the break
|
||||
// point including the byte of data that originally was stored at that
|
||||
// address.
|
||||
type BreakPoint struct {
|
||||
FunctionName string
|
||||
File string
|
||||
Line int
|
||||
Addr uint64
|
||||
OriginalData []byte
|
||||
ID int
|
||||
temp bool
|
||||
}
|
||||
|
||||
// Returned when trying to set a breakpoint at
|
||||
// an address that already has a breakpoint set for it.
|
||||
type BreakPointExistsError struct {
|
||||
file string
|
||||
line int
|
||||
addr uint64
|
||||
}
|
||||
|
||||
func (bpe BreakPointExistsError) Error() string {
|
||||
return fmt.Sprintf("Breakpoint exists at %s:%d at %x", bpe.file, bpe.line, bpe.addr)
|
||||
}
|
||||
|
||||
// InvalidAddressError represents the result of
|
||||
// attempting to set a breakpoint at an invalid address.
|
||||
type InvalidAddressError struct {
|
||||
address uint64
|
||||
}
|
||||
|
||||
func (iae InvalidAddressError) Error() string {
|
||||
return fmt.Sprintf("Invalid address %#v\n", iae.address)
|
||||
}
|
||||
|
||||
// Returns whether or not a breakpoint has been set for the given address.
|
||||
func (dbp *DebuggedProcess) BreakpointExists(addr uint64) bool {
|
||||
for _, bp := range dbp.HWBreakPoints {
|
||||
// TODO(darwin)
|
||||
if runtime.GOOS == "darwin" {
|
||||
break
|
||||
}
|
||||
if bp != nil && bp.Addr == addr {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if _, ok := dbp.BreakPoints[addr]; ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) newBreakpoint(fn, f string, l int, addr uint64, data []byte) *BreakPoint {
|
||||
dbp.breakpointIDCounter++
|
||||
return &BreakPoint{
|
||||
FunctionName: fn,
|
||||
File: f,
|
||||
Line: l,
|
||||
Addr: addr,
|
||||
OriginalData: data,
|
||||
ID: dbp.breakpointIDCounter,
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) setBreakpoint(tid int, addr uint64) (*BreakPoint, error) {
|
||||
var f, l, fn = dbp.GoSymTable.PCToLine(uint64(addr))
|
||||
if fn == nil {
|
||||
return nil, InvalidAddressError{address: addr}
|
||||
}
|
||||
if dbp.BreakpointExists(addr) {
|
||||
return nil, BreakPointExistsError{f, l, addr}
|
||||
}
|
||||
// Try and set a hardware breakpoint.
|
||||
for i, v := range dbp.HWBreakPoints {
|
||||
// TODO(darwin)
|
||||
if runtime.GOOS == "darwin" {
|
||||
break
|
||||
}
|
||||
if v == nil {
|
||||
if err := setHardwareBreakpoint(i, tid, addr); err != nil {
|
||||
return nil, fmt.Errorf("could not set hardware breakpoint: %v", err)
|
||||
}
|
||||
dbp.HWBreakPoints[i] = dbp.newBreakpoint(fn.Name, f, l, addr, nil)
|
||||
return dbp.HWBreakPoints[i], nil
|
||||
}
|
||||
}
|
||||
// Fall back to software breakpoint. 0xCC is INT 3, software
|
||||
// breakpoint trap interrupt.
|
||||
thread := dbp.Threads[tid]
|
||||
originalData := make([]byte, 1)
|
||||
if _, err := readMemory(thread, uintptr(addr), originalData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := writeMemory(thread, uintptr(addr), []byte{0xCC}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dbp.BreakPoints[addr] = dbp.newBreakpoint(fn.Name, f, l, addr, originalData)
|
||||
return dbp.BreakPoints[addr], nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) clearBreakpoint(tid int, addr uint64) (*BreakPoint, error) {
|
||||
// Check for hardware breakpoint
|
||||
for i, bp := range dbp.HWBreakPoints {
|
||||
if bp == nil {
|
||||
continue
|
||||
}
|
||||
if bp.Addr == addr {
|
||||
dbp.HWBreakPoints[i] = nil
|
||||
if err := clearHardwareBreakpoint(i, tid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bp, nil
|
||||
}
|
||||
}
|
||||
// Check for software breakpoint
|
||||
if bp, ok := dbp.BreakPoints[addr]; ok {
|
||||
thread := dbp.Threads[tid]
|
||||
if _, err := writeMemory(thread, uintptr(bp.Addr), bp.OriginalData); err != nil {
|
||||
return nil, fmt.Errorf("could not clear breakpoint %s", err)
|
||||
}
|
||||
delete(dbp.BreakPoints, addr)
|
||||
return bp, nil
|
||||
}
|
||||
return nil, fmt.Errorf("No breakpoint currently set for %#v", addr)
|
||||
}
|
13
proctl/breakpoints_darwin_amd64.go
Normal file
13
proctl/breakpoints_darwin_amd64.go
Normal file
@ -0,0 +1,13 @@
|
||||
package proctl
|
||||
|
||||
import "fmt"
|
||||
|
||||
// TODO(darwin)
|
||||
func setHardwareBreakpoint(reg, tid int, addr uint64) error {
|
||||
return fmt.Errorf("not implemented on darwin")
|
||||
}
|
||||
|
||||
// TODO(darwin)
|
||||
func clearHardwareBreakpoint(reg, tid int) error {
|
||||
return fmt.Errorf("not implemented on darwin")
|
||||
}
|
@ -15,147 +15,7 @@ int offset(int reg) {
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
sys "golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Represents a single breakpoint. Stores information on the break
|
||||
// point including the byte of data that originally was stored at that
|
||||
// address.
|
||||
type BreakPoint struct {
|
||||
FunctionName string
|
||||
File string
|
||||
Line int
|
||||
Addr uint64
|
||||
OriginalData []byte
|
||||
ID int
|
||||
temp bool
|
||||
}
|
||||
|
||||
// Returned when trying to set a breakpoint at
|
||||
// an address that already has a breakpoint set for it.
|
||||
type BreakPointExistsError struct {
|
||||
file string
|
||||
line int
|
||||
addr uint64
|
||||
}
|
||||
|
||||
func (bpe BreakPointExistsError) Error() string {
|
||||
return fmt.Sprintf("Breakpoint exists at %s:%d at %x", bpe.file, bpe.line, bpe.addr)
|
||||
}
|
||||
|
||||
// InvalidAddressError represents the result of
|
||||
// attempting to set a breakpoint at an invalid address.
|
||||
type InvalidAddressError struct {
|
||||
address uint64
|
||||
}
|
||||
|
||||
func (iae InvalidAddressError) Error() string {
|
||||
return fmt.Sprintf("Invalid address %#v\n", iae.address)
|
||||
}
|
||||
|
||||
func PtracePokeUser(tid int, off, addr uintptr) error {
|
||||
_, _, err := sys.Syscall6(sys.SYS_PTRACE, sys.PTRACE_POKEUSR, uintptr(tid), uintptr(off), uintptr(addr), 0, 0)
|
||||
if err != syscall.Errno(0) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func PtracePeekUser(tid int, off uintptr) (uintptr, error) {
|
||||
var val uintptr
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_PTRACE, syscall.PTRACE_PEEKUSR, uintptr(tid), uintptr(off), uintptr(unsafe.Pointer(&val)), 0, 0)
|
||||
if err != syscall.Errno(0) {
|
||||
return 0, err
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// Returns whether or not a breakpoint has been set for the given address.
|
||||
func (dbp *DebuggedProcess) BreakpointExists(addr uint64) bool {
|
||||
for _, bp := range dbp.HWBreakPoints {
|
||||
if bp != nil && bp.Addr == addr {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if _, ok := dbp.BreakPoints[addr]; ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) setBreakpoint(tid int, addr uint64) (*BreakPoint, error) {
|
||||
var f, l, fn = dbp.GoSymTable.PCToLine(uint64(addr))
|
||||
if fn == nil {
|
||||
return nil, InvalidAddressError{address: addr}
|
||||
}
|
||||
if dbp.BreakpointExists(addr) {
|
||||
return nil, BreakPointExistsError{f, l, addr}
|
||||
}
|
||||
// Try and set a hardware breakpoint.
|
||||
for i, v := range dbp.HWBreakPoints {
|
||||
if v == nil {
|
||||
if err := setHardwareBreakpoint(i, tid, addr); err != nil {
|
||||
return nil, fmt.Errorf("could not set hardware breakpoint: %v", err)
|
||||
}
|
||||
dbp.HWBreakPoints[i] = dbp.newBreakpoint(fn.Name, f, l, addr, nil)
|
||||
return dbp.HWBreakPoints[i], nil
|
||||
}
|
||||
}
|
||||
// Fall back to software breakpoint. 0xCC is INT 3, software
|
||||
// breakpoint trap interrupt.
|
||||
originalData := make([]byte, 1)
|
||||
if _, err := readMemory(tid, uintptr(addr), originalData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err := writeMemory(tid, uintptr(addr), []byte{0xCC})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dbp.BreakPoints[addr] = dbp.newBreakpoint(fn.Name, f, l, addr, originalData)
|
||||
return dbp.BreakPoints[addr], nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) clearBreakpoint(tid int, addr uint64) (*BreakPoint, error) {
|
||||
// Check for hardware breakpoint
|
||||
for i, bp := range dbp.HWBreakPoints {
|
||||
if bp == nil {
|
||||
continue
|
||||
}
|
||||
if bp.Addr == addr {
|
||||
dbp.HWBreakPoints[i] = nil
|
||||
if err := clearHardwareBreakpoint(i, tid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bp, nil
|
||||
}
|
||||
}
|
||||
// Check for software breakpoint
|
||||
if bp, ok := dbp.BreakPoints[addr]; ok {
|
||||
if _, err := writeMemory(tid, uintptr(bp.Addr), bp.OriginalData); err != nil {
|
||||
return nil, fmt.Errorf("could not clear breakpoint %s", err)
|
||||
}
|
||||
delete(dbp.BreakPoints, addr)
|
||||
return bp, nil
|
||||
}
|
||||
return nil, fmt.Errorf("No breakpoint currently set for %#v", addr)
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) newBreakpoint(fn, f string, l int, addr uint64, data []byte) *BreakPoint {
|
||||
dbp.breakpointIDCounter++
|
||||
return &BreakPoint{
|
||||
FunctionName: fn,
|
||||
File: f,
|
||||
Line: l,
|
||||
Addr: addr,
|
||||
OriginalData: data,
|
||||
ID: dbp.breakpointIDCounter,
|
||||
}
|
||||
}
|
||||
import "fmt"
|
||||
|
||||
// Sets a hardware breakpoint by setting the contents of the
|
||||
// debug register `reg` with the address of the instruction
|
||||
@ -208,3 +68,10 @@ func setHardwareBreakpoint(reg, tid int, addr uint64) error {
|
||||
// an instruction stored in dr0-dr3.
|
||||
return PtracePokeUser(tid, dr7off, dr7)
|
||||
}
|
||||
|
||||
// Clears a hardware breakpoint. Essentially sets
|
||||
// the debug reg to 0 and clears the control register
|
||||
// flags for that reg.
|
||||
func clearHardwareBreakpoint(reg, tid int) error {
|
||||
return setHardwareBreakpoint(reg, tid, 0)
|
||||
}
|
||||
|
119
proctl/exc.defs
Normal file
119
proctl/exc.defs
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
/*
|
||||
* @OSF_COPYRIGHT@
|
||||
*/
|
||||
/*
|
||||
* Mach Operating System
|
||||
* Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify and distribute this software and its
|
||||
* documentation is hereby granted, provided that both the copyright
|
||||
* notice and this permission notice appear in all copies of the
|
||||
* software, derivative works or modified versions, and any portions
|
||||
* thereof, and that both notices appear in supporting documentation.
|
||||
*
|
||||
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
||||
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
|
||||
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
||||
*
|
||||
* Carnegie Mellon requests users of this software to return to
|
||||
*
|
||||
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
|
||||
* School of Computer Science
|
||||
* Carnegie Mellon University
|
||||
* Pittsburgh PA 15213-3890
|
||||
*
|
||||
* any improvements or extensions that they make and grant Carnegie Mellon
|
||||
* the rights to redistribute these changes.
|
||||
*/
|
||||
/*
|
||||
*/
|
||||
/*
|
||||
* Abstract:
|
||||
* MiG definitions file for Mach exception interface.
|
||||
*/
|
||||
|
||||
subsystem
|
||||
#if KERNEL_USER
|
||||
KernelUser
|
||||
#endif
|
||||
exc 2401;
|
||||
|
||||
#include <mach/std_types.defs>
|
||||
#include <mach/mach_types.defs>
|
||||
|
||||
ServerPrefix catch_;
|
||||
|
||||
type exception_data_t = array[*:2] of integer_t;
|
||||
type exception_type_t = int;
|
||||
|
||||
routine exception_raise(
|
||||
#if KERNEL_USER
|
||||
exception_port : mach_port_move_send_t;
|
||||
thread : mach_port_move_send_t;
|
||||
task : mach_port_move_send_t;
|
||||
#else /* KERNEL_USER */
|
||||
exception_port : mach_port_t;
|
||||
thread : mach_port_t;
|
||||
task : mach_port_t;
|
||||
#endif /* KERNEL_USER */
|
||||
exception : exception_type_t;
|
||||
code : exception_data_t
|
||||
);
|
||||
|
||||
routine exception_raise_state(
|
||||
#if KERNEL_USER
|
||||
exception_port : mach_port_move_send_t;
|
||||
#else /* KERNEL_USER */
|
||||
exception_port : mach_port_t;
|
||||
#endif /* KERNEL_USER */
|
||||
exception : exception_type_t;
|
||||
code : exception_data_t, const;
|
||||
inout flavor : int;
|
||||
old_state : thread_state_t, const;
|
||||
out new_state : thread_state_t);
|
||||
|
||||
routine exception_raise_state_identity(
|
||||
#if KERNEL_USER
|
||||
exception_port : mach_port_move_send_t;
|
||||
thread : mach_port_move_send_t;
|
||||
task : mach_port_move_send_t;
|
||||
#else /* KERNEL_USER */
|
||||
exception_port : mach_port_t;
|
||||
thread : mach_port_t;
|
||||
task : mach_port_t;
|
||||
#endif /* KERNEL_USER */
|
||||
exception : exception_type_t;
|
||||
code : exception_data_t;
|
||||
inout flavor : int;
|
||||
old_state : thread_state_t;
|
||||
out new_state : thread_state_t);
|
||||
|
||||
/* vim: set ft=c : */
|
283
proctl/exc.h
Normal file
283
proctl/exc.h
Normal file
@ -0,0 +1,283 @@
|
||||
#ifndef _exc_user_
|
||||
#define _exc_user_
|
||||
|
||||
/* Module exc */
|
||||
|
||||
#include <string.h>
|
||||
#include <mach/ndr.h>
|
||||
#include <mach/boolean.h>
|
||||
#include <mach/kern_return.h>
|
||||
#include <mach/notify.h>
|
||||
#include <mach/mach_types.h>
|
||||
#include <mach/message.h>
|
||||
#include <mach/mig_errors.h>
|
||||
#include <mach/port.h>
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifndef KERNEL
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<mach/mig_voucher_support.h>)
|
||||
#ifndef USING_VOUCHERS
|
||||
#define USING_VOUCHERS
|
||||
#endif
|
||||
#ifndef __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#define __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#endif // __has_include(<mach/mach_voucher_types.h>)
|
||||
#endif // __has_include
|
||||
#endif // !KERNEL
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
|
||||
#ifdef AUTOTEST
|
||||
#ifndef FUNCTION_PTR_T
|
||||
#define FUNCTION_PTR_T
|
||||
typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t);
|
||||
typedef struct {
|
||||
char *name;
|
||||
function_ptr_t function;
|
||||
} function_table_entry;
|
||||
typedef function_table_entry *function_table_t;
|
||||
#endif /* FUNCTION_PTR_T */
|
||||
#endif /* AUTOTEST */
|
||||
|
||||
#ifndef exc_MSG_COUNT
|
||||
#define exc_MSG_COUNT 3
|
||||
#endif /* exc_MSG_COUNT */
|
||||
|
||||
#include <mach/std_types.h>
|
||||
#include <mach/mig.h>
|
||||
#include <mach/mig.h>
|
||||
#include <mach/mach_types.h>
|
||||
|
||||
#ifdef __BeforeMigUserHeader
|
||||
__BeforeMigUserHeader
|
||||
#endif /* __BeforeMigUserHeader */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__BEGIN_DECLS
|
||||
|
||||
|
||||
/* Routine exception_raise */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t exception_raise
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt
|
||||
);
|
||||
|
||||
/* Routine exception_raise_state */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t exception_raise_state
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
exception_type_t exception,
|
||||
const exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
const thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
);
|
||||
|
||||
/* Routine exception_raise_state_identity */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t exception_raise_state_identity
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
/********************** Caution **************************/
|
||||
/* The following data types should be used to calculate */
|
||||
/* maximum message sizes only. The actual message may be */
|
||||
/* smaller, and the position of the arguments within the */
|
||||
/* message layout may vary from what is presented here. */
|
||||
/* For example, if any of the arguments are variable- */
|
||||
/* sized, and less than the maximum is sent, the data */
|
||||
/* will be packed tight in the actual message to reduce */
|
||||
/* the presence of holes. */
|
||||
/********************** Caution **************************/
|
||||
|
||||
/* typedefs for all requests */
|
||||
|
||||
#ifndef __Request__exc_subsystem__defined
|
||||
#define __Request__exc_subsystem__defined
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
} __Request__exception_raise_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__exception_raise_state_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
#endif /* !__Request__exc_subsystem__defined */
|
||||
|
||||
/* union of all requests */
|
||||
|
||||
#ifndef __RequestUnion__exc_subsystem__defined
|
||||
#define __RequestUnion__exc_subsystem__defined
|
||||
union __RequestUnion__exc_subsystem {
|
||||
__Request__exception_raise_t Request_exception_raise;
|
||||
__Request__exception_raise_state_t Request_exception_raise_state;
|
||||
__Request__exception_raise_state_identity_t Request_exception_raise_state_identity;
|
||||
};
|
||||
#endif /* !__RequestUnion__exc_subsystem__defined */
|
||||
/* typedefs for all replies */
|
||||
|
||||
#ifndef __Reply__exc_subsystem__defined
|
||||
#define __Reply__exc_subsystem__defined
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
} __Reply__exception_raise_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply__exception_raise_state_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply__exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
#endif /* !__Reply__exc_subsystem__defined */
|
||||
|
||||
/* union of all replies */
|
||||
|
||||
#ifndef __ReplyUnion__exc_subsystem__defined
|
||||
#define __ReplyUnion__exc_subsystem__defined
|
||||
union __ReplyUnion__exc_subsystem {
|
||||
__Reply__exception_raise_t Reply_exception_raise;
|
||||
__Reply__exception_raise_state_t Reply_exception_raise_state;
|
||||
__Reply__exception_raise_state_identity_t Reply_exception_raise_state_identity;
|
||||
};
|
||||
#endif /* !__RequestUnion__exc_subsystem__defined */
|
||||
|
||||
#ifndef subsystem_to_name_map_exc
|
||||
#define subsystem_to_name_map_exc \
|
||||
{ "exception_raise", 2401 },\
|
||||
{ "exception_raise_state", 2402 },\
|
||||
{ "exception_raise_state_identity", 2403 }
|
||||
#endif
|
||||
|
||||
#ifdef __AfterMigUserHeader
|
||||
__AfterMigUserHeader
|
||||
#endif /* __AfterMigUserHeader */
|
||||
|
||||
#endif /* _exc_user_ */
|
766
proctl/excServer.c
Normal file
766
proctl/excServer.c
Normal file
@ -0,0 +1,766 @@
|
||||
/*
|
||||
* IDENTIFICATION:
|
||||
* stub generated Sun Feb 22 20:54:31 2015
|
||||
* with a MiG generated by bootstrap_cmds-91
|
||||
* OPTIONS:
|
||||
*/
|
||||
|
||||
/* Module exc */
|
||||
|
||||
#define __MIG_check__Request__exc_subsystem__ 1
|
||||
|
||||
#include <string.h>
|
||||
#include <mach/ndr.h>
|
||||
#include <mach/boolean.h>
|
||||
#include <mach/kern_return.h>
|
||||
#include <mach/notify.h>
|
||||
#include <mach/mach_types.h>
|
||||
#include <mach/message.h>
|
||||
#include <mach/mig_errors.h>
|
||||
#include <mach/port.h>
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifndef KERNEL
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<mach/mig_voucher_support.h>)
|
||||
#ifndef USING_VOUCHERS
|
||||
#define USING_VOUCHERS
|
||||
#endif
|
||||
#ifndef __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#define __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#endif // __has_include(<mach/mach_voucher_types.h>)
|
||||
#endif // __has_include
|
||||
#endif // !KERNEL
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
|
||||
#include <mach/std_types.h>
|
||||
#include <mach/mig.h>
|
||||
#include <mach/mig.h>
|
||||
#include <mach/mach_types.h>
|
||||
|
||||
#ifndef mig_internal
|
||||
#define mig_internal static __inline__
|
||||
#endif /* mig_internal */
|
||||
|
||||
#ifndef mig_external
|
||||
#define mig_external
|
||||
#endif /* mig_external */
|
||||
|
||||
#if !defined(__MigTypeCheck) && defined(TypeCheck)
|
||||
#define __MigTypeCheck TypeCheck /* Legacy setting */
|
||||
#endif /* !defined(__MigTypeCheck) */
|
||||
|
||||
#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)
|
||||
#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */
|
||||
#endif /* !defined(__MigKernelSpecificCode) */
|
||||
|
||||
#ifndef LimitCheck
|
||||
#define LimitCheck 0
|
||||
#endif /* LimitCheck */
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ( ((a) < (b))? (a): (b) )
|
||||
#endif /* min */
|
||||
|
||||
#if !defined(_WALIGN_)
|
||||
#define _WALIGN_(x) (((x) + 3) & ~3)
|
||||
#endif /* !defined(_WALIGN_) */
|
||||
|
||||
#if !defined(_WALIGNSZ_)
|
||||
#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))
|
||||
#endif /* !defined(_WALIGNSZ_) */
|
||||
|
||||
#ifndef UseStaticTemplates
|
||||
#define UseStaticTemplates 0
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#ifndef __DeclareRcvRpc
|
||||
#define __DeclareRcvRpc(_NUM_, _NAME_)
|
||||
#endif /* __DeclareRcvRpc */
|
||||
|
||||
#ifndef __BeforeRcvRpc
|
||||
#define __BeforeRcvRpc(_NUM_, _NAME_)
|
||||
#endif /* __BeforeRcvRpc */
|
||||
|
||||
#ifndef __AfterRcvRpc
|
||||
#define __AfterRcvRpc(_NUM_, _NAME_)
|
||||
#endif /* __AfterRcvRpc */
|
||||
|
||||
#ifndef __DeclareRcvSimple
|
||||
#define __DeclareRcvSimple(_NUM_, _NAME_)
|
||||
#endif /* __DeclareRcvSimple */
|
||||
|
||||
#ifndef __BeforeRcvSimple
|
||||
#define __BeforeRcvSimple(_NUM_, _NAME_)
|
||||
#endif /* __BeforeRcvSimple */
|
||||
|
||||
#ifndef __AfterRcvSimple
|
||||
#define __AfterRcvSimple(_NUM_, _NAME_)
|
||||
#endif /* __AfterRcvSimple */
|
||||
|
||||
#define novalue void
|
||||
|
||||
#define msgh_request_port msgh_local_port
|
||||
#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits)
|
||||
#define msgh_reply_port msgh_remote_port
|
||||
#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits)
|
||||
|
||||
#define MIG_RETURN_ERROR(X, code) {\
|
||||
((mig_reply_error_t *)X)->RetCode = code;\
|
||||
((mig_reply_error_t *)X)->NDR = NDR_record;\
|
||||
return;\
|
||||
}
|
||||
|
||||
/* typedefs for all requests */
|
||||
|
||||
#ifndef __Request__exc_subsystem__defined
|
||||
#define __Request__exc_subsystem__defined
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
} __Request__exception_raise_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__exception_raise_state_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
#endif /* !__Request__exc_subsystem__defined */
|
||||
|
||||
/* typedefs for all replies */
|
||||
|
||||
#ifndef __Reply__exc_subsystem__defined
|
||||
#define __Reply__exc_subsystem__defined
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
} __Reply__exception_raise_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply__exception_raise_state_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply__exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
#endif /* !__Reply__exc_subsystem__defined */
|
||||
|
||||
|
||||
/* union of all replies */
|
||||
|
||||
#ifndef __ReplyUnion__catch_exc_subsystem__defined
|
||||
#define __ReplyUnion__catch_exc_subsystem__defined
|
||||
union __ReplyUnion__catch_exc_subsystem {
|
||||
__Reply__exception_raise_t Reply_exception_raise;
|
||||
__Reply__exception_raise_state_t Reply_exception_raise_state;
|
||||
__Reply__exception_raise_state_identity_t Reply_exception_raise_state_identity;
|
||||
};
|
||||
#endif /* __RequestUnion__catch_exc_subsystem__defined */
|
||||
/* Forward Declarations */
|
||||
|
||||
|
||||
mig_internal novalue _Xexception_raise
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
|
||||
|
||||
mig_internal novalue _Xexception_raise_state
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
|
||||
|
||||
mig_internal novalue _Xexception_raise_state_identity
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
|
||||
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Request__exc_subsystem__
|
||||
#if !defined(__MIG_check__Request__exception_raise_t__defined)
|
||||
#define __MIG_check__Request__exception_raise_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Request__exception_raise_t(__attribute__((__unused__)) __Request__exception_raise_t *In0P)
|
||||
{
|
||||
|
||||
typedef __Request__exception_raise_t __Request;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = In0P->Head.msgh_size;
|
||||
if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
(In0P->msgh_body.msgh_descriptor_count != 2) ||
|
||||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 8)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if __MigTypeCheck
|
||||
if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR ||
|
||||
In0P->thread.disposition != 17)
|
||||
return MIG_TYPE_ERROR;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if __MigTypeCheck
|
||||
if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR ||
|
||||
In0P->task.disposition != 17)
|
||||
return MIG_TYPE_ERROR;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if defined(__NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined)
|
||||
if (In0P->NDR.int_rep != NDR_record.int_rep)
|
||||
__NDR_convert__int_rep__Request__exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
|
||||
#endif /* __NDR_convert__int_rep__Request__exception_raise_t__codeCnt__defined */
|
||||
#if __MigTypeCheck
|
||||
if ( In0P->codeCnt > 2 )
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 8)) / 4 < In0P->codeCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Request) - 8) + (4 * In0P->codeCnt)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Request__exception_raise_t__defined) */
|
||||
#endif /* __MIG_check__Request__exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine exception_raise */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t catch_exception_raise
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt
|
||||
);
|
||||
|
||||
/* Routine exception_raise */
|
||||
mig_internal novalue _Xexception_raise
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
typedef __Request__exception_raise_t __Request;
|
||||
typedef __Reply__exception_raise_t Reply;
|
||||
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
Request *In0P = (Request *) InHeadP;
|
||||
Reply *OutP = (Reply *) OutHeadP;
|
||||
#ifdef __MIG_check__Request__exception_raise_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Request__exception_raise_t__defined */
|
||||
|
||||
__DeclareRcvRpc(2401, "exception_raise")
|
||||
__BeforeRcvRpc(2401, "exception_raise")
|
||||
|
||||
#if defined(__MIG_check__Request__exception_raise_t__defined)
|
||||
check_result = __MIG_check__Request__exception_raise_t((__Request *)In0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ MIG_RETURN_ERROR(OutP, check_result); }
|
||||
#endif /* defined(__MIG_check__Request__exception_raise_t__defined) */
|
||||
|
||||
OutP->RetCode = catch_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt);
|
||||
|
||||
OutP->NDR = NDR_record;
|
||||
|
||||
|
||||
__AfterRcvRpc(2401, "exception_raise")
|
||||
}
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Request__exc_subsystem__
|
||||
#if !defined(__MIG_check__Request__exception_raise_state_t__defined)
|
||||
#define __MIG_check__Request__exception_raise_state_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Request__exception_raise_state_t(__attribute__((__unused__)) __Request__exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__exception_raise_state_t **In1PP)
|
||||
{
|
||||
|
||||
typedef __Request__exception_raise_state_t __Request;
|
||||
__Request *In1P;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
unsigned int msgh_size_delta;
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = In0P->Head.msgh_size;
|
||||
if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 904)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined)
|
||||
if (In0P->NDR.int_rep != NDR_record.int_rep)
|
||||
__NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
|
||||
#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__codeCnt__defined */
|
||||
msgh_size_delta = (4 * In0P->codeCnt);
|
||||
#if __MigTypeCheck
|
||||
if ( In0P->codeCnt > 2 )
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 904)) / 4 < In0P->codeCnt) ||
|
||||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 904) + (4 * In0P->codeCnt)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
msgh_size -= msgh_size_delta;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
*In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 8);
|
||||
|
||||
#if defined(__NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined)
|
||||
if (In0P->NDR.int_rep != NDR_record.int_rep)
|
||||
__NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep);
|
||||
#endif /* __NDR_convert__int_rep__Request__exception_raise_state_t__old_stateCnt__defined */
|
||||
#if __MigTypeCheck
|
||||
if ( In1P->old_stateCnt > 224 )
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 904)) / 4 < In1P->old_stateCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Request) - 904) + (4 * In1P->old_stateCnt)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Request__exception_raise_state_t__defined) */
|
||||
#endif /* __MIG_check__Request__exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine exception_raise_state */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t catch_exception_raise_state
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
exception_type_t exception,
|
||||
const exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
const thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
);
|
||||
|
||||
/* Routine exception_raise_state */
|
||||
mig_internal novalue _Xexception_raise_state
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
typedef __Request__exception_raise_state_t __Request;
|
||||
typedef __Reply__exception_raise_state_t Reply;
|
||||
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
Request *In0P = (Request *) InHeadP;
|
||||
Request *In1P;
|
||||
Reply *OutP = (Reply *) OutHeadP;
|
||||
#ifdef __MIG_check__Request__exception_raise_state_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Request__exception_raise_state_t__defined */
|
||||
|
||||
__DeclareRcvRpc(2402, "exception_raise_state")
|
||||
__BeforeRcvRpc(2402, "exception_raise_state")
|
||||
|
||||
#if defined(__MIG_check__Request__exception_raise_state_t__defined)
|
||||
check_result = __MIG_check__Request__exception_raise_state_t((__Request *)In0P, (__Request **)&In1P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ MIG_RETURN_ERROR(OutP, check_result); }
|
||||
#endif /* defined(__MIG_check__Request__exception_raise_state_t__defined) */
|
||||
|
||||
OutP->new_stateCnt = 224;
|
||||
|
||||
OutP->RetCode = catch_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt);
|
||||
if (OutP->RetCode != KERN_SUCCESS) {
|
||||
MIG_RETURN_ERROR(OutP, OutP->RetCode);
|
||||
}
|
||||
|
||||
OutP->NDR = NDR_record;
|
||||
|
||||
|
||||
OutP->flavor = In1P->flavor;
|
||||
OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt)));
|
||||
|
||||
__AfterRcvRpc(2402, "exception_raise_state")
|
||||
}
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Request__exc_subsystem__
|
||||
#if !defined(__MIG_check__Request__exception_raise_state_identity_t__defined)
|
||||
#define __MIG_check__Request__exception_raise_state_identity_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Request__exception_raise_state_identity_t(__attribute__((__unused__)) __Request__exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__exception_raise_state_identity_t **In1PP)
|
||||
{
|
||||
|
||||
typedef __Request__exception_raise_state_identity_t __Request;
|
||||
__Request *In1P;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
unsigned int msgh_size_delta;
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = In0P->Head.msgh_size;
|
||||
if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
(In0P->msgh_body.msgh_descriptor_count != 2) ||
|
||||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 904)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if __MigTypeCheck
|
||||
if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR ||
|
||||
In0P->thread.disposition != 17)
|
||||
return MIG_TYPE_ERROR;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if __MigTypeCheck
|
||||
if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR ||
|
||||
In0P->task.disposition != 17)
|
||||
return MIG_TYPE_ERROR;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined)
|
||||
if (In0P->NDR.int_rep != NDR_record.int_rep)
|
||||
__NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
|
||||
#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__codeCnt__defined */
|
||||
msgh_size_delta = (4 * In0P->codeCnt);
|
||||
#if __MigTypeCheck
|
||||
if ( In0P->codeCnt > 2 )
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 904)) / 4 < In0P->codeCnt) ||
|
||||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 904) + (4 * In0P->codeCnt)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
msgh_size -= msgh_size_delta;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
*In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 8);
|
||||
|
||||
#if defined(__NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined)
|
||||
if (In0P->NDR.int_rep != NDR_record.int_rep)
|
||||
__NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep);
|
||||
#endif /* __NDR_convert__int_rep__Request__exception_raise_state_identity_t__old_stateCnt__defined */
|
||||
#if __MigTypeCheck
|
||||
if ( In1P->old_stateCnt > 224 )
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 904)) / 4 < In1P->old_stateCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Request) - 904) + (4 * In1P->old_stateCnt)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Request__exception_raise_state_identity_t__defined) */
|
||||
#endif /* __MIG_check__Request__exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine exception_raise_state_identity */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t catch_exception_raise_state_identity
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
);
|
||||
|
||||
/* Routine exception_raise_state_identity */
|
||||
mig_internal novalue _Xexception_raise_state_identity
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
typedef __Request__exception_raise_state_identity_t __Request;
|
||||
typedef __Reply__exception_raise_state_identity_t Reply;
|
||||
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
Request *In0P = (Request *) InHeadP;
|
||||
Request *In1P;
|
||||
Reply *OutP = (Reply *) OutHeadP;
|
||||
#ifdef __MIG_check__Request__exception_raise_state_identity_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Request__exception_raise_state_identity_t__defined */
|
||||
|
||||
__DeclareRcvRpc(2403, "exception_raise_state_identity")
|
||||
__BeforeRcvRpc(2403, "exception_raise_state_identity")
|
||||
|
||||
#if defined(__MIG_check__Request__exception_raise_state_identity_t__defined)
|
||||
check_result = __MIG_check__Request__exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ MIG_RETURN_ERROR(OutP, check_result); }
|
||||
#endif /* defined(__MIG_check__Request__exception_raise_state_identity_t__defined) */
|
||||
|
||||
OutP->new_stateCnt = 224;
|
||||
|
||||
OutP->RetCode = catch_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt);
|
||||
if (OutP->RetCode != KERN_SUCCESS) {
|
||||
MIG_RETURN_ERROR(OutP, OutP->RetCode);
|
||||
}
|
||||
|
||||
OutP->NDR = NDR_record;
|
||||
|
||||
|
||||
OutP->flavor = In1P->flavor;
|
||||
OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt)));
|
||||
|
||||
__AfterRcvRpc(2403, "exception_raise_state_identity")
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
mig_routine_t exc_server_routine(
|
||||
mach_msg_header_t *InHeadP);
|
||||
|
||||
|
||||
/* Description of this subsystem, for use in direct RPC */
|
||||
const struct catch_exc_subsystem {
|
||||
mig_server_routine_t server; /* Server routine */
|
||||
mach_msg_id_t start; /* Min routine number */
|
||||
mach_msg_id_t end; /* Max routine number + 1 */
|
||||
unsigned int maxsize; /* Max msg size */
|
||||
vm_address_t reserved; /* Reserved */
|
||||
struct routine_descriptor /*Array of routine descriptors */
|
||||
routine[3];
|
||||
} catch_exc_subsystem = {
|
||||
exc_server_routine,
|
||||
2401,
|
||||
2404,
|
||||
(mach_msg_size_t)sizeof(union __ReplyUnion__catch_exc_subsystem),
|
||||
(vm_address_t)0,
|
||||
{
|
||||
{ (mig_impl_routine_t) 0,
|
||||
(mig_stub_routine_t) _Xexception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__exception_raise_t)},
|
||||
{ (mig_impl_routine_t) 0,
|
||||
(mig_stub_routine_t) _Xexception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__exception_raise_state_t)},
|
||||
{ (mig_impl_routine_t) 0,
|
||||
(mig_stub_routine_t) _Xexception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__exception_raise_state_identity_t)},
|
||||
}
|
||||
};
|
||||
|
||||
mig_external boolean_t exc_server
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
|
||||
{
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
register mig_routine_t routine;
|
||||
|
||||
OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);
|
||||
OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;
|
||||
/* Minimal size: routine() will update it if different */
|
||||
OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
|
||||
OutHeadP->msgh_local_port = MACH_PORT_NULL;
|
||||
OutHeadP->msgh_id = InHeadP->msgh_id + 100;
|
||||
|
||||
if ((InHeadP->msgh_id > 2403) || (InHeadP->msgh_id < 2401) ||
|
||||
((routine = catch_exc_subsystem.routine[InHeadP->msgh_id - 2401].stub_routine) == 0)) {
|
||||
((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;
|
||||
((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;
|
||||
return FALSE;
|
||||
}
|
||||
(*routine) (InHeadP, OutHeadP);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
mig_external mig_routine_t exc_server_routine
|
||||
(mach_msg_header_t *InHeadP)
|
||||
{
|
||||
register int msgh_id;
|
||||
|
||||
msgh_id = InHeadP->msgh_id - 2401;
|
||||
|
||||
if ((msgh_id > 2) || (msgh_id < 0))
|
||||
return 0;
|
||||
|
||||
return catch_exc_subsystem.routine[msgh_id].stub_routine;
|
||||
}
|
768
proctl/excUser.c
Normal file
768
proctl/excUser.c
Normal file
@ -0,0 +1,768 @@
|
||||
/*
|
||||
* IDENTIFICATION:
|
||||
* stub generated Sun Feb 22 20:54:31 2015
|
||||
* with a MiG generated by bootstrap_cmds-91
|
||||
* OPTIONS:
|
||||
*/
|
||||
#define __MIG_check__Reply__exc_subsystem__ 1
|
||||
|
||||
#include "exc.h"
|
||||
|
||||
|
||||
#ifndef mig_internal
|
||||
#define mig_internal static __inline__
|
||||
#endif /* mig_internal */
|
||||
|
||||
#ifndef mig_external
|
||||
#define mig_external
|
||||
#endif /* mig_external */
|
||||
|
||||
#if !defined(__MigTypeCheck) && defined(TypeCheck)
|
||||
#define __MigTypeCheck TypeCheck /* Legacy setting */
|
||||
#endif /* !defined(__MigTypeCheck) */
|
||||
|
||||
#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)
|
||||
#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */
|
||||
#endif /* !defined(__MigKernelSpecificCode) */
|
||||
|
||||
#ifndef LimitCheck
|
||||
#define LimitCheck 0
|
||||
#endif /* LimitCheck */
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ( ((a) < (b))? (a): (b) )
|
||||
#endif /* min */
|
||||
|
||||
#if !defined(_WALIGN_)
|
||||
#define _WALIGN_(x) (((x) + 3) & ~3)
|
||||
#endif /* !defined(_WALIGN_) */
|
||||
|
||||
#if !defined(_WALIGNSZ_)
|
||||
#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))
|
||||
#endif /* !defined(_WALIGNSZ_) */
|
||||
|
||||
#ifndef UseStaticTemplates
|
||||
#define UseStaticTemplates 0
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#ifndef __MachMsgErrorWithTimeout
|
||||
#define __MachMsgErrorWithTimeout(_R_) { \
|
||||
switch (_R_) { \
|
||||
case MACH_SEND_INVALID_DATA: \
|
||||
case MACH_SEND_INVALID_DEST: \
|
||||
case MACH_SEND_INVALID_HEADER: \
|
||||
mig_put_reply_port(InP->Head.msgh_reply_port); \
|
||||
break; \
|
||||
case MACH_SEND_TIMED_OUT: \
|
||||
case MACH_RCV_TIMED_OUT: \
|
||||
default: \
|
||||
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
|
||||
} \
|
||||
}
|
||||
#endif /* __MachMsgErrorWithTimeout */
|
||||
|
||||
#ifndef __MachMsgErrorWithoutTimeout
|
||||
#define __MachMsgErrorWithoutTimeout(_R_) { \
|
||||
switch (_R_) { \
|
||||
case MACH_SEND_INVALID_DATA: \
|
||||
case MACH_SEND_INVALID_DEST: \
|
||||
case MACH_SEND_INVALID_HEADER: \
|
||||
mig_put_reply_port(InP->Head.msgh_reply_port); \
|
||||
break; \
|
||||
default: \
|
||||
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
|
||||
} \
|
||||
}
|
||||
#endif /* __MachMsgErrorWithoutTimeout */
|
||||
|
||||
#ifndef __DeclareSendRpc
|
||||
#define __DeclareSendRpc(_NUM_, _NAME_)
|
||||
#endif /* __DeclareSendRpc */
|
||||
|
||||
#ifndef __BeforeSendRpc
|
||||
#define __BeforeSendRpc(_NUM_, _NAME_)
|
||||
#endif /* __BeforeSendRpc */
|
||||
|
||||
#ifndef __AfterSendRpc
|
||||
#define __AfterSendRpc(_NUM_, _NAME_)
|
||||
#endif /* __AfterSendRpc */
|
||||
|
||||
#ifndef __DeclareSendSimple
|
||||
#define __DeclareSendSimple(_NUM_, _NAME_)
|
||||
#endif /* __DeclareSendSimple */
|
||||
|
||||
#ifndef __BeforeSendSimple
|
||||
#define __BeforeSendSimple(_NUM_, _NAME_)
|
||||
#endif /* __BeforeSendSimple */
|
||||
|
||||
#ifndef __AfterSendSimple
|
||||
#define __AfterSendSimple(_NUM_, _NAME_)
|
||||
#endif /* __AfterSendSimple */
|
||||
|
||||
#define msgh_request_port msgh_remote_port
|
||||
#define msgh_reply_port msgh_local_port
|
||||
|
||||
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Reply__exc_subsystem__
|
||||
#if !defined(__MIG_check__Reply__exception_raise_t__defined)
|
||||
#define __MIG_check__Reply__exception_raise_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Reply__exception_raise_t(__Reply__exception_raise_t *Out0P)
|
||||
{
|
||||
|
||||
typedef __Reply__exception_raise_t __Reply;
|
||||
if (Out0P->Head.msgh_id != 2501) {
|
||||
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
|
||||
{ return MIG_SERVER_DIED; }
|
||||
else
|
||||
{ return MIG_REPLY_MISMATCH; }
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
(Out0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Reply)))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
{
|
||||
return Out0P->RetCode;
|
||||
}
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Reply__exception_raise_t__defined) */
|
||||
#endif /* __MIG_check__Reply__exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine exception_raise */
|
||||
mig_external kern_return_t exception_raise
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt
|
||||
)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
mach_msg_trailer_t trailer;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
} __Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
union {
|
||||
Request In;
|
||||
Reply Out;
|
||||
} Mess;
|
||||
|
||||
Request *InP = &Mess.In;
|
||||
Reply *Out0P = &Mess.Out;
|
||||
|
||||
mach_msg_return_t msg_result;
|
||||
unsigned int msgh_size;
|
||||
|
||||
#ifdef __MIG_check__Reply__exception_raise_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Reply__exception_raise_t__defined */
|
||||
|
||||
__DeclareSendRpc(2401, "exception_raise")
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t threadTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t taskTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->msgh_body.msgh_descriptor_count = 2;
|
||||
#if UseStaticTemplates
|
||||
InP->thread = threadTemplate;
|
||||
InP->thread.name = thread;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->thread.name = thread;
|
||||
InP->thread.disposition = 19;
|
||||
InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
InP->task = taskTemplate;
|
||||
InP->task.name = task;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->task.name = task;
|
||||
InP->task.disposition = 19;
|
||||
InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->NDR = NDR_record;
|
||||
|
||||
InP->exception = exception;
|
||||
|
||||
if (codeCnt > 2) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->code, (const char *) code, 4 * codeCnt);
|
||||
|
||||
InP->codeCnt = codeCnt;
|
||||
|
||||
msgh_size = (mach_msg_size_t)(sizeof(Request) - 8) + ((4 * codeCnt));
|
||||
InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
|
||||
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
/* msgh_size passed as argument */
|
||||
InP->Head.msgh_request_port = exception_port;
|
||||
InP->Head.msgh_reply_port = mig_get_reply_port();
|
||||
InP->Head.msgh_id = 2401;
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifdef USING_VOUCHERS
|
||||
if (voucher_mach_msg_set != NULL) {
|
||||
voucher_mach_msg_set(&InP->Head);
|
||||
}
|
||||
#endif // USING_VOUCHERS
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
__BeforeSendRpc(2401, "exception_raise")
|
||||
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
__AfterSendRpc(2401, "exception_raise")
|
||||
if (msg_result != MACH_MSG_SUCCESS) {
|
||||
__MachMsgErrorWithoutTimeout(msg_result);
|
||||
{ return msg_result; }
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MIG_check__Reply__exception_raise_t__defined)
|
||||
check_result = __MIG_check__Reply__exception_raise_t((__Reply__exception_raise_t *)Out0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ return check_result; }
|
||||
#endif /* defined(__MIG_check__Reply__exception_raise_t__defined) */
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Reply__exc_subsystem__
|
||||
#if !defined(__MIG_check__Reply__exception_raise_state_t__defined)
|
||||
#define __MIG_check__Reply__exception_raise_state_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Reply__exception_raise_state_t(__Reply__exception_raise_state_t *Out0P)
|
||||
{
|
||||
|
||||
typedef __Reply__exception_raise_state_t __Reply;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->Head.msgh_id != 2502) {
|
||||
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
|
||||
{ return MIG_SERVER_DIED; }
|
||||
else
|
||||
{ return MIG_REPLY_MISMATCH; }
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = Out0P->Head.msgh_size;
|
||||
|
||||
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) &&
|
||||
(msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
|
||||
Out0P->RetCode == KERN_SUCCESS)))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->RetCode != KERN_SUCCESS) {
|
||||
return ((mig_reply_error_t *)Out0P)->RetCode;
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
if ( Out0P->new_stateCnt > 224 )
|
||||
return MIG_TYPE_ERROR;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Reply__exception_raise_state_t__defined) */
|
||||
#endif /* __MIG_check__Reply__exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine exception_raise_state */
|
||||
mig_external kern_return_t exception_raise_state
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
exception_type_t exception,
|
||||
const exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
const thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
union {
|
||||
Request In;
|
||||
Reply Out;
|
||||
} Mess;
|
||||
|
||||
Request *InP = &Mess.In;
|
||||
Reply *Out0P = &Mess.Out;
|
||||
|
||||
mach_msg_return_t msg_result;
|
||||
unsigned int msgh_size;
|
||||
unsigned int msgh_size_delta;
|
||||
|
||||
|
||||
#ifdef __MIG_check__Reply__exception_raise_state_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Reply__exception_raise_state_t__defined */
|
||||
|
||||
__DeclareSendRpc(2402, "exception_raise_state")
|
||||
|
||||
InP->NDR = NDR_record;
|
||||
|
||||
InP->exception = exception;
|
||||
|
||||
if (codeCnt > 2) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->code, (const char *) code, 4 * codeCnt);
|
||||
|
||||
InP->codeCnt = codeCnt;
|
||||
|
||||
msgh_size_delta = (4 * codeCnt);
|
||||
msgh_size = (mach_msg_size_t)(sizeof(Request) - 904) + msgh_size_delta;
|
||||
InP = (Request *) ((pointer_t) InP + msgh_size_delta - 8);
|
||||
|
||||
InP->flavor = *flavor;
|
||||
|
||||
if (old_stateCnt > 224) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);
|
||||
|
||||
InP->old_stateCnt = old_stateCnt;
|
||||
|
||||
msgh_size += (4 * old_stateCnt);
|
||||
InP = &Mess.In;
|
||||
InP->Head.msgh_bits =
|
||||
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
/* msgh_size passed as argument */
|
||||
InP->Head.msgh_request_port = exception_port;
|
||||
InP->Head.msgh_reply_port = mig_get_reply_port();
|
||||
InP->Head.msgh_id = 2402;
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifdef USING_VOUCHERS
|
||||
if (voucher_mach_msg_set != NULL) {
|
||||
voucher_mach_msg_set(&InP->Head);
|
||||
}
|
||||
#endif // USING_VOUCHERS
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
__BeforeSendRpc(2402, "exception_raise_state")
|
||||
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
__AfterSendRpc(2402, "exception_raise_state")
|
||||
if (msg_result != MACH_MSG_SUCCESS) {
|
||||
__MachMsgErrorWithoutTimeout(msg_result);
|
||||
{ return msg_result; }
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MIG_check__Reply__exception_raise_state_t__defined)
|
||||
check_result = __MIG_check__Reply__exception_raise_state_t((__Reply__exception_raise_state_t *)Out0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ return check_result; }
|
||||
#endif /* defined(__MIG_check__Reply__exception_raise_state_t__defined) */
|
||||
|
||||
*flavor = Out0P->flavor;
|
||||
|
||||
if (Out0P->new_stateCnt > 224) {
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224);
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);
|
||||
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Reply__exc_subsystem__
|
||||
#if !defined(__MIG_check__Reply__exception_raise_state_identity_t__defined)
|
||||
#define __MIG_check__Reply__exception_raise_state_identity_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Reply__exception_raise_state_identity_t(__Reply__exception_raise_state_identity_t *Out0P)
|
||||
{
|
||||
|
||||
typedef __Reply__exception_raise_state_identity_t __Reply;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->Head.msgh_id != 2503) {
|
||||
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
|
||||
{ return MIG_SERVER_DIED; }
|
||||
else
|
||||
{ return MIG_REPLY_MISMATCH; }
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = Out0P->Head.msgh_size;
|
||||
|
||||
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) &&
|
||||
(msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
|
||||
Out0P->RetCode == KERN_SUCCESS)))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->RetCode != KERN_SUCCESS) {
|
||||
return ((mig_reply_error_t *)Out0P)->RetCode;
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
if ( Out0P->new_stateCnt > 224 )
|
||||
return MIG_TYPE_ERROR;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Reply__exception_raise_state_identity_t__defined) */
|
||||
#endif /* __MIG_check__Reply__exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine exception_raise_state_identity */
|
||||
mig_external kern_return_t exception_raise_state_identity
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
union {
|
||||
Request In;
|
||||
Reply Out;
|
||||
} Mess;
|
||||
|
||||
Request *InP = &Mess.In;
|
||||
Reply *Out0P = &Mess.Out;
|
||||
|
||||
mach_msg_return_t msg_result;
|
||||
unsigned int msgh_size;
|
||||
unsigned int msgh_size_delta;
|
||||
|
||||
|
||||
#ifdef __MIG_check__Reply__exception_raise_state_identity_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Reply__exception_raise_state_identity_t__defined */
|
||||
|
||||
__DeclareSendRpc(2403, "exception_raise_state_identity")
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t threadTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t taskTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->msgh_body.msgh_descriptor_count = 2;
|
||||
#if UseStaticTemplates
|
||||
InP->thread = threadTemplate;
|
||||
InP->thread.name = thread;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->thread.name = thread;
|
||||
InP->thread.disposition = 19;
|
||||
InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
InP->task = taskTemplate;
|
||||
InP->task.name = task;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->task.name = task;
|
||||
InP->task.disposition = 19;
|
||||
InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->NDR = NDR_record;
|
||||
|
||||
InP->exception = exception;
|
||||
|
||||
if (codeCnt > 2) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->code, (const char *) code, 4 * codeCnt);
|
||||
|
||||
InP->codeCnt = codeCnt;
|
||||
|
||||
msgh_size_delta = (4 * codeCnt);
|
||||
msgh_size = (mach_msg_size_t)(sizeof(Request) - 904) + msgh_size_delta;
|
||||
InP = (Request *) ((pointer_t) InP + msgh_size_delta - 8);
|
||||
|
||||
InP->flavor = *flavor;
|
||||
|
||||
if (old_stateCnt > 224) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);
|
||||
|
||||
InP->old_stateCnt = old_stateCnt;
|
||||
|
||||
msgh_size += (4 * old_stateCnt);
|
||||
InP = &Mess.In;
|
||||
InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
|
||||
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
/* msgh_size passed as argument */
|
||||
InP->Head.msgh_request_port = exception_port;
|
||||
InP->Head.msgh_reply_port = mig_get_reply_port();
|
||||
InP->Head.msgh_id = 2403;
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifdef USING_VOUCHERS
|
||||
if (voucher_mach_msg_set != NULL) {
|
||||
voucher_mach_msg_set(&InP->Head);
|
||||
}
|
||||
#endif // USING_VOUCHERS
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
__BeforeSendRpc(2403, "exception_raise_state_identity")
|
||||
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
__AfterSendRpc(2403, "exception_raise_state_identity")
|
||||
if (msg_result != MACH_MSG_SUCCESS) {
|
||||
__MachMsgErrorWithoutTimeout(msg_result);
|
||||
{ return msg_result; }
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MIG_check__Reply__exception_raise_state_identity_t__defined)
|
||||
check_result = __MIG_check__Reply__exception_raise_state_identity_t((__Reply__exception_raise_state_identity_t *)Out0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ return check_result; }
|
||||
#endif /* defined(__MIG_check__Reply__exception_raise_state_identity_t__defined) */
|
||||
|
||||
*flavor = Out0P->flavor;
|
||||
|
||||
if (Out0P->new_stateCnt > 224) {
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224);
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);
|
||||
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
119
proctl/mach_exc.defs
Normal file
119
proctl/mach_exc.defs
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
/*
|
||||
* @OSF_COPYRIGHT@
|
||||
*/
|
||||
/*
|
||||
* Mach Operating System
|
||||
* Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify and distribute this software and its
|
||||
* documentation is hereby granted, provided that both the copyright
|
||||
* notice and this permission notice appear in all copies of the
|
||||
* software, derivative works or modified versions, and any portions
|
||||
* thereof, and that both notices appear in supporting documentation.
|
||||
*
|
||||
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
||||
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
|
||||
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
||||
*
|
||||
* Carnegie Mellon requests users of this software to return to
|
||||
*
|
||||
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
|
||||
* School of Computer Science
|
||||
* Carnegie Mellon University
|
||||
* Pittsburgh PA 15213-3890
|
||||
*
|
||||
* any improvements or extensions that they make and grant Carnegie Mellon
|
||||
* the rights to redistribute these changes.
|
||||
*/
|
||||
/*
|
||||
*/
|
||||
/*
|
||||
* Abstract:
|
||||
* MiG definitions file for Mach exception interface.
|
||||
*/
|
||||
|
||||
subsystem
|
||||
#if KERNEL_USER
|
||||
KernelUser
|
||||
#endif
|
||||
mach_exc 2405;
|
||||
|
||||
#include <mach/std_types.defs>
|
||||
#include <mach/mach_types.defs>
|
||||
|
||||
ServerPrefix catch_;
|
||||
|
||||
type mach_exception_data_t = array[*:2] of int64_t;
|
||||
type exception_type_t = int;
|
||||
|
||||
routine mach_exception_raise(
|
||||
#if KERNEL_USER
|
||||
exception_port : mach_port_move_send_t;
|
||||
thread : mach_port_move_send_t;
|
||||
task : mach_port_move_send_t;
|
||||
#else /* KERNEL_USER */
|
||||
exception_port : mach_port_t;
|
||||
thread : mach_port_t;
|
||||
task : mach_port_t;
|
||||
#endif /* KERNEL_USER */
|
||||
exception : exception_type_t;
|
||||
code : mach_exception_data_t
|
||||
);
|
||||
|
||||
routine mach_exception_raise_state(
|
||||
#if KERNEL_USER
|
||||
exception_port : mach_port_move_send_t;
|
||||
#else /* KERNEL_USER */
|
||||
exception_port : mach_port_t;
|
||||
#endif /* KERNEL_USER */
|
||||
exception : exception_type_t;
|
||||
code : mach_exception_data_t, const;
|
||||
inout flavor : int;
|
||||
old_state : thread_state_t, const;
|
||||
out new_state : thread_state_t);
|
||||
|
||||
routine mach_exception_raise_state_identity(
|
||||
#if KERNEL_USER
|
||||
exception_port : mach_port_move_send_t;
|
||||
thread : mach_port_move_send_t;
|
||||
task : mach_port_move_send_t;
|
||||
#else /* KERNEL_USER */
|
||||
exception_port : mach_port_t;
|
||||
thread : mach_port_t;
|
||||
task : mach_port_t;
|
||||
#endif /* KERNEL_USER */
|
||||
exception : exception_type_t;
|
||||
code : mach_exception_data_t;
|
||||
inout flavor : int;
|
||||
old_state : thread_state_t;
|
||||
out new_state : thread_state_t);
|
||||
|
||||
/* vim: set ft=c : */
|
283
proctl/mach_exc.h
Normal file
283
proctl/mach_exc.h
Normal file
@ -0,0 +1,283 @@
|
||||
#ifndef _mach_exc_user_
|
||||
#define _mach_exc_user_
|
||||
|
||||
/* Module mach_exc */
|
||||
|
||||
#include <string.h>
|
||||
#include <mach/ndr.h>
|
||||
#include <mach/boolean.h>
|
||||
#include <mach/kern_return.h>
|
||||
#include <mach/notify.h>
|
||||
#include <mach/mach_types.h>
|
||||
#include <mach/message.h>
|
||||
#include <mach/mig_errors.h>
|
||||
#include <mach/port.h>
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifndef KERNEL
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<mach/mig_voucher_support.h>)
|
||||
#ifndef USING_VOUCHERS
|
||||
#define USING_VOUCHERS
|
||||
#endif
|
||||
#ifndef __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#define __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#endif // __has_include(<mach/mach_voucher_types.h>)
|
||||
#endif // __has_include
|
||||
#endif // !KERNEL
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
|
||||
#ifdef AUTOTEST
|
||||
#ifndef FUNCTION_PTR_T
|
||||
#define FUNCTION_PTR_T
|
||||
typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t);
|
||||
typedef struct {
|
||||
char *name;
|
||||
function_ptr_t function;
|
||||
} function_table_entry;
|
||||
typedef function_table_entry *function_table_t;
|
||||
#endif /* FUNCTION_PTR_T */
|
||||
#endif /* AUTOTEST */
|
||||
|
||||
#ifndef mach_exc_MSG_COUNT
|
||||
#define mach_exc_MSG_COUNT 3
|
||||
#endif /* mach_exc_MSG_COUNT */
|
||||
|
||||
#include <mach/std_types.h>
|
||||
#include <mach/mig.h>
|
||||
#include <mach/mig.h>
|
||||
#include <mach/mach_types.h>
|
||||
|
||||
#ifdef __BeforeMigUserHeader
|
||||
__BeforeMigUserHeader
|
||||
#endif /* __BeforeMigUserHeader */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__BEGIN_DECLS
|
||||
|
||||
|
||||
/* Routine mach_exception_raise */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t mach_exception_raise
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt
|
||||
);
|
||||
|
||||
/* Routine mach_exception_raise_state */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t mach_exception_raise_state
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
exception_type_t exception,
|
||||
const mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
const thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
);
|
||||
|
||||
/* Routine mach_exception_raise_state_identity */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t mach_exception_raise_state_identity
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
/********************** Caution **************************/
|
||||
/* The following data types should be used to calculate */
|
||||
/* maximum message sizes only. The actual message may be */
|
||||
/* smaller, and the position of the arguments within the */
|
||||
/* message layout may vary from what is presented here. */
|
||||
/* For example, if any of the arguments are variable- */
|
||||
/* sized, and less than the maximum is sent, the data */
|
||||
/* will be packed tight in the actual message to reduce */
|
||||
/* the presence of holes. */
|
||||
/********************** Caution **************************/
|
||||
|
||||
/* typedefs for all requests */
|
||||
|
||||
#ifndef __Request__mach_exc_subsystem__defined
|
||||
#define __Request__mach_exc_subsystem__defined
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
} __Request__mach_exception_raise_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__mach_exception_raise_state_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__mach_exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
#endif /* !__Request__mach_exc_subsystem__defined */
|
||||
|
||||
/* union of all requests */
|
||||
|
||||
#ifndef __RequestUnion__mach_exc_subsystem__defined
|
||||
#define __RequestUnion__mach_exc_subsystem__defined
|
||||
union __RequestUnion__mach_exc_subsystem {
|
||||
__Request__mach_exception_raise_t Request_mach_exception_raise;
|
||||
__Request__mach_exception_raise_state_t Request_mach_exception_raise_state;
|
||||
__Request__mach_exception_raise_state_identity_t Request_mach_exception_raise_state_identity;
|
||||
};
|
||||
#endif /* !__RequestUnion__mach_exc_subsystem__defined */
|
||||
/* typedefs for all replies */
|
||||
|
||||
#ifndef __Reply__mach_exc_subsystem__defined
|
||||
#define __Reply__mach_exc_subsystem__defined
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
} __Reply__mach_exception_raise_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply__mach_exception_raise_state_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply__mach_exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
#endif /* !__Reply__mach_exc_subsystem__defined */
|
||||
|
||||
/* union of all replies */
|
||||
|
||||
#ifndef __ReplyUnion__mach_exc_subsystem__defined
|
||||
#define __ReplyUnion__mach_exc_subsystem__defined
|
||||
union __ReplyUnion__mach_exc_subsystem {
|
||||
__Reply__mach_exception_raise_t Reply_mach_exception_raise;
|
||||
__Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state;
|
||||
__Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity;
|
||||
};
|
||||
#endif /* !__RequestUnion__mach_exc_subsystem__defined */
|
||||
|
||||
#ifndef subsystem_to_name_map_mach_exc
|
||||
#define subsystem_to_name_map_mach_exc \
|
||||
{ "mach_exception_raise", 2401 },\
|
||||
{ "mach_exception_raise_state", 2402 },\
|
||||
{ "mach_exception_raise_state_identity", 2403 }
|
||||
#endif
|
||||
|
||||
#ifdef __AfterMigUserHeader
|
||||
__AfterMigUserHeader
|
||||
#endif /* __AfterMigUserHeader */
|
||||
|
||||
#endif /* _mach_exc_user_ */
|
771
proctl/mach_excServer.c
Normal file
771
proctl/mach_excServer.c
Normal file
@ -0,0 +1,771 @@
|
||||
/*
|
||||
* IDENTIFICATION:
|
||||
* stub generated Sat Feb 21 18:10:52 2015
|
||||
* with a MiG generated by bootstrap_cmds-91
|
||||
* OPTIONS:
|
||||
*/
|
||||
|
||||
/* Module mach_exc */
|
||||
|
||||
#define __MIG_check__Request__mach_exc_subsystem__ 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <mach/ndr.h>
|
||||
#include <mach/boolean.h>
|
||||
#include <mach/kern_return.h>
|
||||
#include <mach/notify.h>
|
||||
#include <mach/mach_types.h>
|
||||
#include <mach/message.h>
|
||||
#include <mach/mig_errors.h>
|
||||
#include <mach/port.h>
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifndef KERNEL
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<mach/mig_voucher_support.h>)
|
||||
#ifndef USING_VOUCHERS
|
||||
#define USING_VOUCHERS
|
||||
#endif
|
||||
#ifndef __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#define __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#endif // __has_include(<mach/mach_voucher_types.h>)
|
||||
#endif // __has_include
|
||||
#endif // !KERNEL
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
|
||||
#include <mach/std_types.h>
|
||||
#include <mach/mig.h>
|
||||
#include <mach/mig.h>
|
||||
#include <mach/mach_types.h>
|
||||
|
||||
#ifndef mig_internal
|
||||
#define mig_internal static __inline__
|
||||
#endif /* mig_internal */
|
||||
|
||||
#ifndef mig_external
|
||||
#define mig_external
|
||||
#endif /* mig_external */
|
||||
|
||||
#if !defined(__MigTypeCheck) && defined(TypeCheck)
|
||||
#define __MigTypeCheck TypeCheck /* Legacy setting */
|
||||
#endif /* !defined(__MigTypeCheck) */
|
||||
|
||||
#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)
|
||||
#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */
|
||||
#endif /* !defined(__MigKernelSpecificCode) */
|
||||
|
||||
#ifndef LimitCheck
|
||||
#define LimitCheck 0
|
||||
#endif /* LimitCheck */
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ( ((a) < (b))? (a): (b) )
|
||||
#endif /* min */
|
||||
|
||||
#if !defined(_WALIGN_)
|
||||
#define _WALIGN_(x) (((x) + 3) & ~3)
|
||||
#endif /* !defined(_WALIGN_) */
|
||||
|
||||
#if !defined(_WALIGNSZ_)
|
||||
#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))
|
||||
#endif /* !defined(_WALIGNSZ_) */
|
||||
|
||||
#ifndef UseStaticTemplates
|
||||
#define UseStaticTemplates 0
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#ifndef __DeclareRcvRpc
|
||||
#define __DeclareRcvRpc(_NUM_, _NAME_)
|
||||
#endif /* __DeclareRcvRpc */
|
||||
|
||||
#ifndef __BeforeRcvRpc
|
||||
#define __BeforeRcvRpc(_NUM_, _NAME_)
|
||||
#endif /* __BeforeRcvRpc */
|
||||
|
||||
#ifndef __AfterRcvRpc
|
||||
#define __AfterRcvRpc(_NUM_, _NAME_)
|
||||
#endif /* __AfterRcvRpc */
|
||||
|
||||
#ifndef __DeclareRcvSimple
|
||||
#define __DeclareRcvSimple(_NUM_, _NAME_)
|
||||
#endif /* __DeclareRcvSimple */
|
||||
|
||||
#ifndef __BeforeRcvSimple
|
||||
#define __BeforeRcvSimple(_NUM_, _NAME_)
|
||||
#endif /* __BeforeRcvSimple */
|
||||
|
||||
#ifndef __AfterRcvSimple
|
||||
#define __AfterRcvSimple(_NUM_, _NAME_)
|
||||
#endif /* __AfterRcvSimple */
|
||||
|
||||
#define novalue void
|
||||
|
||||
#define msgh_request_port msgh_local_port
|
||||
#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits)
|
||||
#define msgh_reply_port msgh_remote_port
|
||||
#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits)
|
||||
|
||||
#define MIG_RETURN_ERROR(X, code) {\
|
||||
((mig_reply_error_t *)X)->RetCode = code;\
|
||||
((mig_reply_error_t *)X)->NDR = NDR_record;\
|
||||
return;\
|
||||
}
|
||||
|
||||
/* typedefs for all requests */
|
||||
|
||||
#ifndef __Request__mach_exc_subsystem__defined
|
||||
#define __Request__mach_exc_subsystem__defined
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
} __Request__mach_exception_raise_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__mach_exception_raise_state_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__mach_exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
#endif /* !__Request__mach_exc_subsystem__defined */
|
||||
|
||||
/* typedefs for all replies */
|
||||
|
||||
#ifndef __Reply__mach_exc_subsystem__defined
|
||||
#define __Reply__mach_exc_subsystem__defined
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
} __Reply__mach_exception_raise_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply__mach_exception_raise_state_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply__mach_exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
#endif /* !__Reply__mach_exc_subsystem__defined */
|
||||
|
||||
|
||||
/* union of all replies */
|
||||
|
||||
#ifndef __ReplyUnion__catch_mach_exc_subsystem__defined
|
||||
#define __ReplyUnion__catch_mach_exc_subsystem__defined
|
||||
union __ReplyUnion__catch_mach_exc_subsystem {
|
||||
__Reply__mach_exception_raise_t Reply_mach_exception_raise;
|
||||
__Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state;
|
||||
__Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity;
|
||||
};
|
||||
#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */
|
||||
/* Forward Declarations */
|
||||
|
||||
|
||||
mig_internal novalue _Xmach_exception_raise
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
|
||||
|
||||
mig_internal novalue _Xmach_exception_raise_state
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
|
||||
|
||||
mig_internal novalue _Xmach_exception_raise_state_identity
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
|
||||
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Request__mach_exc_subsystem__
|
||||
#if !defined(__MIG_check__Request__mach_exception_raise_t__defined)
|
||||
#define __MIG_check__Request__mach_exception_raise_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_t(__attribute__((__unused__)) __Request__mach_exception_raise_t *In0P)
|
||||
{
|
||||
|
||||
typedef __Request__mach_exception_raise_t __Request;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = In0P->Head.msgh_size;
|
||||
if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
(In0P->msgh_body.msgh_descriptor_count != 2) ||
|
||||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 16)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if __MigTypeCheck
|
||||
if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR ||
|
||||
In0P->thread.disposition != 17)
|
||||
return MIG_TYPE_ERROR;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if __MigTypeCheck
|
||||
if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR ||
|
||||
In0P->task.disposition != 17)
|
||||
return MIG_TYPE_ERROR;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined)
|
||||
if (In0P->NDR.int_rep != NDR_record.int_rep)
|
||||
__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
|
||||
#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined */
|
||||
#if __MigTypeCheck
|
||||
if ( In0P->codeCnt > 2 )
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 16)) / 8 < In0P->codeCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Request) - 16) + (8 * In0P->codeCnt)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Request__mach_exception_raise_t__defined) */
|
||||
#endif /* __MIG_check__Request__mach_exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine mach_exception_raise */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t catch_mach_exception_raise
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt
|
||||
);
|
||||
|
||||
/* Routine mach_exception_raise */
|
||||
mig_internal novalue _Xmach_exception_raise
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
typedef __Request__mach_exception_raise_t __Request;
|
||||
typedef __Reply__mach_exception_raise_t Reply;
|
||||
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
Request *In0P = (Request *) InHeadP;
|
||||
Reply *OutP = (Reply *) OutHeadP;
|
||||
#ifdef __MIG_check__Request__mach_exception_raise_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Request__mach_exception_raise_t__defined */
|
||||
|
||||
__DeclareRcvRpc(2405, "mach_exception_raise")
|
||||
__BeforeRcvRpc(2405, "mach_exception_raise")
|
||||
|
||||
#if defined(__MIG_check__Request__mach_exception_raise_t__defined)
|
||||
check_result = __MIG_check__Request__mach_exception_raise_t((__Request *)In0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ MIG_RETURN_ERROR(OutP, check_result); }
|
||||
#endif /* defined(__MIG_check__Request__mach_exception_raise_t__defined) */
|
||||
|
||||
OutP->RetCode = catch_mach_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt);
|
||||
|
||||
OutP->NDR = NDR_record;
|
||||
|
||||
|
||||
__AfterRcvRpc(2405, "mach_exception_raise")
|
||||
}
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Request__mach_exc_subsystem__
|
||||
#if !defined(__MIG_check__Request__mach_exception_raise_state_t__defined)
|
||||
#define __MIG_check__Request__mach_exception_raise_state_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_t **In1PP)
|
||||
{
|
||||
|
||||
typedef __Request__mach_exception_raise_state_t __Request;
|
||||
__Request *In1P;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
unsigned int msgh_size_delta;
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = In0P->Head.msgh_size;
|
||||
if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined)
|
||||
if (In0P->NDR.int_rep != NDR_record.int_rep)
|
||||
__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
|
||||
#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined */
|
||||
msgh_size_delta = (8 * In0P->codeCnt);
|
||||
#if __MigTypeCheck
|
||||
if ( In0P->codeCnt > 2 )
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) ||
|
||||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
msgh_size -= msgh_size_delta;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
*In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16);
|
||||
|
||||
#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined)
|
||||
if (In0P->NDR.int_rep != NDR_record.int_rep)
|
||||
__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep);
|
||||
#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined */
|
||||
#if __MigTypeCheck
|
||||
if ( In1P->old_stateCnt > 224 )
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */
|
||||
#endif /* __MIG_check__Request__mach_exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine mach_exception_raise_state */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t catch_mach_exception_raise_state
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
exception_type_t exception,
|
||||
const mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
const thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
);
|
||||
|
||||
/* Routine mach_exception_raise_state */
|
||||
mig_internal novalue _Xmach_exception_raise_state
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
typedef __Request__mach_exception_raise_state_t __Request;
|
||||
typedef __Reply__mach_exception_raise_state_t Reply;
|
||||
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
Request *In0P = (Request *) InHeadP;
|
||||
Request *In1P;
|
||||
Reply *OutP = (Reply *) OutHeadP;
|
||||
#ifdef __MIG_check__Request__mach_exception_raise_state_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Request__mach_exception_raise_state_t__defined */
|
||||
|
||||
__DeclareRcvRpc(2406, "mach_exception_raise_state")
|
||||
__BeforeRcvRpc(2406, "mach_exception_raise_state")
|
||||
|
||||
#if defined(__MIG_check__Request__mach_exception_raise_state_t__defined)
|
||||
check_result = __MIG_check__Request__mach_exception_raise_state_t((__Request *)In0P, (__Request **)&In1P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ MIG_RETURN_ERROR(OutP, check_result); }
|
||||
#endif /* defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */
|
||||
|
||||
OutP->new_stateCnt = 224;
|
||||
|
||||
OutP->RetCode = catch_mach_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt);
|
||||
if (OutP->RetCode != KERN_SUCCESS) {
|
||||
MIG_RETURN_ERROR(OutP, OutP->RetCode);
|
||||
}
|
||||
|
||||
OutP->NDR = NDR_record;
|
||||
|
||||
|
||||
OutP->flavor = In1P->flavor;
|
||||
OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt)));
|
||||
|
||||
__AfterRcvRpc(2406, "mach_exception_raise_state")
|
||||
}
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Request__mach_exc_subsystem__
|
||||
#if !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined)
|
||||
#define __MIG_check__Request__mach_exception_raise_state_identity_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_identity_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t **In1PP)
|
||||
{
|
||||
|
||||
typedef __Request__mach_exception_raise_state_identity_t __Request;
|
||||
__Request *In1P;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
unsigned int msgh_size_delta;
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = In0P->Head.msgh_size;
|
||||
if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
(In0P->msgh_body.msgh_descriptor_count != 2) ||
|
||||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if __MigTypeCheck
|
||||
if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR ||
|
||||
In0P->thread.disposition != 17)
|
||||
return MIG_TYPE_ERROR;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if __MigTypeCheck
|
||||
if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR ||
|
||||
In0P->task.disposition != 17)
|
||||
return MIG_TYPE_ERROR;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined)
|
||||
if (In0P->NDR.int_rep != NDR_record.int_rep)
|
||||
__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
|
||||
#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined */
|
||||
msgh_size_delta = (8 * In0P->codeCnt);
|
||||
#if __MigTypeCheck
|
||||
if ( In0P->codeCnt > 2 )
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) ||
|
||||
(msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
msgh_size -= msgh_size_delta;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
*In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16);
|
||||
|
||||
#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined)
|
||||
if (In0P->NDR.int_rep != NDR_record.int_rep)
|
||||
__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep);
|
||||
#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined */
|
||||
#if __MigTypeCheck
|
||||
if ( In1P->old_stateCnt > 224 )
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt)))
|
||||
return MIG_BAD_ARGUMENTS;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */
|
||||
#endif /* __MIG_check__Request__mach_exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine mach_exception_raise_state_identity */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t catch_mach_exception_raise_state_identity
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
);
|
||||
|
||||
/* Routine mach_exception_raise_state_identity */
|
||||
mig_internal novalue _Xmach_exception_raise_state_identity
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
typedef __Request__mach_exception_raise_state_identity_t __Request;
|
||||
typedef __Reply__mach_exception_raise_state_identity_t Reply;
|
||||
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
Request *In0P = (Request *) InHeadP;
|
||||
Request *In1P;
|
||||
Reply *OutP = (Reply *) OutHeadP;
|
||||
#ifdef __MIG_check__Request__mach_exception_raise_state_identity_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Request__mach_exception_raise_state_identity_t__defined */
|
||||
|
||||
__DeclareRcvRpc(2407, "mach_exception_raise_state_identity")
|
||||
__BeforeRcvRpc(2407, "mach_exception_raise_state_identity")
|
||||
|
||||
#if defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined)
|
||||
check_result = __MIG_check__Request__mach_exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ MIG_RETURN_ERROR(OutP, check_result); }
|
||||
#endif /* defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */
|
||||
|
||||
OutP->new_stateCnt = 224;
|
||||
|
||||
OutP->RetCode = catch_mach_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt);
|
||||
if (OutP->RetCode != KERN_SUCCESS) {
|
||||
MIG_RETURN_ERROR(OutP, OutP->RetCode);
|
||||
}
|
||||
|
||||
OutP->NDR = NDR_record;
|
||||
|
||||
|
||||
OutP->flavor = In1P->flavor;
|
||||
OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt)));
|
||||
|
||||
__AfterRcvRpc(2407, "mach_exception_raise_state_identity")
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
mig_routine_t mach_exc_server_routine(
|
||||
mach_msg_header_t *InHeadP);
|
||||
|
||||
|
||||
/* Description of this subsystem, for use in direct RPC */
|
||||
const struct catch_mach_exc_subsystem {
|
||||
mig_server_routine_t server; /* Server routine */
|
||||
mach_msg_id_t start; /* Min routine number */
|
||||
mach_msg_id_t end; /* Max routine number + 1 */
|
||||
unsigned int maxsize; /* Max msg size */
|
||||
vm_address_t reserved; /* Reserved */
|
||||
struct routine_descriptor /*Array of routine descriptors */
|
||||
routine[3];
|
||||
} catch_mach_exc_subsystem = {
|
||||
mach_exc_server_routine,
|
||||
2405,
|
||||
2408,
|
||||
(mach_msg_size_t)sizeof(union __ReplyUnion__catch_mach_exc_subsystem),
|
||||
(vm_address_t)0,
|
||||
{
|
||||
{ (mig_impl_routine_t) 0,
|
||||
(mig_stub_routine_t) _Xmach_exception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_t)},
|
||||
{ (mig_impl_routine_t) 0,
|
||||
(mig_stub_routine_t) _Xmach_exception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_t)},
|
||||
{ (mig_impl_routine_t) 0,
|
||||
(mig_stub_routine_t) _Xmach_exception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_identity_t)},
|
||||
}
|
||||
};
|
||||
|
||||
mig_external boolean_t mach_exc_server
|
||||
(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
|
||||
{
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
register mig_routine_t routine;
|
||||
|
||||
OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);
|
||||
OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;
|
||||
/* Minimal size: routine() will update it if different */
|
||||
OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
|
||||
OutHeadP->msgh_local_port = MACH_PORT_NULL;
|
||||
OutHeadP->msgh_id = InHeadP->msgh_id + 100;
|
||||
#if TARGET_OSX_USE_64BIT_EXCEPTIONS
|
||||
puts("64 bit");
|
||||
#endif
|
||||
|
||||
if ((InHeadP->msgh_id > 2407) || (InHeadP->msgh_id < 2405) ||
|
||||
((routine = catch_mach_exc_subsystem.routine[InHeadP->msgh_id - 2405].stub_routine) == 0)) {
|
||||
((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;
|
||||
((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;
|
||||
printf("msgh_id %d\n", InHeadP->msgh_id);
|
||||
return FALSE;
|
||||
}
|
||||
(*routine) (InHeadP, OutHeadP);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
mig_external mig_routine_t mach_exc_server_routine
|
||||
(mach_msg_header_t *InHeadP)
|
||||
{
|
||||
register int msgh_id;
|
||||
|
||||
msgh_id = InHeadP->msgh_id - 2405;
|
||||
|
||||
if ((msgh_id > 2) || (msgh_id < 0))
|
||||
return 0;
|
||||
|
||||
return catch_mach_exc_subsystem.routine[msgh_id].stub_routine;
|
||||
}
|
768
proctl/mach_excUser.c
Normal file
768
proctl/mach_excUser.c
Normal file
@ -0,0 +1,768 @@
|
||||
/*
|
||||
* IDENTIFICATION:
|
||||
* stub generated Sat Feb 21 18:10:52 2015
|
||||
* with a MiG generated by bootstrap_cmds-91
|
||||
* OPTIONS:
|
||||
*/
|
||||
#define __MIG_check__Reply__mach_exc_subsystem__ 1
|
||||
|
||||
#include "mach_exc.h"
|
||||
|
||||
|
||||
#ifndef mig_internal
|
||||
#define mig_internal static __inline__
|
||||
#endif /* mig_internal */
|
||||
|
||||
#ifndef mig_external
|
||||
#define mig_external
|
||||
#endif /* mig_external */
|
||||
|
||||
#if !defined(__MigTypeCheck) && defined(TypeCheck)
|
||||
#define __MigTypeCheck TypeCheck /* Legacy setting */
|
||||
#endif /* !defined(__MigTypeCheck) */
|
||||
|
||||
#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)
|
||||
#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */
|
||||
#endif /* !defined(__MigKernelSpecificCode) */
|
||||
|
||||
#ifndef LimitCheck
|
||||
#define LimitCheck 0
|
||||
#endif /* LimitCheck */
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ( ((a) < (b))? (a): (b) )
|
||||
#endif /* min */
|
||||
|
||||
#if !defined(_WALIGN_)
|
||||
#define _WALIGN_(x) (((x) + 3) & ~3)
|
||||
#endif /* !defined(_WALIGN_) */
|
||||
|
||||
#if !defined(_WALIGNSZ_)
|
||||
#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))
|
||||
#endif /* !defined(_WALIGNSZ_) */
|
||||
|
||||
#ifndef UseStaticTemplates
|
||||
#define UseStaticTemplates 0
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#ifndef __MachMsgErrorWithTimeout
|
||||
#define __MachMsgErrorWithTimeout(_R_) { \
|
||||
switch (_R_) { \
|
||||
case MACH_SEND_INVALID_DATA: \
|
||||
case MACH_SEND_INVALID_DEST: \
|
||||
case MACH_SEND_INVALID_HEADER: \
|
||||
mig_put_reply_port(InP->Head.msgh_reply_port); \
|
||||
break; \
|
||||
case MACH_SEND_TIMED_OUT: \
|
||||
case MACH_RCV_TIMED_OUT: \
|
||||
default: \
|
||||
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
|
||||
} \
|
||||
}
|
||||
#endif /* __MachMsgErrorWithTimeout */
|
||||
|
||||
#ifndef __MachMsgErrorWithoutTimeout
|
||||
#define __MachMsgErrorWithoutTimeout(_R_) { \
|
||||
switch (_R_) { \
|
||||
case MACH_SEND_INVALID_DATA: \
|
||||
case MACH_SEND_INVALID_DEST: \
|
||||
case MACH_SEND_INVALID_HEADER: \
|
||||
mig_put_reply_port(InP->Head.msgh_reply_port); \
|
||||
break; \
|
||||
default: \
|
||||
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
|
||||
} \
|
||||
}
|
||||
#endif /* __MachMsgErrorWithoutTimeout */
|
||||
|
||||
#ifndef __DeclareSendRpc
|
||||
#define __DeclareSendRpc(_NUM_, _NAME_)
|
||||
#endif /* __DeclareSendRpc */
|
||||
|
||||
#ifndef __BeforeSendRpc
|
||||
#define __BeforeSendRpc(_NUM_, _NAME_)
|
||||
#endif /* __BeforeSendRpc */
|
||||
|
||||
#ifndef __AfterSendRpc
|
||||
#define __AfterSendRpc(_NUM_, _NAME_)
|
||||
#endif /* __AfterSendRpc */
|
||||
|
||||
#ifndef __DeclareSendSimple
|
||||
#define __DeclareSendSimple(_NUM_, _NAME_)
|
||||
#endif /* __DeclareSendSimple */
|
||||
|
||||
#ifndef __BeforeSendSimple
|
||||
#define __BeforeSendSimple(_NUM_, _NAME_)
|
||||
#endif /* __BeforeSendSimple */
|
||||
|
||||
#ifndef __AfterSendSimple
|
||||
#define __AfterSendSimple(_NUM_, _NAME_)
|
||||
#endif /* __AfterSendSimple */
|
||||
|
||||
#define msgh_request_port msgh_remote_port
|
||||
#define msgh_reply_port msgh_local_port
|
||||
|
||||
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Reply__mach_exc_subsystem__
|
||||
#if !defined(__MIG_check__Reply__mach_exception_raise_t__defined)
|
||||
#define __MIG_check__Reply__mach_exception_raise_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_t(__Reply__mach_exception_raise_t *Out0P)
|
||||
{
|
||||
|
||||
typedef __Reply__mach_exception_raise_t __Reply;
|
||||
if (Out0P->Head.msgh_id != 2505) {
|
||||
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
|
||||
{ return MIG_SERVER_DIED; }
|
||||
else
|
||||
{ return MIG_REPLY_MISMATCH; }
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
(Out0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Reply)))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
{
|
||||
return Out0P->RetCode;
|
||||
}
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Reply__mach_exception_raise_t__defined) */
|
||||
#endif /* __MIG_check__Reply__mach_exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine mach_exception_raise */
|
||||
mig_external kern_return_t mach_exception_raise
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt
|
||||
)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
mach_msg_trailer_t trailer;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
} __Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
union {
|
||||
Request In;
|
||||
Reply Out;
|
||||
} Mess;
|
||||
|
||||
Request *InP = &Mess.In;
|
||||
Reply *Out0P = &Mess.Out;
|
||||
|
||||
mach_msg_return_t msg_result;
|
||||
unsigned int msgh_size;
|
||||
|
||||
#ifdef __MIG_check__Reply__mach_exception_raise_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Reply__mach_exception_raise_t__defined */
|
||||
|
||||
__DeclareSendRpc(2405, "mach_exception_raise")
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t threadTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t taskTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->msgh_body.msgh_descriptor_count = 2;
|
||||
#if UseStaticTemplates
|
||||
InP->thread = threadTemplate;
|
||||
InP->thread.name = thread;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->thread.name = thread;
|
||||
InP->thread.disposition = 19;
|
||||
InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
InP->task = taskTemplate;
|
||||
InP->task.name = task;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->task.name = task;
|
||||
InP->task.disposition = 19;
|
||||
InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->NDR = NDR_record;
|
||||
|
||||
InP->exception = exception;
|
||||
|
||||
if (codeCnt > 2) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);
|
||||
|
||||
InP->codeCnt = codeCnt;
|
||||
|
||||
msgh_size = (mach_msg_size_t)(sizeof(Request) - 16) + ((8 * codeCnt));
|
||||
InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
|
||||
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
/* msgh_size passed as argument */
|
||||
InP->Head.msgh_request_port = exception_port;
|
||||
InP->Head.msgh_reply_port = mig_get_reply_port();
|
||||
InP->Head.msgh_id = 2405;
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifdef USING_VOUCHERS
|
||||
if (voucher_mach_msg_set != NULL) {
|
||||
voucher_mach_msg_set(&InP->Head);
|
||||
}
|
||||
#endif // USING_VOUCHERS
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
__BeforeSendRpc(2405, "mach_exception_raise")
|
||||
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
__AfterSendRpc(2405, "mach_exception_raise")
|
||||
if (msg_result != MACH_MSG_SUCCESS) {
|
||||
__MachMsgErrorWithoutTimeout(msg_result);
|
||||
{ return msg_result; }
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MIG_check__Reply__mach_exception_raise_t__defined)
|
||||
check_result = __MIG_check__Reply__mach_exception_raise_t((__Reply__mach_exception_raise_t *)Out0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ return check_result; }
|
||||
#endif /* defined(__MIG_check__Reply__mach_exception_raise_t__defined) */
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Reply__mach_exc_subsystem__
|
||||
#if !defined(__MIG_check__Reply__mach_exception_raise_state_t__defined)
|
||||
#define __MIG_check__Reply__mach_exception_raise_state_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_state_t(__Reply__mach_exception_raise_state_t *Out0P)
|
||||
{
|
||||
|
||||
typedef __Reply__mach_exception_raise_state_t __Reply;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->Head.msgh_id != 2506) {
|
||||
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
|
||||
{ return MIG_SERVER_DIED; }
|
||||
else
|
||||
{ return MIG_REPLY_MISMATCH; }
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = Out0P->Head.msgh_size;
|
||||
|
||||
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) &&
|
||||
(msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
|
||||
Out0P->RetCode == KERN_SUCCESS)))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->RetCode != KERN_SUCCESS) {
|
||||
return ((mig_reply_error_t *)Out0P)->RetCode;
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
if ( Out0P->new_stateCnt > 224 )
|
||||
return MIG_TYPE_ERROR;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) */
|
||||
#endif /* __MIG_check__Reply__mach_exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine mach_exception_raise_state */
|
||||
mig_external kern_return_t mach_exception_raise_state
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
exception_type_t exception,
|
||||
const mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
const thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
union {
|
||||
Request In;
|
||||
Reply Out;
|
||||
} Mess;
|
||||
|
||||
Request *InP = &Mess.In;
|
||||
Reply *Out0P = &Mess.Out;
|
||||
|
||||
mach_msg_return_t msg_result;
|
||||
unsigned int msgh_size;
|
||||
unsigned int msgh_size_delta;
|
||||
|
||||
|
||||
#ifdef __MIG_check__Reply__mach_exception_raise_state_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Reply__mach_exception_raise_state_t__defined */
|
||||
|
||||
__DeclareSendRpc(2406, "mach_exception_raise_state")
|
||||
|
||||
InP->NDR = NDR_record;
|
||||
|
||||
InP->exception = exception;
|
||||
|
||||
if (codeCnt > 2) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);
|
||||
|
||||
InP->codeCnt = codeCnt;
|
||||
|
||||
msgh_size_delta = (8 * codeCnt);
|
||||
msgh_size = (mach_msg_size_t)(sizeof(Request) - 912) + msgh_size_delta;
|
||||
InP = (Request *) ((pointer_t) InP + msgh_size_delta - 16);
|
||||
|
||||
InP->flavor = *flavor;
|
||||
|
||||
if (old_stateCnt > 224) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);
|
||||
|
||||
InP->old_stateCnt = old_stateCnt;
|
||||
|
||||
msgh_size += (4 * old_stateCnt);
|
||||
InP = &Mess.In;
|
||||
InP->Head.msgh_bits =
|
||||
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
/* msgh_size passed as argument */
|
||||
InP->Head.msgh_request_port = exception_port;
|
||||
InP->Head.msgh_reply_port = mig_get_reply_port();
|
||||
InP->Head.msgh_id = 2406;
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifdef USING_VOUCHERS
|
||||
if (voucher_mach_msg_set != NULL) {
|
||||
voucher_mach_msg_set(&InP->Head);
|
||||
}
|
||||
#endif // USING_VOUCHERS
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
__BeforeSendRpc(2406, "mach_exception_raise_state")
|
||||
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
__AfterSendRpc(2406, "mach_exception_raise_state")
|
||||
if (msg_result != MACH_MSG_SUCCESS) {
|
||||
__MachMsgErrorWithoutTimeout(msg_result);
|
||||
{ return msg_result; }
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MIG_check__Reply__mach_exception_raise_state_t__defined)
|
||||
check_result = __MIG_check__Reply__mach_exception_raise_state_t((__Reply__mach_exception_raise_state_t *)Out0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ return check_result; }
|
||||
#endif /* defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) */
|
||||
|
||||
*flavor = Out0P->flavor;
|
||||
|
||||
if (Out0P->new_stateCnt > 224) {
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224);
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);
|
||||
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Reply__mach_exc_subsystem__
|
||||
#if !defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined)
|
||||
#define __MIG_check__Reply__mach_exception_raise_state_identity_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_state_identity_t(__Reply__mach_exception_raise_state_identity_t *Out0P)
|
||||
{
|
||||
|
||||
typedef __Reply__mach_exception_raise_state_identity_t __Reply;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->Head.msgh_id != 2507) {
|
||||
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
|
||||
{ return MIG_SERVER_DIED; }
|
||||
else
|
||||
{ return MIG_REPLY_MISMATCH; }
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = Out0P->Head.msgh_size;
|
||||
|
||||
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) &&
|
||||
(msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
|
||||
Out0P->RetCode == KERN_SUCCESS)))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->RetCode != KERN_SUCCESS) {
|
||||
return ((mig_reply_error_t *)Out0P)->RetCode;
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
if ( Out0P->new_stateCnt > 224 )
|
||||
return MIG_TYPE_ERROR;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) */
|
||||
#endif /* __MIG_check__Reply__mach_exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine mach_exception_raise_state_identity */
|
||||
mig_external kern_return_t mach_exception_raise_state_identity
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
union {
|
||||
Request In;
|
||||
Reply Out;
|
||||
} Mess;
|
||||
|
||||
Request *InP = &Mess.In;
|
||||
Reply *Out0P = &Mess.Out;
|
||||
|
||||
mach_msg_return_t msg_result;
|
||||
unsigned int msgh_size;
|
||||
unsigned int msgh_size_delta;
|
||||
|
||||
|
||||
#ifdef __MIG_check__Reply__mach_exception_raise_state_identity_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Reply__mach_exception_raise_state_identity_t__defined */
|
||||
|
||||
__DeclareSendRpc(2407, "mach_exception_raise_state_identity")
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t threadTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t taskTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->msgh_body.msgh_descriptor_count = 2;
|
||||
#if UseStaticTemplates
|
||||
InP->thread = threadTemplate;
|
||||
InP->thread.name = thread;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->thread.name = thread;
|
||||
InP->thread.disposition = 19;
|
||||
InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
InP->task = taskTemplate;
|
||||
InP->task.name = task;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->task.name = task;
|
||||
InP->task.disposition = 19;
|
||||
InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->NDR = NDR_record;
|
||||
|
||||
InP->exception = exception;
|
||||
|
||||
if (codeCnt > 2) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);
|
||||
|
||||
InP->codeCnt = codeCnt;
|
||||
|
||||
msgh_size_delta = (8 * codeCnt);
|
||||
msgh_size = (mach_msg_size_t)(sizeof(Request) - 912) + msgh_size_delta;
|
||||
InP = (Request *) ((pointer_t) InP + msgh_size_delta - 16);
|
||||
|
||||
InP->flavor = *flavor;
|
||||
|
||||
if (old_stateCnt > 224) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);
|
||||
|
||||
InP->old_stateCnt = old_stateCnt;
|
||||
|
||||
msgh_size += (4 * old_stateCnt);
|
||||
InP = &Mess.In;
|
||||
InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
|
||||
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
/* msgh_size passed as argument */
|
||||
InP->Head.msgh_request_port = exception_port;
|
||||
InP->Head.msgh_reply_port = mig_get_reply_port();
|
||||
InP->Head.msgh_id = 2407;
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifdef USING_VOUCHERS
|
||||
if (voucher_mach_msg_set != NULL) {
|
||||
voucher_mach_msg_set(&InP->Head);
|
||||
}
|
||||
#endif // USING_VOUCHERS
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
__BeforeSendRpc(2407, "mach_exception_raise_state_identity")
|
||||
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
__AfterSendRpc(2407, "mach_exception_raise_state_identity")
|
||||
if (msg_result != MACH_MSG_SUCCESS) {
|
||||
__MachMsgErrorWithoutTimeout(msg_result);
|
||||
{ return msg_result; }
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined)
|
||||
check_result = __MIG_check__Reply__mach_exception_raise_state_identity_t((__Reply__mach_exception_raise_state_identity_t *)Out0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ return check_result; }
|
||||
#endif /* defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) */
|
||||
|
||||
*flavor = Out0P->flavor;
|
||||
|
||||
if (Out0P->new_stateCnt > 224) {
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224);
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);
|
||||
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
305
proctl/proctl.go
305
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 := dbp.Threads[pid]
|
||||
thread, ok := dbp.Threads[pid]
|
||||
if !ok {
|
||||
return fmt.Errorf("could not find thread for %d", pid)
|
||||
}
|
||||
|
||||
if pid != dbp.CurrentThread.Id {
|
||||
fmt.Printf("thread context changed from %d to %d\n", dbp.CurrentThread.Id, pid)
|
||||
fmt.Printf("thread context changed from %d to %d\n", dbp.CurrentThread.Id, thread.Id)
|
||||
dbp.CurrentThread = thread
|
||||
}
|
||||
|
||||
pc, err := thread.CurrentPC()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get current pc %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Check to see if we hit a runtime.breakpoint
|
||||
@ -457,15 +335,15 @@ func handleBreakPoint(dbp *DebuggedProcess, pid int) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
stopTheWorld(dbp)
|
||||
dbp.Halt()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check for hardware breakpoint
|
||||
for _, bp := range dbp.HWBreakPoints {
|
||||
if bp.Addr == pc {
|
||||
if bp != nil && bp.Addr == pc {
|
||||
if !bp.temp {
|
||||
stopTheWorld(dbp)
|
||||
return dbp.Halt()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -473,81 +351,10 @@ func handleBreakPoint(dbp *DebuggedProcess, pid int) error {
|
||||
// Check to see if we have hit a software breakpoint.
|
||||
if bp, ok := dbp.BreakPoints[pc-1]; ok {
|
||||
if !bp.temp {
|
||||
stopTheWorld(dbp)
|
||||
return dbp.Halt()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("did not hit recognized breakpoint")
|
||||
}
|
||||
|
||||
// Ensure execution of every traced thread is halted.
|
||||
func stopTheWorld(dbp *DebuggedProcess) error {
|
||||
// Loop through all threads and ensure that we
|
||||
// stop the rest of them, so that by the time
|
||||
// we return control to the user, all threads
|
||||
// are inactive. We send SIGSTOP and ensure all
|
||||
// threads are in in signal-delivery-stop mode.
|
||||
for _, th := range dbp.Threads {
|
||||
if stopped(th.Id) {
|
||||
continue
|
||||
}
|
||||
err := sys.Tgkill(dbp.Pid, th.Id, sys.SIGSTOP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pid, _, err := wait(th.Id, sys.WNOHANG)
|
||||
if err != nil {
|
||||
return fmt.Errorf("wait err %s %d", err, pid)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addNewThread(dbp *DebuggedProcess, pid int) error {
|
||||
// A traced thread has cloned a new thread, grab the pid and
|
||||
// add it to our list of traced threads.
|
||||
msg, err := sys.PtraceGetEventMsg(pid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get event message: %s", err)
|
||||
}
|
||||
fmt.Println("new thread spawned", msg)
|
||||
|
||||
_, err = dbp.addThread(int(msg))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = sys.PtraceCont(int(msg), 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not continue new thread %d %s", msg, err)
|
||||
}
|
||||
|
||||
// Here we loop for a while to ensure that the once we continue
|
||||
// the newly created thread, we allow enough time for the runtime
|
||||
// to assign m->procid. This is important because we rely on
|
||||
// looping through runtime.allm in other parts of the code, so
|
||||
// we require that this is set before we do anything else.
|
||||
// TODO(dp): we might be able to eliminate this loop by telling
|
||||
// the CPU to emit a breakpoint exception on write to this location
|
||||
// in memory. That way we prevent having to loop, and can be
|
||||
// notified as soon as m->procid is set.
|
||||
th := dbp.Threads[pid]
|
||||
for {
|
||||
allm, _ := th.AllM()
|
||||
for _, m := range allm {
|
||||
if m.procid == int(msg) {
|
||||
// Continue the thread that cloned
|
||||
return sys.PtraceCont(pid, 0)
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func wait(pid, options int) (int, *sys.WaitStatus, error) {
|
||||
var status sys.WaitStatus
|
||||
wpid, err := sys.Wait4(pid, &status, sys.WALL|options, nil)
|
||||
return wpid, &status, err
|
||||
return fmt.Errorf("unrecognized breakpoint %#v", pc)
|
||||
}
|
||||
|
204
proctl/proctl_darwin.c
Normal file
204
proctl/proctl_darwin.c
Normal file
@ -0,0 +1,204 @@
|
||||
#include "proctl_darwin.h"
|
||||
|
||||
|
||||
static const unsigned char info_plist[]
|
||||
__attribute__ ((section ("__TEXT,__info_plist"),used)) =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\""
|
||||
" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
|
||||
"<plist version=\"1.0\">\n"
|
||||
"<dict>\n"
|
||||
" <key>CFBundleIdentifier</key>\n"
|
||||
" <string>org.dlv</string>\n"
|
||||
" <key>CFBundleName</key>\n"
|
||||
" <string>delve</string>\n"
|
||||
" <key>CFBundleVersion</key>\n"
|
||||
" <string>1.0</string>\n"
|
||||
" <key>SecTaskAccess</key>\n"
|
||||
" <array>\n"
|
||||
" <string>allowed</string>\n"
|
||||
" <string>debug</string>\n"
|
||||
" </array>\n"
|
||||
"</dict>\n"
|
||||
"</plist>\n";
|
||||
|
||||
static thread_act_t _global_thread;
|
||||
|
||||
kern_return_t
|
||||
acquire_mach_task(int tid, mach_port_name_t *task, mach_port_t *exception_port) {
|
||||
kern_return_t kret;
|
||||
mach_port_t self = mach_task_self();
|
||||
|
||||
kret = task_for_pid(self, tid, task);
|
||||
if (kret != KERN_SUCCESS) return kret;
|
||||
|
||||
kret = mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, exception_port);
|
||||
if (kret != KERN_SUCCESS) return kret;
|
||||
|
||||
kret = mach_port_insert_right(self, *exception_port, *exception_port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
if (kret != KERN_SUCCESS) return kret;
|
||||
|
||||
// Set exception port
|
||||
return task_set_exception_ports(*task, EXC_MASK_BREAKPOINT|EXC_MASK_SOFTWARE, *exception_port,
|
||||
EXCEPTION_DEFAULT, THREAD_STATE_NONE);
|
||||
}
|
||||
|
||||
char *
|
||||
find_executable(int pid) {
|
||||
static char pathbuf[PATH_MAX];
|
||||
proc_pidpath(pid, pathbuf, PATH_MAX);
|
||||
return pathbuf;
|
||||
}
|
||||
|
||||
kern_return_t
|
||||
get_threads(task_t task, void *slice) {
|
||||
kern_return_t kret;
|
||||
thread_act_array_t list;
|
||||
mach_msg_type_number_t count;
|
||||
|
||||
kret = task_threads(task, &list, &count);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
return kret;
|
||||
}
|
||||
|
||||
memcpy(slice, (void*)list, count*sizeof(list[0]));
|
||||
return (kern_return_t)0;
|
||||
}
|
||||
|
||||
int
|
||||
thread_count(task_t task) {
|
||||
kern_return_t kret;
|
||||
thread_act_array_t list;
|
||||
mach_msg_type_number_t count;
|
||||
|
||||
// TODO(dp) vm_deallocate list
|
||||
kret = task_threads(task, &list, &count);
|
||||
if (kret != KERN_SUCCESS) return -1;
|
||||
return count;
|
||||
}
|
||||
|
||||
typedef struct exc_msg {
|
||||
mach_msg_header_t Head;
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
exception_data_t code;
|
||||
char pad[512];
|
||||
} exc_msg_t;
|
||||
|
||||
thread_act_t
|
||||
mach_port_wait(mach_port_t port) {
|
||||
puts("begin mach wait");
|
||||
mach_msg_return_t msg = mach_msg_server_once(exc_server, sizeof(exc_msg_t), port, MACH_MSG_TIMEOUT_NONE);
|
||||
if (msg != MACH_MSG_SUCCESS) {
|
||||
}
|
||||
puts("fin mach wait");
|
||||
return _global_thread;
|
||||
}
|
||||
|
||||
// 64 bit exception handlers
|
||||
|
||||
kern_return_t
|
||||
catch_mach_exception_raise(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt)
|
||||
{
|
||||
puts("caught exception raise");
|
||||
fprintf(stderr, "My exception handler was called by exception_raise()\n");
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
kern_return_t
|
||||
catch_mach_exception_raise_state(
|
||||
mach_port_t exception_port,
|
||||
exception_type_t exception,
|
||||
const mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
const thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt)
|
||||
{
|
||||
puts("caught raise state");
|
||||
fprintf(stderr, "My exception handler was called by exception_raise()\n");
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
kern_return_t
|
||||
catch_mach_exception_raise_state_identity(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt)
|
||||
{
|
||||
puts("caught identity");
|
||||
fprintf(stderr, "My exception handler was called by exception_raise()\n");
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
// 32 bit exception handlers
|
||||
|
||||
kern_return_t
|
||||
catch_exception_raise(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt)
|
||||
{
|
||||
_global_thread = (thread_act_t)thread;
|
||||
thread_suspend(thread);
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
kern_return_t
|
||||
catch_exception_raise_state(
|
||||
mach_port_t exception_port,
|
||||
exception_type_t exception,
|
||||
const mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
const thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt)
|
||||
{
|
||||
puts("caught raise state");
|
||||
fprintf(stderr, "My exception handler was called by exception_raise()\n");
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
kern_return_t
|
||||
catch_exception_raise_state_identity(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt)
|
||||
{
|
||||
puts("caught identity");
|
||||
fprintf(stderr, "My exception handler was called by exception_raise()\n");
|
||||
return KERN_SUCCESS;
|
||||
}
|
223
proctl/proctl_darwin.go
Normal file
223
proctl/proctl_darwin.go
Normal file
@ -0,0 +1,223 @@
|
||||
package proctl
|
||||
|
||||
// #include "proctl_darwin.h"
|
||||
import "C"
|
||||
import (
|
||||
"debug/gosym"
|
||||
"debug/macho"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/frame"
|
||||
sys "golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type OSProcessDetails struct {
|
||||
task C.mach_port_name_t
|
||||
exceptionPort C.mach_port_t
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) Halt() (err error) {
|
||||
for _, th := range dbp.Threads {
|
||||
err := th.Halt()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Finds the executable and then uses it
|
||||
// to parse the following information:
|
||||
// * Dwarf .debug_frame section
|
||||
// * Dwarf .debug_line section
|
||||
// * Go symbol table.
|
||||
func (dbp *DebuggedProcess) LoadInformation() error {
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
exe *macho.File
|
||||
err error
|
||||
)
|
||||
|
||||
if err := dbp.acquireMachTask(); err != nil {
|
||||
return fmt.Errorf("could not acquire mach task")
|
||||
}
|
||||
exe, err = dbp.findExecutable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := exe.DWARF()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dbp.Dwarf = data
|
||||
|
||||
wg.Add(2)
|
||||
go dbp.parseDebugFrame(exe, &wg)
|
||||
go dbp.obtainGoSymbols(exe, &wg)
|
||||
wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns a new DebuggedProcess struct.
|
||||
func newDebugProcess(pid int, attach bool) (*DebuggedProcess, error) {
|
||||
dbp := DebuggedProcess{
|
||||
Pid: pid,
|
||||
Threads: make(map[int]*ThreadContext),
|
||||
BreakPoints: make(map[uint64]*BreakPoint),
|
||||
os: new(OSProcessDetails),
|
||||
}
|
||||
|
||||
proc, err := os.FindProcess(pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dbp.Process = proc
|
||||
err = dbp.LoadInformation()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := dbp.updateThreadList(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &dbp, nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) updateThreadList() error {
|
||||
var (
|
||||
err error
|
||||
kret C.kern_return_t
|
||||
th *ThreadContext
|
||||
count = C.thread_count(C.task_t(dbp.os.task))
|
||||
list = make([]uint32, count)
|
||||
)
|
||||
|
||||
// TODO(dp) might be better to malloc mem in C and them free it here
|
||||
// instead of getting count above and passing in a slice
|
||||
kret = C.get_threads(C.task_t(dbp.os.task), unsafe.Pointer(&list[0]))
|
||||
if kret != C.KERN_SUCCESS {
|
||||
return fmt.Errorf("could not get thread list")
|
||||
}
|
||||
if count < 0 {
|
||||
return fmt.Errorf("could not get thread list")
|
||||
}
|
||||
|
||||
for _, port := range list {
|
||||
th, err = dbp.addThread(int(port), false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(dp) account for GOMAXPROCS=1 or attaching to pid
|
||||
if count == 1 {
|
||||
dbp.CurrentThread = th
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) acquireMachTask() error {
|
||||
if ret := C.acquire_mach_task(C.int(dbp.Pid), &dbp.os.task, &dbp.os.exceptionPort); ret != C.KERN_SUCCESS {
|
||||
return fmt.Errorf("could not acquire mach task %d", ret)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// export addThread
|
||||
func (dbp *DebuggedProcess) addThread(port int, attach bool) (*ThreadContext, error) {
|
||||
thread := &ThreadContext{
|
||||
Id: port,
|
||||
Process: dbp,
|
||||
os: new(OSSpecificDetails),
|
||||
}
|
||||
dbp.Threads[port] = thread
|
||||
thread.os.thread_act = C.thread_act_t(port)
|
||||
return thread, nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) parseDebugFrame(exe *macho.File, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
if sec := exe.Section("__debug_frame"); sec != nil {
|
||||
debugFrame, err := exe.Section("__debug_frame").Data()
|
||||
if err != nil {
|
||||
fmt.Println("could not get __debug_frame section", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
dbp.FrameEntries = frame.Parse(debugFrame)
|
||||
} else {
|
||||
fmt.Println("could not find __debug_frame section in binary")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) obtainGoSymbols(exe *macho.File, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
var (
|
||||
symdat []byte
|
||||
pclndat []byte
|
||||
err error
|
||||
)
|
||||
|
||||
if sec := exe.Section("__gosymtab"); sec != nil {
|
||||
symdat, err = sec.Data()
|
||||
if err != nil {
|
||||
fmt.Println("could not get .gosymtab section", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if sec := exe.Section("__gopclntab"); sec != nil {
|
||||
pclndat, err = sec.Data()
|
||||
if err != nil {
|
||||
fmt.Println("could not get .gopclntab section", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
pcln := gosym.NewLineTable(pclndat, exe.Section("__text").Addr)
|
||||
tab, err := gosym.NewTable(symdat, pcln)
|
||||
if err != nil {
|
||||
fmt.Println("could not get initialize line table", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dbp.GoSymTable = tab
|
||||
}
|
||||
|
||||
// TODO(darwin) IMPLEMENT ME
|
||||
func stopped(pid int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) findExecutable() (*macho.File, error) {
|
||||
pathptr, err := C.find_executable(C.int(dbp.Pid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return macho.Open(C.GoString(pathptr))
|
||||
}
|
||||
|
||||
func trapWait(dbp *DebuggedProcess, pid int) (int, *sys.WaitStatus, error) {
|
||||
port := C.mach_port_wait(dbp.os.exceptionPort)
|
||||
if port == 0 {
|
||||
return -1, nil, fmt.Errorf("mach port wait error")
|
||||
}
|
||||
|
||||
dbp.updateThreadList()
|
||||
return int(port), nil, nil
|
||||
}
|
||||
|
||||
func wait(pid, options int) (int, *sys.WaitStatus, error) {
|
||||
var status sys.WaitStatus
|
||||
wpid, err := sys.Wait4(pid, &status, options, nil)
|
||||
return wpid, &status, err
|
||||
}
|
41
proctl/proctl_darwin.h
Normal file
41
proctl/proctl_darwin.h
Normal file
@ -0,0 +1,41 @@
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <libproc.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_vm.h>
|
||||
#include "mach_exc.h"
|
||||
#include "exc.h"
|
||||
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
boolean_t exc_server(
|
||||
mach_msg_header_t *InHeadP,
|
||||
mach_msg_header_t *OutHeadP);
|
||||
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
boolean_t mach_exc_server(
|
||||
mach_msg_header_t *InHeadP,
|
||||
mach_msg_header_t *OutHeadP);
|
||||
|
||||
kern_return_t
|
||||
acquire_mach_task(int, mach_port_name_t *, mach_port_t *);
|
||||
|
||||
char *
|
||||
find_executable(int pid);
|
||||
|
||||
kern_return_t
|
||||
get_threads(task_t task, void *);
|
||||
|
||||
int
|
||||
thread_count(task_t task);
|
||||
|
||||
thread_act_t
|
||||
mach_port_wait(mach_port_t);
|
367
proctl/proctl_linux.go
Normal file
367
proctl/proctl_linux.go
Normal file
@ -0,0 +1,367 @@
|
||||
package proctl
|
||||
|
||||
import (
|
||||
"debug/elf"
|
||||
"debug/gosym"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
sys "golang.org/x/sys/unix"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/frame"
|
||||
)
|
||||
|
||||
const (
|
||||
STATUS_SLEEPING = 'S'
|
||||
STATUS_RUNNING = 'R'
|
||||
STATUS_TRACE_STOP = 't'
|
||||
)
|
||||
|
||||
// Not actually needed for Linux.
|
||||
type OSProcessDetails interface{}
|
||||
|
||||
func (dbp *DebuggedProcess) Halt() (err error) {
|
||||
for _, th := range dbp.Threads {
|
||||
err := th.Halt()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Steps through process.
|
||||
func (dbp *DebuggedProcess) Step() (err error) {
|
||||
var (
|
||||
th *ThreadContext
|
||||
ok bool
|
||||
)
|
||||
|
||||
allm, err := dbp.CurrentThread.AllM()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fn := func() error {
|
||||
for _, m := range allm {
|
||||
th, ok = dbp.Threads[m.procid]
|
||||
fmt.Println(ok, m.procid)
|
||||
if !ok {
|
||||
if m.procid == 0 {
|
||||
// TODO(dp) might not work for linux
|
||||
th = dbp.Threads[dbp.CurrentThread.Id]
|
||||
}
|
||||
return fmt.Errorf("m->procid is invalid port")
|
||||
}
|
||||
|
||||
if m.blocked == 0 {
|
||||
err := th.Step()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return dbp.run(fn)
|
||||
}
|
||||
|
||||
// Finds the executable from /proc/<pid>/exe and then
|
||||
// uses that to parse the following information:
|
||||
// * Dwarf .debug_frame section
|
||||
// * Dwarf .debug_line section
|
||||
// * Go symbol table.
|
||||
func (dbp *DebuggedProcess) LoadInformation() error {
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
exe *elf.File
|
||||
err error
|
||||
)
|
||||
|
||||
exe, err = dbp.findExecutable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wg.Add(2)
|
||||
go dbp.parseDebugFrame(exe, &wg)
|
||||
go dbp.obtainGoSymbols(exe, &wg)
|
||||
wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Attach to a newly created thread, and store that thread in our list of
|
||||
// known threads.
|
||||
func (dbp *DebuggedProcess) addThread(tid int, attach bool) (*ThreadContext, error) {
|
||||
if thread, ok := dbp.Threads[tid]; ok {
|
||||
return thread, nil
|
||||
}
|
||||
|
||||
if attach {
|
||||
err := sys.PtraceAttach(tid)
|
||||
if err != nil && err != sys.EPERM {
|
||||
// Do not return err if err == EPERM,
|
||||
// we may already be tracing this thread due to
|
||||
// PTRACE_O_TRACECLONE. We will surely blow up later
|
||||
// if we truly don't have permissions.
|
||||
return nil, fmt.Errorf("could not attach to new thread %d %s", tid, err)
|
||||
}
|
||||
|
||||
pid, status, err := wait(tid, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if status.Exited() {
|
||||
return nil, fmt.Errorf("thread already exited %d", pid)
|
||||
}
|
||||
}
|
||||
|
||||
err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE)
|
||||
if err == syscall.ESRCH {
|
||||
_, _, err = wait(tid, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while waiting after adding thread: %d %s", tid, err)
|
||||
}
|
||||
|
||||
err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not set options for new traced thread %d %s", tid, err)
|
||||
}
|
||||
}
|
||||
|
||||
dbp.Threads[tid] = &ThreadContext{
|
||||
Id: tid,
|
||||
Process: dbp,
|
||||
}
|
||||
|
||||
return dbp.Threads[tid], nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) refreshThreadList() error {
|
||||
allm, err := dbp.CurrentThread.AllM()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, m := range allm {
|
||||
if tid == 0 {
|
||||
continue
|
||||
}
|
||||
if _, err := dbp.addThread(m.procid, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) findExecutable() (*elf.File, error) {
|
||||
procpath := fmt.Sprintf("/proc/%d/exe", dbp.Pid)
|
||||
|
||||
f, err := os.OpenFile(procpath, 0, os.ModePerm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
elffile, err := elf.NewFile(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := elffile.DWARF()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dbp.Dwarf = data
|
||||
|
||||
return elffile, nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) parseDebugFrame(exe *elf.File, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
if sec := exe.Section(".debug_frame"); sec != nil {
|
||||
debugFrame, err := exe.Section(".debug_frame").Data()
|
||||
if err != nil {
|
||||
fmt.Println("could not get .debug_frame section", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
dbp.FrameEntries = frame.Parse(debugFrame)
|
||||
} else {
|
||||
fmt.Println("could not find .debug_frame section in binary")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) obtainGoSymbols(exe *elf.File, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
var (
|
||||
symdat []byte
|
||||
pclndat []byte
|
||||
err error
|
||||
)
|
||||
|
||||
if sec := exe.Section(".gosymtab"); sec != nil {
|
||||
symdat, err = sec.Data()
|
||||
if err != nil {
|
||||
fmt.Println("could not get .gosymtab section", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if sec := exe.Section(".gopclntab"); sec != nil {
|
||||
pclndat, err = sec.Data()
|
||||
if err != nil {
|
||||
fmt.Println("could not get .gopclntab section", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
pcln := gosym.NewLineTable(pclndat, exe.Section(".text").Addr)
|
||||
tab, err := gosym.NewTable(symdat, pcln)
|
||||
if err != nil {
|
||||
fmt.Println("could not get initialize line table", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dbp.GoSymTable = tab
|
||||
}
|
||||
|
||||
func newDebugProcess(pid int, attach bool) (*DebuggedProcess, error) {
|
||||
dbp := DebuggedProcess{
|
||||
Pid: pid,
|
||||
Threads: make(map[int]*ThreadContext),
|
||||
BreakPoints: make(map[uint64]*BreakPoint),
|
||||
os: new(OSProcessDetails),
|
||||
}
|
||||
|
||||
if attach {
|
||||
thread, err := dbp.AttachThread(pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dbp.CurrentThread = thread
|
||||
} else {
|
||||
thread, err := dbp.addThread(pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dbp.CurrentThread = thread
|
||||
}
|
||||
|
||||
proc, err := os.FindProcess(pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dbp.Process = proc
|
||||
err = dbp.LoadInformation()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &dbp, nil
|
||||
}
|
||||
|
||||
func addNewThread(dbp *DebuggedProcess, cloner, cloned int) error {
|
||||
fmt.Println("new thread spawned", cloned)
|
||||
|
||||
th, err := dbp.addThread(cloned)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = th.Continue()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not continue new thread %d %s", cloned, err)
|
||||
}
|
||||
|
||||
// Here we loop for a while to ensure that the once we continue
|
||||
// the newly created thread, we allow enough time for the runtime
|
||||
// to assign m->procid. This is important because we rely on
|
||||
// looping through runtime.allm in other parts of the code, so
|
||||
// we require that this is set before we do anything else.
|
||||
// TODO(dp): we might be able to eliminate this loop by telling
|
||||
// the CPU to emit a breakpoint exception on write to this location
|
||||
// in memory. That way we prevent having to loop, and can be
|
||||
// notified as soon as m->procid is set.
|
||||
// TODO(dp) get rid of this hack
|
||||
th = dbp.Threads[cloner]
|
||||
for {
|
||||
allm, _ := th.AllM()
|
||||
for _, m := range allm {
|
||||
if m.procid == cloned {
|
||||
// Continue the thread that cloned
|
||||
return th.Continue()
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func stopped(pid int) bool {
|
||||
f, err := os.Open(fmt.Sprintf("/proc/%d/stat", pid))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var (
|
||||
p int
|
||||
comm string
|
||||
state rune
|
||||
)
|
||||
fmt.Fscanf(f, "%d %s %c", &p, &comm, &state)
|
||||
if state == STATUS_TRACE_STOP {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func trapWait(dbp *DebuggedProcess, pid int) (int, *sys.WaitStatus, error) {
|
||||
for {
|
||||
wpid, status, err := wait(pid, 0)
|
||||
if err != nil {
|
||||
return -1, nil, fmt.Errorf("wait err %s %d", err, pid)
|
||||
}
|
||||
if wpid == 0 {
|
||||
continue
|
||||
}
|
||||
if th, ok := dbp.Threads[wpid]; ok {
|
||||
th.Status = status
|
||||
}
|
||||
if status.Exited() && wpid == dbp.Pid {
|
||||
return -1, status, ProcessExitedError{wpid}
|
||||
}
|
||||
if status.StopSignal() == sys.SIGTRAP && status.TrapCause() == sys.PTRACE_EVENT_CLONE {
|
||||
// A traced thread has cloned a new thread, grab the pid and
|
||||
// add it to our list of traced threads.
|
||||
tid, err := sys.PtraceGetEventMsg(wpid)
|
||||
if err != nil {
|
||||
return -1, nil, fmt.Errorf("could not get event message: %s", err)
|
||||
}
|
||||
err = addNewThread(dbp, wpid, int(tid))
|
||||
if err != nil {
|
||||
return -1, nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if status.StopSignal() == sys.SIGTRAP {
|
||||
return wpid, status, nil
|
||||
}
|
||||
if status.StopSignal() == sys.SIGSTOP && dbp.halt {
|
||||
return -1, nil, ManualStopError{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func wait(pid, options int) (int, *sys.WaitStatus, error) {
|
||||
var status sys.WaitStatus
|
||||
wpid, err := sys.Wait4(pid, &status, sys.WALL|options, nil)
|
||||
return wpid, &status, err
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
package proctl
|
||||
|
||||
import (
|
||||
"debug/elf"
|
||||
"debug/gosym"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/frame"
|
||||
)
|
||||
|
||||
const (
|
||||
STATUS_SLEEPING = 'S'
|
||||
STATUS_RUNNING = 'R'
|
||||
STATUS_TRACE_STOP = 't'
|
||||
)
|
||||
|
||||
func (dbp *DebuggedProcess) addThread(tid int) (*ThreadContext, error) {
|
||||
err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE)
|
||||
if err == syscall.ESRCH {
|
||||
_, _, err = wait(tid, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while waiting after adding thread: %d %s", tid, err)
|
||||
}
|
||||
|
||||
err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not set options for new traced thread %d %s", tid, err)
|
||||
}
|
||||
}
|
||||
|
||||
dbp.Threads[tid] = &ThreadContext{
|
||||
Id: tid,
|
||||
Process: dbp,
|
||||
}
|
||||
|
||||
return dbp.Threads[tid], nil
|
||||
}
|
||||
|
||||
func stopped(pid int) bool {
|
||||
f, err := os.Open(fmt.Sprintf("/proc/%d/stat", pid))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var (
|
||||
p int
|
||||
comm string
|
||||
state rune
|
||||
)
|
||||
fmt.Fscanf(f, "%d %s %c", &p, &comm, &state)
|
||||
if state == STATUS_TRACE_STOP {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Finds the executable from /proc/<pid>/exe and then
|
||||
// uses that to parse the following information:
|
||||
// * Dwarf .debug_frame section
|
||||
// * Dwarf .debug_line section
|
||||
// * Go symbol table.
|
||||
func (dbp *DebuggedProcess) LoadInformation() error {
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
exe *elf.File
|
||||
err error
|
||||
)
|
||||
|
||||
exe, err = dbp.findExecutable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wg.Add(2)
|
||||
go dbp.parseDebugFrame(exe, &wg)
|
||||
go dbp.obtainGoSymbols(exe, &wg)
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) findExecutable() (*elf.File, error) {
|
||||
procpath := fmt.Sprintf("/proc/%d/exe", dbp.Pid)
|
||||
|
||||
f, err := os.OpenFile(procpath, 0, os.ModePerm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
elffile, err := elf.NewFile(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := elffile.DWARF()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dbp.Dwarf = data
|
||||
|
||||
return elffile, nil
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) parseDebugFrame(exe *elf.File, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
if sec := exe.Section(".debug_frame"); sec != nil {
|
||||
debugFrame, err := exe.Section(".debug_frame").Data()
|
||||
if err != nil {
|
||||
fmt.Println("could not get .debug_frame section", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
dbp.FrameEntries = frame.Parse(debugFrame)
|
||||
} else {
|
||||
fmt.Println("could not find .debug_frame section in binary")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *DebuggedProcess) obtainGoSymbols(exe *elf.File, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
var (
|
||||
symdat []byte
|
||||
pclndat []byte
|
||||
err error
|
||||
)
|
||||
|
||||
if sec := exe.Section(".gosymtab"); sec != nil {
|
||||
symdat, err = sec.Data()
|
||||
if err != nil {
|
||||
fmt.Println("could not get .gosymtab section", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if sec := exe.Section(".gopclntab"); sec != nil {
|
||||
pclndat, err = sec.Data()
|
||||
if err != nil {
|
||||
fmt.Println("could not get .gopclntab section", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
pcln := gosym.NewLineTable(pclndat, exe.Section(".text").Addr)
|
||||
tab, err := gosym.NewTable(symdat, pcln)
|
||||
if err != nil {
|
||||
fmt.Println("could not get initialize line table", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dbp.GoSymTable = tab
|
||||
}
|
@ -3,6 +3,7 @@ package proctl
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@ -37,9 +38,9 @@ func getRegisters(p *DebuggedProcess, t *testing.T) Registers {
|
||||
return regs
|
||||
}
|
||||
|
||||
func dataAtAddr(pid int, addr uint64) ([]byte, error) {
|
||||
func dataAtAddr(thread *ThreadContext, addr uint64) ([]byte, error) {
|
||||
data := make([]byte, 1)
|
||||
_, err := readMemory(pid, uintptr(addr), data)
|
||||
_, err := readMemory(thread, uintptr(addr), data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -78,12 +79,16 @@ func TestStep(t *testing.T) {
|
||||
|
||||
_, err := p.Break(helloworldaddr)
|
||||
assertNoError(err, t, "Break()")
|
||||
fmt.Println("continue")
|
||||
assertNoError(p.Continue(), t, "Continue()")
|
||||
fmt.Println("fin continue")
|
||||
|
||||
regs := getRegisters(p, t)
|
||||
rip := regs.PC()
|
||||
|
||||
fmt.Println("begin step")
|
||||
err = p.Step()
|
||||
fmt.Println("fin step")
|
||||
assertNoError(err, t, "Step()")
|
||||
|
||||
regs = getRegisters(p, t)
|
||||
@ -110,36 +115,21 @@ func TestContinue(t *testing.T) {
|
||||
|
||||
func TestBreakPoint(t *testing.T) {
|
||||
withTestProcess("../_fixtures/testprog", t, func(p *DebuggedProcess) {
|
||||
sleepytimefunc := p.GoSymTable.LookupFunc("main.helloworld")
|
||||
sleepyaddr := sleepytimefunc.Entry
|
||||
helloworldfunc := p.GoSymTable.LookupFunc("main.helloworld")
|
||||
helloworldaddr := helloworldfunc.Entry
|
||||
|
||||
bp, err := p.Break(sleepyaddr)
|
||||
bp, err := p.Break(helloworldaddr)
|
||||
assertNoError(err, t, "Break()")
|
||||
|
||||
breakpc := bp.Addr
|
||||
err = p.Continue()
|
||||
assertNoError(err, t, "Continue()")
|
||||
assertNoError(p.Continue(), t, "Continue()")
|
||||
|
||||
pc, err := p.CurrentPC()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if pc != breakpc {
|
||||
if pc-1 != bp.Addr {
|
||||
f, l, _ := p.GoSymTable.PCToLine(pc)
|
||||
t.Fatalf("Break not respected:\nPC:%#v %s:%d\nFN:%#v \n", pc, f, l, breakpc)
|
||||
}
|
||||
|
||||
err = p.Step()
|
||||
assertNoError(err, t, "Step()")
|
||||
|
||||
pc, err = p.CurrentPC()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if pc == breakpc {
|
||||
t.Fatalf("Step not respected:\nPC:%d\nFN:%d\n", pc, breakpc)
|
||||
t.Fatalf("Break not respected:\nPC:%#v %s:%d\nFN:%#v \n", pc, f, l, bp.Addr)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -151,6 +141,7 @@ func TestBreakPointInSeperateGoRoutine(t *testing.T) {
|
||||
t.Fatal("No fn exists")
|
||||
}
|
||||
|
||||
fmt.Printf("pid is %d set breakpoint for fn at %d\n", p.Pid, fn.Entry)
|
||||
_, err := p.Break(fn.Entry)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -191,7 +182,7 @@ func TestClearBreakPoint(t *testing.T) {
|
||||
bp, err = p.Clear(fn.Entry)
|
||||
assertNoError(err, t, "Clear()")
|
||||
|
||||
data, err := dataAtAddr(p.Pid, bp.Addr)
|
||||
data, err := dataAtAddr(p.CurrentThread, bp.Addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -249,6 +240,7 @@ func TestNext(t *testing.T) {
|
||||
|
||||
f, ln := currentLineNumber(p, t)
|
||||
for _, tc := range testcases {
|
||||
fmt.Println("BEGIN-----------------", tc.begin)
|
||||
if ln != tc.begin {
|
||||
t.Fatalf("Program not stopped at correct spot expected %d was %s:%d", tc.begin, f, ln)
|
||||
}
|
||||
@ -316,12 +308,13 @@ func TestFindReturnAddress(t *testing.T) {
|
||||
addr := uint64(int64(regs.SP()) + ret)
|
||||
data := make([]byte, 8)
|
||||
|
||||
readMemory(p.Pid, uintptr(addr), data)
|
||||
readMemory(p.CurrentThread, uintptr(addr), data)
|
||||
addr = binary.LittleEndian.Uint64(data)
|
||||
|
||||
expected := uint64(0x400fbc)
|
||||
if addr != expected {
|
||||
t.Fatalf("return address not found correctly, expected %#v got %#v", expected, addr)
|
||||
linuxExpected := uint64(0x400fbc)
|
||||
darwinExpected := uint64(0x23bc)
|
||||
if addr != linuxExpected && addr != darwinExpected {
|
||||
t.Fatalf("return address not found correctly, expected (linux) %#v or (darwin) %#v got %#v", linuxExpected, darwinExpected, addr)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
23
proctl/ptrace_darwin.go
Normal file
23
proctl/ptrace_darwin.go
Normal file
@ -0,0 +1,23 @@
|
||||
package proctl
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
sys "golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func PtraceCont(tid, sig int) error {
|
||||
_, _, err := sys.Syscall6(sys.SYS_PTRACE, sys.PTRACE_CONT, uintptr(tid), 1, uintptr(sig), 0, 0)
|
||||
if err != syscall.Errno(0) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func PtraceSingleStep(tid int) error {
|
||||
_, _, err := sys.Syscall6(sys.SYS_PTRACE, sys.PT_STEP, uintptr(tid), 1, 0, 0, 0)
|
||||
if err != syscall.Errno(0) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
33
proctl/ptrace_linux.go
Normal file
33
proctl/ptrace_linux.go
Normal file
@ -0,0 +1,33 @@
|
||||
package proctl
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
sys "golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func PtraceCont(tid, sig int) error {
|
||||
return sys.PtraceCont(tid, sig)
|
||||
}
|
||||
|
||||
func PtraceSingleStep(tid int) error {
|
||||
return sys.PtraceSingleStep(tid)
|
||||
}
|
||||
|
||||
func PtracePokeUser(tid int, off, addr uintptr) error {
|
||||
_, _, err := sys.Syscall6(sys.SYS_PTRACE, sys.PTRACE_POKEUSR, uintptr(tid), uintptr(off), uintptr(addr), 0, 0)
|
||||
if err != syscall.Errno(0) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func PtracePeekUser(tid int, off uintptr) (uintptr, error) {
|
||||
var val uintptr
|
||||
_, _, err := syscall.Syscall6(syscall.SYS_PTRACE, syscall.PTRACE_PEEKUSR, uintptr(tid), uintptr(off), uintptr(unsafe.Pointer(&val)), 0, 0)
|
||||
if err != syscall.Errno(0) {
|
||||
return 0, err
|
||||
}
|
||||
return val, nil
|
||||
}
|
27
proctl/registers_darwin_amd64.go
Normal file
27
proctl/registers_darwin_amd64.go
Normal file
@ -0,0 +1,27 @@
|
||||
package proctl
|
||||
|
||||
// #include "threads_darwin.h"
|
||||
import "C"
|
||||
|
||||
type Regs struct {
|
||||
pc, sp uint64
|
||||
}
|
||||
|
||||
func (r *Regs) PC() uint64 {
|
||||
return r.pc
|
||||
}
|
||||
|
||||
func (r *Regs) SP() uint64 {
|
||||
return r.sp
|
||||
}
|
||||
|
||||
func (r *Regs) SetPC(thread *ThreadContext, pc uint64) error {
|
||||
C.set_pc(thread.os.thread_act, C.uint64_t(pc))
|
||||
return nil
|
||||
}
|
||||
|
||||
func registers(thread *ThreadContext) (Registers, error) {
|
||||
state := C.get_registers(C.mach_port_name_t(thread.os.thread_act))
|
||||
regs := &Regs{pc: uint64(state.__rip), sp: uint64(state.__rsp)}
|
||||
return regs, nil
|
||||
}
|
@ -27,15 +27,3 @@ func registers(tid int) (Registers, error) {
|
||||
}
|
||||
return &Regs{®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)
|
||||
}
|
@ -18,6 +18,7 @@ type ThreadContext struct {
|
||||
Id int
|
||||
Process *DebuggedProcess
|
||||
Status *sys.WaitStatus
|
||||
os *OSSpecificDetails
|
||||
}
|
||||
|
||||
// An interface for a generic register type. The
|
||||
@ -27,16 +28,15 @@ type ThreadContext struct {
|
||||
type Registers interface {
|
||||
PC() uint64
|
||||
SP() uint64
|
||||
SetPC(int, uint64) error
|
||||
SetPC(*ThreadContext, uint64) error
|
||||
}
|
||||
|
||||
// Obtains register values from the debugged process.
|
||||
func (thread *ThreadContext) Registers() (Registers, error) {
|
||||
regs, err := registers(thread.Id)
|
||||
regs, err := registers(thread)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get registers %s", err)
|
||||
}
|
||||
|
||||
return regs, nil
|
||||
}
|
||||
|
||||
@ -46,7 +46,6 @@ func (thread *ThreadContext) CurrentPC() (uint64, error) {
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return regs.PC(), nil
|
||||
}
|
||||
|
||||
@ -66,24 +65,6 @@ func (thread *ThreadContext) PrintInfo() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sets a breakpoint at addr, and stores it in the process wide
|
||||
// break point table. Setting a break point must be thread specific due to
|
||||
// ptrace actions needing the thread to be in a signal-delivery-stop.
|
||||
//
|
||||
// Depending on hardware support, Delve will choose to either
|
||||
// set a hardware or software breakpoint. Essentially, if the
|
||||
// hardware supports it, and there are free debug registers, Delve
|
||||
// will set a hardware breakpoint. Otherwise we fall back to software
|
||||
// breakpoints, which are a bit more work for us.
|
||||
func (thread *ThreadContext) Break(addr uint64) (*BreakPoint, error) {
|
||||
return thread.Process.setBreakpoint(thread.Id, addr)
|
||||
}
|
||||
|
||||
// Clears a breakpoint, and removes it from the process level break point table.
|
||||
func (thread *ThreadContext) Clear(addr uint64) (*BreakPoint, error) {
|
||||
return thread.Process.clearBreakpoint(thread.Id, addr)
|
||||
}
|
||||
|
||||
// Continue the execution of this thread. This method takes
|
||||
// software breakpoints into consideration and ensures that
|
||||
// we step over any breakpoints. It will restore the instruction,
|
||||
@ -103,7 +84,7 @@ func (thread *ThreadContext) Continue() error {
|
||||
}
|
||||
}
|
||||
|
||||
return sys.PtraceCont(thread.Id, 0)
|
||||
return thread.cont()
|
||||
}
|
||||
|
||||
// Single steps this thread a single instruction, ensuring that
|
||||
@ -117,29 +98,28 @@ func (thread *ThreadContext) Step() (err error) {
|
||||
bp, ok := thread.Process.BreakPoints[regs.PC()-1]
|
||||
if ok {
|
||||
// Clear the breakpoint so that we can continue execution.
|
||||
_, err = thread.Clear(bp.Addr)
|
||||
_, err = thread.Process.Clear(bp.Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Reset program counter to our restored instruction.
|
||||
err = regs.SetPC(thread.Id, bp.Addr)
|
||||
err = regs.SetPC(thread, bp.Addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not set registers %s", err)
|
||||
}
|
||||
|
||||
// Restore breakpoint now that we have passed it.
|
||||
defer func() {
|
||||
_, err = thread.Break(bp.Addr)
|
||||
_, err = thread.Process.Break(bp.Addr)
|
||||
}()
|
||||
}
|
||||
|
||||
err = sys.PtraceSingleStep(thread.Id)
|
||||
err = thread.singleStep()
|
||||
if err != nil {
|
||||
return fmt.Errorf("step failed: %s", err.Error())
|
||||
}
|
||||
|
||||
_, _, err = wait(thread.Id, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -197,13 +177,9 @@ func (thread *ThreadContext) Next() (err error) {
|
||||
|
||||
func (thread *ThreadContext) continueToReturnAddress(pc uint64, fde *frame.FrameDescriptionEntry) error {
|
||||
for !fde.Cover(pc) {
|
||||
// Our offset here is be 0 because we
|
||||
// have stepped into the first instruction
|
||||
// of this function. Therefore the function
|
||||
// has not had a chance to modify its' stack
|
||||
// and change our offset.
|
||||
// Offset is 0 because we have just stepped into this function.
|
||||
addr := thread.ReturnAddressFromOffset(0)
|
||||
bp, err := thread.Break(addr)
|
||||
bp, err := thread.Process.Break(addr)
|
||||
if err != nil {
|
||||
if _, ok := err.(BreakPointExistsError); !ok {
|
||||
return err
|
||||
@ -218,11 +194,7 @@ func (thread *ThreadContext) continueToReturnAddress(pc uint64, fde *frame.Frame
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// We wait on -1 here because once we continue this
|
||||
// thread, it's very possible the scheduler could of
|
||||
// change the goroutine context on us, we there is
|
||||
// no guarantee that waiting on this tid will ever
|
||||
// return.
|
||||
// Wait on -1, just in case scheduler switches threads for this G.
|
||||
wpid, _, err := trapWait(thread.Process, -1)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -230,7 +202,10 @@ func (thread *ThreadContext) continueToReturnAddress(pc uint64, fde *frame.Frame
|
||||
if wpid != thread.Id {
|
||||
thread = thread.Process.Threads[wpid]
|
||||
}
|
||||
pc, _ = thread.CurrentPC()
|
||||
pc, err = thread.CurrentPC()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (pc-1) == bp.Addr || pc == bp.Addr {
|
||||
break
|
||||
}
|
||||
@ -250,7 +225,7 @@ func (thread *ThreadContext) ReturnAddressFromOffset(offset int64) uint64 {
|
||||
|
||||
retaddr := int64(regs.SP()) + offset
|
||||
data := make([]byte, 8)
|
||||
readMemory(thread.Id, uintptr(retaddr), data)
|
||||
readMemory(thread, uintptr(retaddr), data)
|
||||
return binary.LittleEndian.Uint64(data)
|
||||
}
|
||||
|
||||
@ -259,7 +234,7 @@ func (thread *ThreadContext) clearTempBreakpoint(pc uint64) error {
|
||||
if _, ok := thread.Process.BreakPoints[pc]; ok {
|
||||
software = true
|
||||
}
|
||||
if _, err := thread.Clear(pc); err != nil {
|
||||
if _, err := thread.Process.Clear(pc); err != nil {
|
||||
return err
|
||||
}
|
||||
if software {
|
||||
@ -269,7 +244,7 @@ func (thread *ThreadContext) clearTempBreakpoint(pc uint64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return regs.SetPC(thread.Id, pc)
|
||||
return regs.SetPC(thread, pc)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
115
proctl/threads_darwin.c
Normal file
115
proctl/threads_darwin.c
Normal file
@ -0,0 +1,115 @@
|
||||
#include "threads_darwin.h"
|
||||
|
||||
int
|
||||
write_memory(mach_port_name_t task, mach_vm_address_t addr, void *d, mach_msg_type_number_t len) {
|
||||
kern_return_t kret;
|
||||
pointer_t data;
|
||||
memcpy((void *)&data, d, len);
|
||||
|
||||
// Set permissions to enable writting to this memory location
|
||||
kret = mach_vm_protect(task, addr, len, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY);
|
||||
if (kret != KERN_SUCCESS) return -1;
|
||||
|
||||
kret = mach_vm_write((vm_map_t)task, addr, (vm_offset_t)&data, len);
|
||||
if (kret != KERN_SUCCESS) return -1;
|
||||
|
||||
// Restore virtual memory permissions
|
||||
// TODO(dp) this should take into account original permissions somehow
|
||||
kret = mach_vm_protect(task, addr, len, FALSE, VM_PROT_READ | VM_PROT_EXECUTE);
|
||||
if (kret != KERN_SUCCESS) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
read_memory(mach_port_name_t task, mach_vm_address_t addr, void *d, mach_msg_type_number_t len) {
|
||||
kern_return_t kret;
|
||||
pointer_t data;
|
||||
mach_msg_type_number_t count;
|
||||
|
||||
kret = mach_vm_read((vm_map_t)task, addr, len, &data, &count);
|
||||
if (kret != KERN_SUCCESS) return -1;
|
||||
// TODO(dp) possible memory leak - vm_deallocate data
|
||||
memcpy(d, (void *)data, len);
|
||||
return count;
|
||||
}
|
||||
|
||||
x86_thread_state64_t
|
||||
get_registers(mach_port_name_t task) {
|
||||
kern_return_t kret;
|
||||
x86_thread_state64_t state;
|
||||
mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT;
|
||||
|
||||
// TODO(dp) - possible memory leak - vm_deallocate state
|
||||
kret = thread_get_state(task, x86_THREAD_STATE64, (thread_state_t)&state, &stateCount);
|
||||
if (kret != KERN_SUCCESS) printf("SOMETHING WENT WRONG-------------- %d\n", kret);
|
||||
if (kret == KERN_INVALID_ARGUMENT) puts("INAVLID ARGUMENT");
|
||||
return state;
|
||||
}
|
||||
|
||||
// TODO(dp) this should return kret instead of void
|
||||
void
|
||||
set_pc(thread_act_t task, uint64_t pc) {
|
||||
kern_return_t kret;
|
||||
x86_thread_state64_t state;
|
||||
mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT;
|
||||
|
||||
kret = thread_get_state(task, x86_THREAD_STATE64, (thread_state_t)&state, &stateCount);
|
||||
if (kret != KERN_SUCCESS) puts(mach_error_string(kret));
|
||||
state.__rip = pc;
|
||||
|
||||
kret = thread_set_state(task, x86_THREAD_STATE64, (thread_state_t)&state, stateCount);
|
||||
if (kret != KERN_SUCCESS) puts(mach_error_string(kret));
|
||||
// TODO(dp) - possible memory leak - vm_deallocate state
|
||||
}
|
||||
|
||||
// TODO(dp) this should return kret instead of void
|
||||
void
|
||||
single_step(thread_act_t thread) {
|
||||
kern_return_t kret;
|
||||
x86_thread_state64_t regs;
|
||||
mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
|
||||
|
||||
kret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)®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?
|
||||
}
|
81
proctl/threads_darwin.go
Normal file
81
proctl/threads_darwin.go
Normal file
@ -0,0 +1,81 @@
|
||||
package proctl
|
||||
|
||||
// #include "threads_darwin.h"
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type OSSpecificDetails struct {
|
||||
thread_act C.thread_act_t
|
||||
}
|
||||
|
||||
func (t *ThreadContext) Halt() error {
|
||||
// TODO(dp) may be able to just task_suspend instead of suspending individual threads
|
||||
var kret C.kern_return_t
|
||||
kret = C.thread_suspend(t.os.thread_act)
|
||||
if kret != C.KERN_SUCCESS {
|
||||
return fmt.Errorf("could not suspend task %d", t.Id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ThreadContext) singleStep() error {
|
||||
C.single_step(t.os.thread_act)
|
||||
trapWait(t.Process, 0)
|
||||
C.clear_trap_flag(t.os.thread_act)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ThreadContext) cont() error {
|
||||
// debug.PrintStack()
|
||||
// TODO(dp) set flag for ptrace stops
|
||||
if err := PtraceCont(t.Process.Pid, 0); err == nil {
|
||||
return nil
|
||||
}
|
||||
for {
|
||||
if C.thread_resume(t.os.thread_act) != C.KERN_SUCCESS {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ThreadContext) blocked() bool {
|
||||
// TODO(dp) cache the func pc to remove this lookup
|
||||
// TODO(dp) check err
|
||||
pc, _ := t.CurrentPC()
|
||||
fn := t.Process.GoSymTable.PCToFunc(pc)
|
||||
if fn != nil && ((fn.Name == "runtime.mach_semaphore_wait") || (fn.Name == "runtime.usleep")) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func writeMemory(thread *ThreadContext, addr uintptr, data []byte) (int, error) {
|
||||
var (
|
||||
vm_data = unsafe.Pointer(&data[0])
|
||||
vm_addr = C.mach_vm_address_t(addr)
|
||||
length = C.mach_msg_type_number_t(len(data))
|
||||
)
|
||||
|
||||
if ret := C.write_memory(thread.Process.os.task, vm_addr, vm_data, length); ret < 0 {
|
||||
return 0, fmt.Errorf("could not write memory")
|
||||
}
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
func readMemory(thread *ThreadContext, addr uintptr, data []byte) (int, error) {
|
||||
var (
|
||||
vm_data = unsafe.Pointer(&data[0])
|
||||
vm_addr = C.mach_vm_address_t(addr)
|
||||
length = C.mach_msg_type_number_t(len(data))
|
||||
)
|
||||
|
||||
ret := C.read_memory(thread.Process.os.task, vm_addr, vm_data, length)
|
||||
if ret < 0 {
|
||||
return 0, fmt.Errorf("could not read memory")
|
||||
}
|
||||
return len(data), nil
|
||||
}
|
23
proctl/threads_darwin.h
Normal file
23
proctl/threads_darwin.h
Normal file
@ -0,0 +1,23 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_vm.h>
|
||||
#include <mach/thread_info.h>
|
||||
|
||||
int
|
||||
write_memory(mach_port_name_t, mach_vm_address_t, void *, mach_msg_type_number_t);
|
||||
|
||||
int
|
||||
read_memory(mach_port_name_t, mach_vm_address_t, void *, mach_msg_type_number_t);
|
||||
|
||||
x86_thread_state64_t
|
||||
get_registers(mach_port_name_t);
|
||||
|
||||
void
|
||||
set_pc(thread_act_t, uint64_t);
|
||||
|
||||
void
|
||||
single_step(thread_act_t);
|
||||
|
||||
void
|
||||
clear_trap_flag(thread_act_t thread);
|
47
proctl/threads_linux.go
Normal file
47
proctl/threads_linux.go
Normal file
@ -0,0 +1,47 @@
|
||||
package proctl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
sys "golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Not actually used, but necessary
|
||||
// to be defined.
|
||||
type OSSpecificDetails interface{}
|
||||
|
||||
func (t *ThreadContext) Halt() error {
|
||||
if stopped(t.Id) {
|
||||
return nil
|
||||
}
|
||||
err := sys.Tgkill(t.Process.Pid, t.Id, sys.SIGSTOP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Halt err %s %d", err, pid)
|
||||
}
|
||||
pid, _, err := wait(th.Id, sys.WNOHANG)
|
||||
if err != nil {
|
||||
return fmt.Errorf("wait err %s %d", err, pid)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ThreadContext) cont() error {
|
||||
return PtraceCont(thread.Id, 0)
|
||||
}
|
||||
|
||||
func (t *ThreadContext) singleStep() error {
|
||||
err := sys.PtraceSingleStep(t.Id)
|
||||
if err != nill {
|
||||
return err
|
||||
}
|
||||
_, _, err = wait(thread.Id, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
func writeMemory(tid int, addr uintptr, data []byte) (int, error) {
|
||||
return sys.PtracePokeData(tid, addr, data)
|
||||
}
|
||||
|
||||
func readMemory(tid int, addr uintptr, data []byte) (int, error) {
|
||||
return sys.PtracePeekData(tid, addr, data)
|
||||
}
|
@ -912,7 +912,7 @@ func (thread *ThreadContext) readFunctionPtr(addr uintptr) (string, error) {
|
||||
func (thread *ThreadContext) readMemory(addr uintptr, size uintptr) ([]byte, error) {
|
||||
buf := make([]byte, size)
|
||||
|
||||
_, err := readMemory(thread.Id, addr, buf)
|
||||
_, err := readMemory(thread, addr, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
4
test_darwin
Executable file
4
test_darwin
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
go test -c && codesign -s dbg-cert ./proctl.test && ./proctl.test -test.v -test.run "$1"
|
||||
rm ./proctl.test
|
Loading…
Reference in New Issue
Block a user