int dummy_dyld_symbol = 1;
#include <stdio.h>
#include <stdlib.h>
#if __ppc__
#include "mach-o/dyld_debug.h"
#include "mach-o/dyld_gdb.h"
static const struct dyld_image_info* sImages = NULL;
static uint32_t sImagesCount = 0;
static task_port_t sImagesTaskPort = 0;
static void* xprocess_read(task_port_t target_task, const void* address, size_t len)
{
void* result = NULL;
mach_vm_address_t page_address = (uint32_t)address & (-4096);
mach_vm_address_t last_page_address = ((uint32_t)address + len + 4095) & (-4096);
mach_vm_size_t page_size = last_page_address - page_address;
uint8_t* local_start;
uint32_t local_len;
kern_return_t r = vm_read(
target_task,
page_address,
page_size,
(vm_offset_t*)&local_start,
&local_len);
if ( r == KERN_SUCCESS ) {
result = malloc(len);
if ( result != NULL )
memcpy(result, &local_start[(uint32_t)address - page_address], len);
vm_deallocate(mach_task_self(), (uintptr_t)local_start, local_len);
}
return result;
}
static const char* xprocess_read_string(task_port_t target_task, const void* address)
{
char* result = NULL;
mach_vm_address_t page_address = (uint32_t)address & (-4096);
mach_vm_size_t page_size = 0x2000; uint8_t* local_start;
uint32_t local_len;
kern_return_t r = vm_read(
target_task,
page_address,
page_size,
(vm_offset_t*)&local_start,
&local_len);
if ( r == KERN_SUCCESS ) {
const char* str = (char*)&local_start[(uint32_t)address - page_address];
return str;
}
return result;
}
static const struct dyld_all_image_infos* dyld_get_all_image_infos()
{
static const struct dyld_all_image_infos* (*p)() = NULL;
if ( p == NULL )
_dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p);
if ( p != NULL )
return p();
else
return NULL;
}
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)
{
if ( sImagesTaskPort == target_task ) {
unsigned int i;
for (i=0; i < sImagesCount; ++i) {
if ( module.header == sImages[i].imageLoadAddress ) {
const char* path = xprocess_read_string(sImagesTaskPort, sImages[i].imageFilePath);
if ( path != NULL ) {
*image_name = (char*)path;
*image_nameCnt = strlen(path);
*module_name = NULL;
*module_nameCnt = 0;
return DYLD_SUCCESS;
}
}
}
}
return DYLD_INVALID_ARGUMENTS;
}
void
_dyld_debug_set_error_func(
void (*func)(struct dyld_debug_error_data *e))
{
}
static ptrdiff_t slideForHeader(task_port_t target_task, const struct mach_header* otherAddressHeader)
{
const struct mach_header* mh = xprocess_read(target_task, otherAddressHeader, 0x2000);
if ( mh != NULL ) {
int i;
const struct segment_command *sgp =
(const struct segment_command *)((char*)mh + sizeof(mh));
for (i = 0; i < mh->ncmds; i++){
if (sgp->cmd == LC_SEGMENT) {
if (sgp->fileoff == 0 && sgp->filesize != 0) {
return (uintptr_t)mh - (uintptr_t)sgp->vmaddr;
}
}
sgp = (const struct segment_command *)((char *)sgp + sgp->cmdsize);
}
free((void*)mh);
}
return 0;
}
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))
{
sImages = NULL;
sImagesCount = 0;
sImagesTaskPort = 0;
const struct dyld_all_image_infos* infoOtherAddressSpace = dyld_get_all_image_infos();
if ( infoOtherAddressSpace != NULL ) {
const struct dyld_all_image_infos* infos;
infos = (const struct dyld_all_image_infos*)xprocess_read(target_task, infoOtherAddressSpace, sizeof(struct dyld_all_image_infos));
if ( infos != NULL ) {
if ( infos->version == 1 ) {
sImages = xprocess_read(target_task, infos->infoArray, infos->infoArrayCount * sizeof(struct dyld_image_info));
if ( sImages != NULL ) {
int i;
sImagesCount = infos->infoArrayCount;
sImagesTaskPort = target_task;
for (i=0; i < infos->infoArrayCount; ++i) {
struct dyld_event addEvent;
bzero(&addEvent, sizeof(struct dyld_event));
const struct mach_header* mh = sImages[i].imageLoadAddress;
addEvent.type = DYLD_IMAGE_ADDED;
addEvent.arg[0].header = (struct mach_header*)mh;
addEvent.arg[0].vmaddr_slide = slideForHeader(target_task, mh);
addEvent.arg[0].module_index = 0;
(*dyld_event_routine)(addEvent);
}
}
}
free((void*)infos);
}
}
struct dyld_event event;
event.type = DYLD_PAST_EVENTS_END;
(*dyld_event_routine)(event);
return DYLD_SUCCESS;
}
#endif