#if defined(__MWERKS__) && !defined(__private_extern__)
#define __private_extern__ __declspec(private_extern)
#endif
#ifdef SHLIB
#include "shlib.h"
#endif
#import <string.h>
#import <libc.h>
#import <errno.h>
#import <mach/mach.h>
#import <mach/mach_error.h>
#import <mach/machine/vm_param.h>
#include <unistd.h>
#ifdef _POSIX_THREADS
#include <pthread.h>
#else
#import <mach/cthreads.h>
#endif
#import <mach-o/loader.h>
#import "stuff/bool.h"
#import <mach-o/dyld_debug.h>
#import <mach/machine/thread_status.h>
#ifdef hppa
#import <architecture/hppa/cframe.h>
#endif
#ifndef __OPENSTEP__
#include <mach-o/getsect.h>
#endif
#import "_dyld_debug.h"
#import "debug.h"
struct server_loop_params {
mach_port_t subscriber;
void (*dyld_event_routine)(struct dyld_event event);
};
static void server_loop(
struct server_loop_params *server_loop_params);
static enum dyld_debug_return get_or_start_debug_thread(
task_port_t target_task,
struct _dyld_debug_task_state *state);
static enum dyld_debug_return get_set_dyld_data(
enum bool get,
task_port_t target_task,
struct dyld_data_section *dyld_data);
static enum dyld_debug_return make_dyld_image_data_writable(
task_port_t target_task);
static enum dyld_debug_return task_suspend_threads(
task_port_t target_task,
thread_port_array_t *threads,
unsigned int *count);
static enum dyld_debug_return task_resume_threads(
thread_port_array_t threads,
unsigned int count);
static enum dyld_debug_return translate_port(
task_port_t target_task,
mach_port_name_t target_port,
mach_port_t *dest_port);
static enum dyld_debug_return thread_start(
task_port_t task,
void *func,
long arg,
vm_offset_t stack_size,
thread_port_t *thread);
static enum dyld_debug_return thread_setup(
thread_port_t thread,
void *func,
long arg,
vm_address_t stack_copy,
vm_address_t stack_base,
vm_offset_t stack_size);
#ifndef __MACH30__
static int mig_error = 0;
static struct dyld_debug_error_data _dyld_debug_error_data;
__private_extern__
void
dyld_debug_MsgError(
msg_return_t msg_result)
{
SET_MACH_DYLD_DEBUG_ERROR(msg_result, 89);
mig_error = 1;
}
#endif
enum dyld_debug_return
_dyld_debug_defining_module(
task_port_t target_task,
unsigned long send_timeout,
unsigned long rcv_timeout,
boolean_t inconsistent_data_ok,
char *name,
struct dyld_debug_module *module)
{
enum dyld_debug_return d, p;
struct _dyld_debug_task_state state;
#ifdef __MACH30__
kern_return_t k;
#endif
p = _dyld_debug_make_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
#ifdef __MACH30__
k = user_dyld_debug_defining_module(state.debug_port, rcv_timeout,
inconsistent_data_ok, name, strlen(name), module, &d);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 88);
d = DYLD_FAILURE;
}
#else
d = user_dyld_debug_defining_module(state.debug_port, send_timeout,
rcv_timeout, inconsistent_data_ok, name, strlen(name), module);
if(d != DYLD_SUCCESS)
set_dyld_debug_error_data(d,0,0,87,__FILE__,__LINE__);
#endif
p = _dyld_debug_restore_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
return(d);
}
enum dyld_debug_return
_dyld_debug_is_module_bound(
task_port_t target_task,
unsigned long send_timeout,
unsigned long rcv_timeout,
boolean_t inconsistent_data_ok,
struct dyld_debug_module module,
boolean_t *bound)
{
enum dyld_debug_return d, p;
struct _dyld_debug_task_state state;
#ifdef __MACH30__
kern_return_t k;
#endif
p = _dyld_debug_make_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
#ifdef __MACH30__
k = user_dyld_debug_is_module_bound(state.debug_port, rcv_timeout,
inconsistent_data_ok, module, bound, &d);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 86);
d = DYLD_FAILURE;
}
else if(d != DYLD_SUCCESS)
SET_LOCAL_DYLD_DEBUG_ERROR(85);
#else
mig_error = 0;
d = user_dyld_debug_is_module_bound(state.debug_port, send_timeout,
rcv_timeout, inconsistent_data_ok, module, bound);
if(mig_error == 0 && d != DYLD_SUCCESS)
set_dyld_debug_error_data(d,0,0,84,__FILE__,__LINE__);
#endif
p = _dyld_debug_restore_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
return(d);
}
enum dyld_debug_return
_dyld_debug_bind_module(
task_port_t target_task,
unsigned long send_timeout,
unsigned long rcv_timeout,
boolean_t inconsistent_data_ok,
struct dyld_debug_module module)
{
enum dyld_debug_return d, p;
struct _dyld_debug_task_state state;
#ifdef __MACH30__
kern_return_t k;
#endif
p = _dyld_debug_make_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
#ifdef __MACH30__
k = user_dyld_debug_bind_module(state.debug_port, rcv_timeout,
inconsistent_data_ok, module, &d);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 83);
d = DYLD_FAILURE;
}
#else
mig_error = 0;
d = user_dyld_debug_bind_module(state.debug_port, send_timeout,
rcv_timeout, inconsistent_data_ok, module);
if(mig_error == 0 && d != DYLD_SUCCESS)
set_dyld_debug_error_data(d,0,0,82,__FILE__,__LINE__);
#endif
p = _dyld_debug_restore_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
return(d);
}
enum dyld_debug_return
_dyld_debug_module_name(
task_port_t target_task,
unsigned long send_timeout,
unsigned long rcv_timeout,
boolean_t inconsistent_data_ok,
struct dyld_debug_module module,
char **image_name,
unsigned long *image_nameCnt,
char **module_name,
unsigned long *module_nameCnt)
{
enum dyld_debug_return d, p;
struct _dyld_debug_task_state state;
#ifdef __MACH30__
kern_return_t k;
#endif
p = _dyld_debug_make_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
#ifdef __MACH30__
k = user_dyld_debug_module_name(state.debug_port, rcv_timeout,
inconsistent_data_ok, module, image_name,
(unsigned int *)image_nameCnt, module_name,
(unsigned int *)module_nameCnt, &d);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 81);
d = DYLD_FAILURE;
}
else if(d != DYLD_SUCCESS)
SET_LOCAL_DYLD_DEBUG_ERROR(80);
#else
mig_error = 0;
d = user_dyld_debug_module_name(state.debug_port, send_timeout,
rcv_timeout, inconsistent_data_ok, module, image_name,
(unsigned int *)image_nameCnt, module_name,
(unsigned int *)module_nameCnt);
if(mig_error == 0 && d != DYLD_SUCCESS)
set_dyld_debug_error_data(d,0,0,79,__FILE__,__LINE__);
#endif
p = _dyld_debug_restore_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
return(d);
}
#ifdef DYLD_PROFILING
enum dyld_debug_return
_dyld_debug_monoutput(
task_port_t target_task,
unsigned long send_timeout,
unsigned long rcv_timeout)
{
enum dyld_debug_return d, p;
struct _dyld_debug_task_state state;
#ifdef __MACH30__
kern_return_t k;
#endif
p = _dyld_debug_make_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
#ifdef __MACH30__
k = user_dyld_debug_monoutput(state.debug_port, rcv_timeout, &d);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 78);
d = DYLD_FAILURE;
}
else if(d != DYLD_SUCCESS)
SET_LOCAL_DYLD_DEBUG_ERROR(77);
#else
mig_error = 0;
d = user_dyld_debug_monoutput(state.debug_port, send_timeout,
rcv_timeout);
if(mig_error == 0 && d != DYLD_SUCCESS)
set_dyld_debug_error_data(d,0,0,76,__FILE__,__LINE__);
#endif
p = _dyld_debug_restore_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
return(d);
}
#endif
#ifdef _POSIX_THREADS
static pthread_key_t thread_data_key;
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
static
void
init_routine(void)
{
(void)pthread_key_create(&thread_data_key, NULL);
}
#endif
enum dyld_debug_return
_dyld_debug_subscribe_to_events(
task_port_t target_task,
unsigned long send_timeout,
unsigned long rcv_timeout,
boolean_t inconsistent_data_ok,
void (*dyld_event_routine)(struct dyld_event event))
{
kern_return_t k;
#ifdef _POSIX_THREADS
pthread_t server_loop_thread;
#else
cthread_t server_loop_thread;
#endif
mach_port_t subscriber;
enum dyld_debug_return p;
struct _dyld_debug_task_state state;
#ifdef __MACH30__
enum dyld_debug_return d;
#endif
struct server_loop_params *server_loop_params;
server_loop_params = malloc(sizeof(struct server_loop_params));
if(server_loop_params == NULL){
SET_ERRNO_DYLD_DEBUG_ERROR(errno, 75);
return(DYLD_FAILURE);
}
#ifdef __MACH30__
if((k = mach_port_allocate(mach_task_self(),
MACH_PORT_RIGHT_RECEIVE, &subscriber)) != KERN_SUCCESS)
#else
if((k = port_allocate(mach_task_self(),
(int *)&subscriber)) != KERN_SUCCESS)
#endif
{
free(server_loop_params);
SET_MACH_DYLD_DEBUG_ERROR(k, 74);
return(DYLD_FAILURE);
}
server_loop_params->subscriber = subscriber;
server_loop_params->dyld_event_routine = dyld_event_routine;
#ifdef _POSIX_THREADS
if(pthread_once(&once_control, init_routine) != 0){
SET_ERRNO_DYLD_DEBUG_ERROR(errno, 73);
return(DYLD_FAILURE);
}
if(pthread_create(&server_loop_thread, NULL,
(void *(*)(void *))server_loop,
(void *)server_loop_params) != 0){
SET_ERRNO_DYLD_DEBUG_ERROR(errno, 72);
return(DYLD_FAILURE);
}
pthread_detach(server_loop_thread);
#else
server_loop_thread = cthread_fork((cthread_fn_t)server_loop,
(any_t)server_loop_params);
cthread_detach(server_loop_thread);
#endif
p = _dyld_debug_make_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
#ifdef __MACH30__
k = user_dyld_debug_add_event_subscriber(state.debug_port, rcv_timeout,
inconsistent_data_ok, subscriber, &d);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 71);
d = DYLD_FAILURE;
}
else if(d != DYLD_SUCCESS)
SET_LOCAL_DYLD_DEBUG_ERROR(70);
#else
user_dyld_debug_add_event_subscriber(state.debug_port, send_timeout,
rcv_timeout, inconsistent_data_ok, subscriber);
#endif
p = _dyld_debug_restore_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
#ifdef __MACH30__
if(d == DYLD_FAILURE)
return(DYLD_FAILURE);
#endif
return(DYLD_SUCCESS);
}
enum dyld_debug_return
_dyld_debug_add_event_subscriber(
task_port_t target_task,
unsigned long send_timeout,
unsigned long rcv_timeout,
boolean_t inconsistent_data_ok,
mach_port_t subscriber)
{
enum dyld_debug_return p;
struct _dyld_debug_task_state state;
#ifdef __MACH30__
enum dyld_debug_return d;
kern_return_t k;
#endif
p = _dyld_debug_make_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
#ifdef __MACH30__
k = user_dyld_debug_add_event_subscriber(state.debug_port, rcv_timeout,
inconsistent_data_ok, subscriber, &d);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 69);
d = DYLD_FAILURE;
}
else if(d != DYLD_SUCCESS)
SET_LOCAL_DYLD_DEBUG_ERROR(68);
#else
user_dyld_debug_add_event_subscriber(state.debug_port, send_timeout,
rcv_timeout, inconsistent_data_ok, subscriber);
#endif
p = _dyld_debug_restore_runnable(target_task, &state);
if(p != DYLD_SUCCESS)
return(DYLD_FAILURE);
#ifdef __MACH30__
if(d == DYLD_FAILURE)
return(DYLD_FAILURE);
#endif
return(DYLD_SUCCESS);
}
static
void
server_loop(
struct server_loop_params *server_loop_params)
{
struct _dyld_event_message_request request;
struct _dyld_event_message_reply reply;
kern_return_t r;
boolean_t b;
#ifdef _POSIX_THREADS
pthread_setspecific(thread_data_key,
server_loop_params->dyld_event_routine);
#else
cthread_set_data(cthread_self(),
(any_t)server_loop_params->dyld_event_routine);
#endif
while(TRUE){
#ifdef __MACH30__
r = mach_msg(
&request.head,
MACH_RCV_MSG,
0,
sizeof(struct _dyld_event_message_request),
server_loop_params->subscriber,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
if(r != MACH_MSG_SUCCESS){
continue;
}
b = _dyld_event_server(&request.head, &reply.head);
#else
request.head.msg_local_port = server_loop_params->subscriber;
request.head.msg_size = sizeof(struct _dyld_event_message_request);
r = msg_receive(&request.head, MACH_MSG_OPTION_NONE, 0);
if(r != RCV_SUCCESS){
continue;
}
b = _dyld_event_server(&request, &reply);
#endif
if(b == FALSE){
continue;
}
#ifdef __MACH30__
#else
reply.head.msg_local_port = server_loop_params->subscriber;
msg_send(&reply.head, MACH_MSG_OPTION_NONE, 0);
#endif
}
}
__private_extern__
#ifdef __MACH30__
kern_return_t
#else
void
#endif
_dyld_event_server_callback(
#ifdef __MACH30__
mach_port_t subscriber,
#else
port_t subscriber,
#endif
struct dyld_event event)
{
void (*dyld_event_routine)(struct dyld_event event);
#ifdef _POSIX_THREADS
dyld_event_routine = pthread_getspecific(thread_data_key);
#else
dyld_event_routine = cthread_data(cthread_self());
#endif
dyld_event_routine(event);
#ifdef __MACH30__
return(KERN_SUCCESS);
#endif
}
enum dyld_debug_return
_dyld_debug_make_runnable(
task_port_t target_task,
struct _dyld_debug_task_state *state)
{
enum dyld_debug_return d;
struct thread_basic_info info;
unsigned int info_count;
kern_return_t k;
unsigned int i;
d = get_or_start_debug_thread(target_task, state);
if(d != DYLD_SUCCESS)
return(d);
k = task_suspend(target_task);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 67);
return(DYLD_FAILURE);
}
k = task_threads(target_task, &state->threads, &state->thread_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 66);
return(DYLD_FAILURE);
}
for(i = 0; i < state->thread_count; i++){
if(state->threads[i] != state->debug_thread){
k = thread_suspend(state->threads[i]);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 65);
return(DYLD_FAILURE);
}
}
}
info_count = THREAD_BASIC_INFO_COUNT;
k = thread_info(state->debug_thread, THREAD_BASIC_INFO,
(thread_info_t)&info, &info_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 64);
return(DYLD_FAILURE);
}
state->debug_thread_resume_count = 0;
for(i = 0; i < info.suspend_count; i++){
k = thread_resume(state->debug_thread);
if(k == KERN_SUCCESS)
state->debug_thread_resume_count += 1;
else if(k == KERN_FAILURE)
break;
else{
SET_MACH_DYLD_DEBUG_ERROR(k, 63);
return(DYLD_FAILURE);
}
}
k = task_resume(target_task);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 62);
return(DYLD_FAILURE);
}
state->task_resume_count = 0;
while(task_resume(target_task) == KERN_SUCCESS)
state->task_resume_count++;
return(DYLD_SUCCESS);
}
enum dyld_debug_return
_dyld_debug_restore_runnable(
task_port_t target_task,
struct _dyld_debug_task_state *state)
{
unsigned int i;
kern_return_t k;
while(state->task_resume_count--){
k = task_suspend(target_task);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 61);
return(DYLD_FAILURE);
}
}
for(i = 0; i < state->debug_thread_resume_count; i++){
k = thread_suspend(state->debug_thread);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 60);
return(DYLD_FAILURE);
}
}
for(i = 0; i < state->thread_count; i++){
if(state->threads[i] != state->debug_thread){
k = thread_resume(state->threads[i]);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 59);
return(DYLD_FAILURE);
}
}
}
k = vm_deallocate(mach_task_self(), (vm_address_t)state->threads,
sizeof(state->threads[0]) * state->thread_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 58);
return(DYLD_FAILURE);
}
return(DYLD_SUCCESS);
}
#ifdef CORE_DEBUG
#ifdef __i386__
void
printf_i386_thread_state_t(
i386_thread_state_t *cpu)
{
printf(
"\t eax 0x%08x ebx 0x%08x ecx 0x%08x edx 0x%08x\n"
"\t edi 0x%08x esi 0x%08x ebp 0x%08x esp 0x%08x\n"
"\t ss 0x%08x eflags 0x%08x eip 0x%08x cs 0x%08x\n"
"\t ds 0x%08x es 0x%08x fs 0x%08x gs 0x%08x\n",
cpu->eax, cpu->ebx, cpu->ecx, cpu->edx, cpu->edi, cpu->esi,
cpu->ebp, cpu->esp, cpu->ss, cpu->eflags, cpu->eip, cpu->cs,
cpu->ds, cpu->es, cpu->fs, cpu->gs);
}
#endif
#ifdef __ppc__
void
printf_ppc_thread_state_t(
ppc_thread_state_t *cpu)
{
printf(" r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x "
"r4 0x%08x\n"
" r5 0x%08x r6 0x%08x r7 0x%08x r8 0x%08x "
"r9 0x%08x\n"
" r10 0x%08x r11 0x%08x r12 0x%08x r13 0x%08x "
"r14 0x%08x\n"
" r15 0x%08x r16 0x%08x r17 0x%08x r18 0x%08x "
"r19 0x%08x\n"
" r20 0x%08x r21 0x%08x r22 0x%08x r23 0x%08x "
"r24 0x%08x\n"
" r25 0x%08x r26 0x%08x r27 0x%08x r28 0x%08x "
"r29 0x%08x\n"
" r30 0x%08x r31 0x%08x lr 0x%08x ctr 0x%08x "
"srr0 0x%08x\n",
cpu->r0, cpu->r1, cpu->r2, cpu->r3, cpu->r4, cpu->r5,
cpu->r6, cpu->r7, cpu->r8, cpu->r9, cpu->r10, cpu->r11,
cpu->r12, cpu->r13, cpu->r14, cpu->r15, cpu->r16, cpu->r17,
cpu->r18, cpu->r19, cpu->r20, cpu->r21, cpu->r22, cpu->r23,
cpu->r24, cpu->r25, cpu->r26, cpu->r27, cpu->r28, cpu->r29,
cpu->r30, cpu->r31, cpu->lr, cpu->ctr, cpu->srr0);
printf(" cr 0x%08x\n", cpu->cr);
printf(" xer 0x%08x\n", cpu->xer);
printf(" srr1 0x%08x\n", cpu->srr1);
}
#endif
#ifdef hppa
void
printf_hp_pa_integer_thread_state(
struct hp_pa_integer_thread_state *frame)
{
printf(
"r1 0x%08lx r2 0x%08lx r3 0x%08lx r4 0x%08lx\n"
"r5 0x%08lx r6 0x%08lx r7 0x%08lx r8 0x%08lx\n"
"r9 0x%08lx r10 0x%08lx r11 0x%08lx r12 0x%08lx\n"
"r13 0x%08lx r14 0x%08lx r15 0x%08lx r16 0x%08lx\n"
"r17 0x%08lx r18 0x%08lx r19 0x%08lx r20 0x%08lx\n"
"r21 0x%08lx r22 0x%08lx r23 0x%08lx r24 0x%08lx\n"
"r25 0x%08lx r26 0x%08lx r27 0x%08lx r28 0x%08lx\n"
"r29 0x%08lx r30 0x%08lx r31 0x%08lx\n"
"sr0 0x%08lx sr1 0x%08lx sr2 0x%08lx sar 0x%08lx\n",
frame->ts_gr1, frame->ts_gr2, frame->ts_gr3, frame->ts_gr4,
frame->ts_gr5, frame->ts_gr6, frame->ts_gr7, frame->ts_gr8,
frame->ts_gr9, frame->ts_gr10, frame->ts_gr11, frame->ts_gr12,
frame->ts_gr13, frame->ts_gr14, frame->ts_gr15, frame->ts_gr16,
frame->ts_gr17, frame->ts_gr18, frame->ts_gr19, frame->ts_gr20,
frame->ts_gr21, frame->ts_gr22, frame->ts_gr23, frame->ts_gr24,
frame->ts_gr25, frame->ts_gr26, frame->ts_gr27, frame->ts_gr28,
frame->ts_gr29, frame->ts_gr30, frame->ts_gr31,
frame->ts_sr0, frame->ts_sr1, frame->ts_sr2, frame->ts_sar);
}
void
print_hp_pa_frame_thread_state(
struct hp_pa_frame_thread_state *frame)
{
printf("pcsq_front 0x%08lx pcsq_back 0x%08lx\n"
"pcoq_front 0x%08lx pcoq_back 0x%08lx\n"
" psw 0x%08lx\n",
frame->ts_pcsq_front, frame->ts_pcsq_back,
frame->ts_pcoq_front, frame->ts_pcoq_back,
frame->ts_psw);
}
#endif
#endif
static
enum dyld_debug_return
get_or_start_debug_thread(
task_port_t target_task,
struct _dyld_debug_task_state *state)
{
enum dyld_debug_return d;
struct dyld_data_section data;
thread_port_array_t threads;
unsigned int count;
unsigned int count1, trys;
boolean_t task_resumed;
thread_port_t debug_thread;
kern_return_t k;
struct host_sched_info info;
enum bool core_task;
mach_port_t my_mach_host_self;
state->debug_thread = MACH_PORT_NULL;
state->debug_port = MACH_PORT_NULL;
d = make_dyld_image_data_writable(target_task);
if(d != DYLD_SUCCESS)
return(d);
d = get_dyld_data(target_task, &data);
if(d != DYLD_SUCCESS)
return(d);
if(data.debug_port == CORE_DEBUG_PORT &&
data.debug_thread == CORE_DEBUG_THREAD){
core_task = TRUE;
data.debug_port = MACH_PORT_NULL;
data.debug_thread = MACH_PORT_NULL;
d = set_dyld_data(target_task, &data);
if(d != DYLD_SUCCESS)
return(d);
}
else
core_task = FALSE;
if(data.start_debug_thread == 0){
#ifdef CORE_DEBUG
printf("data.stub_binding_helper_interface 0x%x\n",
(unsigned int)data.stub_binding_helper_interface);
printf("data._dyld_func_lookup 0x%x\n",
(unsigned int)data._dyld_func_lookup);
printf("data.start_debug_thread 0x%x\n",
(unsigned int)data.start_debug_thread);
printf("data.debug_thread %d\n", data.debug_thread);
printf("data.debug_port %d\n", data.debug_port);
#ifdef __ppc__
printf("data.dyld_stub_binding_helper 0x%x\n",
(unsigned int)data.dyld_stub_binding_helper);
#endif
printf("data.core_debug %lu\n", data.core_debug);
#endif
SET_LOCAL_DYLD_DEBUG_ERROR(57);
return(DYLD_FAILURE);
}
if(data.debug_thread == MACH_PORT_NULL ||
data.debug_port == MACH_PORT_NULL){
if(core_task == FALSE){
d = task_suspend_threads(target_task, &threads, &count);
if(d != DYLD_SUCCESS)
return(d);
}
task_resumed = FALSE;
if(task_resume(target_task) == KERN_SUCCESS)
task_resumed = TRUE;
#ifdef CORE_DEBUG
k = task_threads(target_task, &threads, &count);
if(k != KERN_SUCCESS)
printf("task_threads failed (before thread_start())\n");
else
printf("task_threads count = %d (before thread_start())\n",
count);
#endif
d = thread_start(target_task,
data.start_debug_thread,
core_task,
64 * vm_page_size,
&debug_thread);
if(d != DYLD_SUCCESS)
return(d);
#ifdef CORE_DEBUG
k = task_threads(target_task, &threads, &count);
if(k != KERN_SUCCESS)
printf("task_threads failed %d (%s)\n",
k, mach_error_string(k));
else{
int i;
#ifdef hppa
struct hp_pa_frame_thread_state frame_state;
struct hp_pa_integer_thread_state integer_state;
unsigned int frame_state_count, integer_state_count;
memset(&frame_state, '\0', sizeof(frame_state));
memset(&integer_state, '\0', sizeof(integer_state));
#endif
#ifdef __ppc__
ppc_thread_state_t state;
unsigned int state_count;
memset(&state, '\0', sizeof(state));
#endif
#ifdef __i386__
i386_thread_state_t state;
unsigned int state_count;
memset(&state, '\0', sizeof(state));
#endif
printf("task_threads count = %d (after thread_start())\n",
count);
for(i = 0; i < count; i++){
#ifdef __i386__
state_count = i386_THREAD_STATE_COUNT;
k = thread_get_state(threads[i],
i386_THREAD_STATE,
(thread_state_t)&state,
&state_count);
if(k == KERN_SUCCESS){
printf("thread_get_state worked\n");
printf_i386_thread_state_t(&state);
}
else
printf("thread_get_state failed %d (s)\n", k
mach_error_string(k));
#endif
#ifdef __ppc__
state_count = PPC_THREAD_STATE_COUNT;
k = thread_get_state(threads[i],
PPC_THREAD_STATE,
(thread_state_t)&state,
&state_count);
if(k == KERN_SUCCESS){
printf("thread_get_state worked\n");
printf_ppc_thread_state_t(&state);
}
else
printf("thread_get_state failed %d (%s)\n", k,
mach_error_string(k));
#endif
#ifdef hppa
integer_state_count = HPPA_INTEGER_THREAD_STATE_COUNT;
k = thread_get_state(threads[i],
HPPA_INTEGER_THREAD_STATE,
(thread_state_t)&integer_state,
&integer_state_count);
if(k == KERN_SUCCESS){
printf("thread_get_state INTEGER worked\n");
printf_hp_pa_integer_thread_state(&integer_state);
}
else
printf("thread_get_state INTEGER failed %d (s)\n", k
mach_error_string(k));
frame_state_count = HPPA_FRAME_THREAD_STATE_COUNT;
k = thread_get_state(threads[i],
HPPA_FRAME_THREAD_STATE,
(thread_state_t)&frame_state,
&frame_state_count);
if(k != KERN_SUCCESS){
printf("thread_get_state FRAME worked\n");
print_hp_pa_frame_thread_state(&frame_state);
}
else
printf("thread_get_state FRAME failed\n");
#endif
}
}
#endif
count1 = HOST_SCHED_INFO_COUNT;
my_mach_host_self = mach_host_self();
k = host_info(my_mach_host_self, HOST_SCHED_INFO,
(host_info_t)(&info), &count1);
mach_port_deallocate(mach_task_self(), my_mach_host_self);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 56);
return(DYLD_FAILURE);
}
trys = 0;
do{
k = thread_switch(MACH_PORT_NULL, SWITCH_OPTION_DEPRESS,
info.min_timeout * 10000);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 55);
return(DYLD_FAILURE);
}
d = get_dyld_data(target_task, &data);
if(d != DYLD_SUCCESS)
return(d);
trys++;
}while((data.debug_thread == MACH_PORT_NULL ||
data.debug_port == MACH_PORT_NULL) &&
trys < 100);
if(task_resumed){
k = task_suspend(target_task);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 54);
return(DYLD_FAILURE);
}
}
if(core_task == FALSE){
d = task_resume_threads(threads, count);
if(d != DYLD_SUCCESS)
return(d);
}
if(trys >= 100){
#ifdef CORE_DEBUG
printf("data.stub_binding_helper_interface 0x%x\n",
(unsigned int)data.stub_binding_helper_interface);
printf("data._dyld_func_lookup 0x%x\n",
(unsigned int)data._dyld_func_lookup);
printf("data.start_debug_thread 0x%x\n",
(unsigned int)data.start_debug_thread);
printf("data.debug_thread %d\n", data.debug_thread);
printf("data.debug_port %d\n", data.debug_port);
#ifdef __ppc__
printf("data.dyld_stub_binding_helper 0x%x\n",
(unsigned int)data.dyld_stub_binding_helper);
#endif
printf("data.core_debug %lu\n", data.core_debug);
#endif
SET_LOCAL_DYLD_DEBUG_ERROR(53);
return(DYLD_FAILURE);
}
}
d = translate_port(target_task, data.debug_thread,&state->debug_thread);
if(d != DYLD_SUCCESS)
return(d);
d = translate_port(target_task, data.debug_port, &state->debug_port);
if(d != DYLD_SUCCESS)
return(d);
return(DYLD_SUCCESS);
}
static
enum dyld_debug_return
make_dyld_image_data_writable(
task_port_t target_task)
{
kern_return_t k;
struct mach_header *mh;
vm_address_t address;
vm_size_t size;
#ifdef __MACH30__
vm_region_basic_info_data_t info;
mach_msg_type_number_t infoCnt;
#else
vm_prot_t max_protection, protection;
vm_inherit_t inheritance;
boolean_t shared;
vm_offset_t offset;
#endif
vm_prot_t data_seg_initprot;
mach_port_t objectName;
pointer_t data;
unsigned int data_count;
struct segment_command *sg, *text_seg, *data_seg;
unsigned long i, mh_address, dyld_vmslide,
data_seg_vmaddr, data_seg_vmsize;
mh = NULL;
mh_address = 0;
address = 0x8fe00000;
#ifdef __MACH30__
infoCnt = VM_REGION_BASIC_INFO_COUNT;
k = vm_region(target_task, &address, &size, VM_REGION_BASIC_INFO,
(vm_region_info_t)&info, &infoCnt, &objectName);
#else
k = vm_region(target_task, &address, &size, &protection,
&max_protection, &inheritance, &shared, &objectName,
&offset);
#endif
if(k == KERN_SUCCESS){
k = vm_read(target_task, address, size, &data, &data_count);
if(k == KERN_SUCCESS){
if(data_count > sizeof(struct mach_header)){
mh = (struct mach_header *)data;
mh_address = address;
if(mh->magic != MH_MAGIC ||
mh->filetype != MH_DYLINKER ||
data_count < sizeof(struct mach_header) +
mh->sizeofcmds){
mh = NULL;
}
}
if(mh == NULL){
k = vm_deallocate(mach_task_self(), data, data_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 52);
return(DYLD_FAILURE);
}
}
else
goto down;
}
}
mh = NULL;
mh_address = 0;
address = VM_MIN_ADDRESS;
do{
#ifdef __MACH30__
infoCnt = VM_REGION_BASIC_INFO_COUNT;
k = vm_region(target_task, &address, &size, VM_REGION_BASIC_INFO,
(vm_region_info_t)&info, &infoCnt, &objectName);
#else
k = vm_region(target_task, &address, &size, &protection,
&max_protection, &inheritance, &shared, &objectName,
&offset);
#endif
if(k == KERN_SUCCESS){
k = vm_read(target_task, address, size, &data, &data_count);
if(k == KERN_SUCCESS){
if(data_count > sizeof(struct mach_header)){
mh = (struct mach_header *)data;
mh_address = address;
if(mh->magic != MH_MAGIC ||
mh->filetype != MH_DYLINKER ||
data_count < sizeof(struct mach_header) +
mh->sizeofcmds){
mh = NULL;
}
}
if(mh == NULL){
k = vm_deallocate(mach_task_self(), data, data_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 51);
return(DYLD_FAILURE);
}
}
}
else if(k != KERN_PROTECTION_FAILURE){
SET_MACH_DYLD_DEBUG_ERROR(k, 50);
return(DYLD_FAILURE);
}
address += size;
}
}while(k != KERN_NO_SPACE && mh == NULL);
down:
if(mh == NULL){
SET_LOCAL_DYLD_DEBUG_ERROR(49);
return(DYLD_FAILURE);
}
text_seg = NULL;
sg = (struct segment_command *)
((char *)mh + sizeof(struct mach_header));
for(i = 0; i < mh->ncmds; i++){
if(sg->cmd == LC_SEGMENT){
if(strncmp(sg->segname, "__TEXT", sizeof(sg->segname)) == 0){
text_seg = sg;
break;
}
}
sg = (struct segment_command *)((char *)sg + sg->cmdsize);
}
if(text_seg == NULL){
SET_LOCAL_DYLD_DEBUG_ERROR(48);
return(DYLD_FAILURE);
}
dyld_vmslide = mh_address - text_seg->vmaddr;
data_seg = NULL;
sg = (struct segment_command *)
((char *)mh + sizeof(struct mach_header));
for(i = 0; i < mh->ncmds; i++){
if(sg->cmd == LC_SEGMENT){
if(strncmp(sg->segname, "__DATA", sizeof(sg->segname)) == 0){
data_seg = sg;
break;
}
}
sg = (struct segment_command *)((char *)sg + sg->cmdsize);
}
if(data_seg == NULL){
SET_LOCAL_DYLD_DEBUG_ERROR(47);
return(DYLD_FAILURE);
}
data_seg_vmaddr = data_seg->vmaddr;
data_seg_vmsize = data_seg->vmsize;
data_seg_initprot = data_seg->initprot;
k = vm_deallocate(mach_task_self(), data, data_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 46);
return(DYLD_FAILURE);
}
address = data_seg_vmaddr + dyld_vmslide;
#ifdef __MACH30__
infoCnt = VM_REGION_BASIC_INFO_COUNT;
k = vm_region(target_task, &address, &size, VM_REGION_BASIC_INFO,
(vm_region_info_t)&info, &infoCnt, &objectName);
#else
k = vm_region(target_task, &address, &size, &protection,
&max_protection, &inheritance, &shared, &objectName,
&offset);
#endif
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 45);
return(DYLD_FAILURE);
}
if(address != data_seg_vmaddr + dyld_vmslide){
SET_LOCAL_DYLD_DEBUG_ERROR(44);
return(DYLD_FAILURE);
}
#ifdef __MACH30__
if((info.protection & VM_PROT_WRITE) != VM_PROT_WRITE)
#else
if((protection & VM_PROT_WRITE) != VM_PROT_WRITE)
#endif
{
k = vm_protect(target_task, address, (vm_size_t)data_seg_vmsize,
FALSE, data_seg_initprot);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 43);
return(DYLD_FAILURE);
}
}
return(DYLD_SUCCESS);
}
enum dyld_debug_return
get_dyld_data(
task_port_t target_task,
struct dyld_data_section *dyld_data)
{
return(get_set_dyld_data(TRUE, target_task, dyld_data));
}
enum dyld_debug_return
set_dyld_data(
task_port_t target_task,
struct dyld_data_section *dyld_data)
{
return(get_set_dyld_data(FALSE, target_task, dyld_data));
}
static
enum dyld_debug_return
get_set_dyld_data(
enum bool get,
task_port_t target_task,
struct dyld_data_section *dyld_data)
{
kern_return_t k;
struct mach_header *mh;
vm_address_t address;
vm_size_t size;
#ifdef __MACH30__
vm_region_basic_info_data_t info;
mach_msg_type_number_t infoCnt;
#else
vm_prot_t protection, max_protection;
vm_inherit_t inheritance;
boolean_t shared;
vm_offset_t offset;
#endif
mach_port_t objectName;
pointer_t data;
unsigned int data_count;
const struct section *s;
unsigned long addr;
if(get == TRUE)
memset(dyld_data, '\0', sizeof(struct dyld_data_section));
mh = NULL;
address = VM_MIN_ADDRESS;
do{
#ifdef __MACH30__
infoCnt = VM_REGION_BASIC_INFO_COUNT;
k = vm_region(target_task, &address, &size, VM_REGION_BASIC_INFO,
(vm_region_info_t)&info, &infoCnt, &objectName);
#else
k = vm_region(target_task, &address, &size, &protection,
&max_protection, &inheritance, &shared, &objectName,
&offset);
#endif
if(k == KERN_SUCCESS){
k = vm_read(target_task, address, size, &data, &data_count);
if(k == KERN_SUCCESS){
if(data_count > sizeof(struct mach_header)){
mh = (struct mach_header *)data;
if(mh->magic != MH_MAGIC ||
mh->filetype != MH_EXECUTE ||
data_count < sizeof(struct mach_header) +
mh->sizeofcmds){
if(mh->magic == MH_MAGIC &&
mh->filetype == MH_EXECUTE){
size = sizeof(struct mach_header) +
mh->sizeofcmds;
size = round_page(size);
k = vm_deallocate(mach_task_self(),data,
data_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 42);
return(DYLD_FAILURE);
}
k = vm_read(target_task, address, size,
&data, &data_count);
if(k != KERN_SUCCESS){
mh = NULL;
data = (pointer_t)NULL;
data_count = 0;
}
else if(data_count < size)
mh = NULL;
else
mh = (struct mach_header *)data;
}
else{
mh = NULL;
}
}
}
if(mh == NULL){
k = vm_deallocate(mach_task_self(), data, data_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 41);
return(DYLD_FAILURE);
}
}
}
else if(k != KERN_PROTECTION_FAILURE){
SET_MACH_DYLD_DEBUG_ERROR(k, 40);
return(DYLD_FAILURE);
}
address += size;
}
else if(k != KERN_NO_SPACE){
SET_MACH_DYLD_DEBUG_ERROR(k, 39);
return(DYLD_FAILURE);
}
}while(k != KERN_NO_SPACE && mh == NULL);
if(mh == NULL){
SET_LOCAL_DYLD_DEBUG_ERROR(38);
return(DYLD_FAILURE);
}
s = getsectbynamefromheader(mh, "__DATA", "__dyld");
if(s == NULL){
SET_LOCAL_DYLD_DEBUG_ERROR(37);
return(DYLD_FAILURE);
}
if(s->size < sizeof(struct dyld_data_section)){
k = vm_deallocate(mach_task_self(), data, data_count);
SET_MACH_DYLD_DEBUG_ERROR(k, 36);
return(DYLD_FAILURE);
}
addr = s->addr;
s = NULL;
k = vm_deallocate(mach_task_self(), data, data_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 35);
return(DYLD_FAILURE);
}
address = addr;
#ifdef __MACH30__
infoCnt = VM_REGION_BASIC_INFO_COUNT;
k = vm_region(target_task, &address, &size, VM_REGION_BASIC_INFO,
(vm_region_info_t)&info, &infoCnt, &objectName);
#else
k = vm_region(target_task, &address, &size, &protection,
&max_protection, &inheritance, &shared, &objectName,
&offset);
#endif
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 34);
return(DYLD_FAILURE);
}
if(address > addr + sizeof(struct dyld_data_section)){
SET_LOCAL_DYLD_DEBUG_ERROR(33);
return(DYLD_FAILURE);
}
k = vm_read(target_task, address, size, &data, &data_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 32);
return(DYLD_FAILURE);
}
if(size - (addr - address) < sizeof(struct dyld_data_section))
return(DYLD_FAILURE);
if(get == TRUE){
memcpy(dyld_data, (char *)data + addr - address,
sizeof(struct dyld_data_section));
}
else{
memcpy((char *)data + addr - address, dyld_data,
sizeof(struct dyld_data_section));
k = vm_write(target_task, address, data, data_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 31);
return(DYLD_FAILURE);
}
}
k = vm_deallocate(mach_task_self(), data, data_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 30);
return(DYLD_FAILURE);
}
#ifdef CORE_DEBUG
printf("got dyld data from 0x%x\n", (unsigned int)addr);
#endif
return(DYLD_SUCCESS);
}
static
enum dyld_debug_return
task_suspend_threads(
task_port_t target_task,
thread_port_array_t *threads,
unsigned int *count)
{
kern_return_t k;
unsigned int i;
k = task_threads(target_task, threads, count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 29);
return(DYLD_FAILURE);
}
for(i = 0; i < *count; i++){
k = thread_suspend((*threads)[i]);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 28);
return(DYLD_FAILURE);
}
}
return(DYLD_SUCCESS);
}
static
enum dyld_debug_return
task_resume_threads(
thread_port_array_t threads,
unsigned int count)
{
kern_return_t k;
unsigned int i;
for(i = 0; i < count; i++){
k = thread_resume((threads)[i]);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 27);
return(DYLD_FAILURE);
}
}
k = vm_deallocate(mach_task_self(), (vm_address_t)threads,
sizeof(threads[0]) * count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 26);
return(DYLD_FAILURE);
}
return(DYLD_SUCCESS);
}
static
enum dyld_debug_return
translate_port(
task_port_t target_task,
mach_port_name_t target_port,
mach_port_t *dest_port)
#ifdef __MACH30__
{
kern_return_t result;
mach_port_type_t target_port_type;
mach_port_t local_port = MACH_PORT_NULL;
mach_port_type_t local_type;
*dest_port = MACH_PORT_NULL;
result = mach_port_type(target_task, target_port, &target_port_type);
if(result != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(result, 25);
return(DYLD_FAILURE);
}
if((target_port_type & MACH_PORT_TYPE_RECEIVE) != 0)
result = mach_port_extract_right(target_task, target_port,
MACH_MSG_TYPE_MAKE_SEND, &local_port, &local_type);
else if((target_port_type & MACH_PORT_TYPE_SEND) != 0)
result = mach_port_extract_right(target_task, target_port,
MACH_MSG_TYPE_COPY_SEND, &local_port, &local_type);
if(result != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(result, 24);
return(DYLD_FAILURE);
}
*dest_port = local_port;
return(DYLD_SUCCESS);
}
#else
{
mach_port_name_t *names;
mach_port_type_array_t types;
unsigned int i, namesCount, typesCount;
kern_return_t k;
*dest_port = MACH_PORT_NULL;
k = port_names(target_task, &names, &namesCount, &types, &typesCount);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 23);
return(DYLD_FAILURE);
}
for(i = 0; i < namesCount; i++){
if(names[i] == target_port){
if(types[i] == PORT_TYPE_RECEIVE_OWN){
k = port_extract_receive(target_task, names[i],
(int *)dest_port);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 22);
return(DYLD_FAILURE);
}
k = port_insert_receive(target_task, *dest_port, names[i]);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 21);
return(DYLD_FAILURE);
}
break;
}
else if(types[i] == PORT_TYPE_SEND){
k = port_extract_send(target_task, names[i],
(int *)dest_port);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 20);
return(DYLD_FAILURE);
}
k = port_insert_send(target_task, *dest_port, names[i]);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 19);
return(DYLD_FAILURE);
}
break;
}
}
}
k = vm_deallocate(mach_task_self(), (vm_address_t)names,
sizeof(*names) * namesCount);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 18);
return(DYLD_FAILURE);
}
k = vm_deallocate(mach_task_self(), (vm_address_t)types,
sizeof(*types) * typesCount);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 17);
return(DYLD_FAILURE);
}
return(DYLD_SUCCESS);
}
#endif
static
enum dyld_debug_return
thread_start(
task_port_t task,
void *func,
long arg,
vm_offset_t stack_size,
thread_port_t *thread)
{
vm_address_t stack_base, stack_copy;
kern_return_t k;
enum dyld_debug_return d;
k = vm_allocate(task, &stack_base, stack_size, TRUE);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 16);
return(DYLD_FAILURE);
}
k = vm_allocate(mach_task_self(), &stack_copy, stack_size, TRUE);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 15);
return(DYLD_FAILURE);
}
k = thread_create(task, thread);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 14);
return(DYLD_FAILURE);
}
d = thread_setup(*thread, func, arg, stack_copy, stack_base,stack_size);
if(d != DYLD_SUCCESS)
return(d);
k = vm_write(task, stack_base, stack_copy, stack_size);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 13);
return(DYLD_FAILURE);
}
k = vm_deallocate(mach_task_self(), stack_copy, stack_size);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 12);
return(DYLD_FAILURE);
}
k = thread_resume(*thread);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 11);
return(DYLD_FAILURE);
}
return(DYLD_SUCCESS);
}
#ifdef __i386__
static
enum dyld_debug_return
thread_setup(
thread_port_t thread,
void *func,
long arg,
vm_address_t stack_copy,
vm_address_t stack_base,
vm_offset_t stack_size)
{
long *ltop, *rtop;
i386_thread_state_t state, *ts;
unsigned int state_count;
kern_return_t k;
ltop = (long *)((char *)stack_copy + stack_size);
rtop = (long *)((char *)stack_base + stack_size);
ts = &state;
state_count = i386_THREAD_STATE_COUNT;
k = thread_get_state(thread,
i386_THREAD_STATE,
(thread_state_t)&state,
&state_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 10);
return(DYLD_FAILURE);
}
ts->eip = (long)func;
*--ltop = (long)arg;
rtop--;
*--ltop = 0;
rtop--;
ts->esp = (long)rtop;
k = thread_set_state(thread,
i386_THREAD_STATE,
(thread_state_t)&state,
state_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 9);
return(DYLD_FAILURE);
}
#ifdef CORE_DEBUG
printf_i386_thread_state_t(&state);
#endif
return(DYLD_SUCCESS);
}
#endif
#ifdef m68k
static
enum dyld_debug_return
thread_setup(
thread_port_t thread,
void *func,
long arg,
vm_address_t stack_copy,
vm_address_t stack_base,
vm_offset_t stack_size)
{
long *ltop, *rtop;
struct m68k_thread_state_regs state, *ts;
unsigned int state_count;
kern_return_t k;
ltop = (long *)((char *)stack_copy + stack_size);
rtop = (long *)((char *)stack_base + stack_size);
ts = &state;
state_count = M68K_THREAD_STATE_REGS_COUNT;
k = thread_get_state(thread,
M68K_THREAD_STATE_REGS,
(thread_state_t)&state,
&state_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 8);
return(DYLD_FAILURE);
}
ts->pc = (long)func;
*--ltop = (long)arg;
rtop--;
*--ltop = 0;
rtop--;
ts->areg[6] = (long) 0;
ts->areg[7] = (long) rtop;
k = thread_set_state(thread,
M68K_THREAD_STATE_REGS,
(thread_state_t)&state,
state_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 7);
return(DYLD_FAILURE);
}
return(DYLD_SUCCESS);
}
#endif
#ifdef hppa
static
enum dyld_debug_return
thread_setup(
thread_port_t thread,
void *func,
long arg,
vm_address_t stack_copy,
vm_address_t stack_base,
vm_offset_t stack_size)
{
long rtop;
struct hp_pa_frame_thread_state frame_state;
struct hp_pa_integer_thread_state integer_state;
unsigned int frame_state_count, integer_state_count;
kern_return_t k;
rtop = (long)stack_base;
memset(&frame_state, 0, sizeof (frame_state));
frame_state.ts_pcoq_front = (long) func;
frame_state.ts_pcoq_back = frame_state.ts_pcoq_front + 4;
frame_state_count = HPPA_FRAME_THREAD_STATE_COUNT;
k = thread_set_state(thread,
HPPA_FRAME_THREAD_STATE,
(thread_state_t)&frame_state,
frame_state_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 6);
return(DYLD_FAILURE);
}
memset(&integer_state, 0, sizeof (integer_state));
integer_state.ts_gr26 = (unsigned long)arg;
integer_state.ts_gr2 = 0;
rtop += C_ARGSAVE_LEN;
integer_state.ts_gr30 = (rtop + C_STACK_ALIGN-1) & ~(C_STACK_ALIGN - 1);
integer_state_count = HPPA_INTEGER_THREAD_STATE_COUNT;
k = thread_set_state (thread,
HPPA_INTEGER_THREAD_STATE,
(thread_state_t)&integer_state,
integer_state_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 5);
return(DYLD_FAILURE);
}
#ifdef CORE_DEBUG
printf_hp_pa_integer_thread_state(&integer_state);
print_hp_pa_frame_thread_state(&frame_state);
#endif
return(DYLD_SUCCESS);
}
#endif
#ifdef sparc
static
enum dyld_debug_return
thread_setup(
thread_port_t thread,
void *func,
long arg,
vm_address_t stack_copy,
vm_address_t stack_base,
vm_offset_t stack_size)
{
long *ltop, *rtop;
struct sparc_thread_state_regs state, *ts;
unsigned int state_count;
kern_return_t k;
ltop = (long *)((char *)stack_copy + stack_size);
rtop = (long *)((char *)stack_base + stack_size);
ltop -= 64;
rtop -= 64;
ts = &state;
state_count = SPARC_THREAD_STATE_REGS_COUNT;
k = thread_get_state(thread,
SPARC_THREAD_STATE_REGS,
(thread_state_t)&state,
&state_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 4);
return(DYLD_FAILURE);
}
ts->regs.r_pc = (int)func;
ts->regs.r_npc = ts->regs.r_pc + 4;
ts->regs.r_o0 = (int)arg;
ts->regs.r_o7 = (int) 0;
ts->regs.r_o6 = (int) rtop;
k = thread_set_state(thread,
SPARC_THREAD_STATE_REGS,
(thread_state_t)&state,
state_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 3);
return(DYLD_FAILURE);
}
return(DYLD_SUCCESS);
}
#endif
#ifdef __ppc__
static
enum dyld_debug_return
thread_setup(
thread_port_t thread,
void *func,
long arg,
vm_address_t stack_copy,
vm_address_t stack_base,
vm_offset_t stack_size)
{
long *ltop, *rtop;
ppc_thread_state_t state, *ts;
unsigned int state_count;
kern_return_t k;
ltop = (long *)((char *)stack_copy + stack_size);
rtop = (long *)((char *)stack_base + stack_size);
ts = &state;
state_count = PPC_THREAD_STATE_COUNT;
k = thread_get_state(thread,
PPC_THREAD_STATE,
(thread_state_t)&state,
&state_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 2);
return(DYLD_FAILURE);
}
#ifdef CORE_DEBUG
state.r0 = 0;
state.r2 = 2;
state.r4 = 4;
state.r5 = 5;
state.r6 = 6;
state.r7 = 7;
state.r8 = 8;
state.r9 = 9;
state.r10 = 10;
state.r11 = 11;
state.r12 = 12;
state.r13 = 13;
state.r14 = 14;
state.r15 = 15;
state.r16 = 16;
state.r17 = 17;
state.r18 = 18;
state.r19 = 19;
state.r20 = 20;
state.r21 = 21;
state.r22 = 22;
state.r23 = 23;
state.r24 = 24;
state.r25 = 25;
state.r26 = 26;
state.r27 = 27;
state.r28 = 28;
state.r29 = 29;
state.r30 = 30;
state.r31 = 31;
state.ctr = 0;
state.xer = 0;
state.srr1 = 0;
#endif
state.srr0 = (long)func;
state.r3 = (unsigned long)arg;
state.lr = 0;
rtop -= 64;
state.r1 = (unsigned int)rtop;
k = thread_set_state(thread,
PPC_THREAD_STATE,
(thread_state_t)&state,
state_count);
if(k != KERN_SUCCESS){
SET_MACH_DYLD_DEBUG_ERROR(k, 1);
return(DYLD_FAILURE);
}
#ifdef CORE_DEBUG
printf_ppc_thread_state_t(&state);
#endif
return(DYLD_SUCCESS);
}
#endif
static void (*user_error_func)(struct dyld_debug_error_data *e) = NULL;
void
_dyld_debug_set_error_func(
void (*func)(struct dyld_debug_error_data *e))
{
user_error_func = func;
}
void
set_dyld_debug_error_data(
enum dyld_debug_return dyld_debug_return,
kern_return_t mach_error,
int dyld_debug_errno,
unsigned long local_error,
char *file_name,
unsigned long line_number)
{
#ifdef __MACH30__
struct dyld_debug_error_data _dyld_debug_error_data;
#endif
_dyld_debug_error_data.dyld_debug_return = dyld_debug_return;
_dyld_debug_error_data.mach_error = mach_error;
_dyld_debug_error_data.dyld_debug_errno = dyld_debug_errno;
_dyld_debug_error_data.local_error = local_error;
_dyld_debug_error_data.file_name = file_name;
_dyld_debug_error_data.line_number = line_number;
if(user_error_func != NULL)
user_error_func(&_dyld_debug_error_data);
}