Add the old memory search back to support the VC injection tool again
This commit is contained in:
parent
0e018f8392
commit
60df33bb23
106
src/common/cafe.h
Normal file
106
src/common/cafe.h
Normal file
@ -0,0 +1,106 @@
|
||||
#ifndef TCPGECKO_STACK_H
|
||||
#define TCPGECKO_STACK_H
|
||||
|
||||
#include "kernel_types.h"
|
||||
|
||||
typedef struct OSThread;
|
||||
|
||||
typedef struct OSThreadLink {
|
||||
OSThread *next;
|
||||
OSThread *prev;
|
||||
} OSThreadLink;
|
||||
|
||||
typedef struct OSThreadQueue {
|
||||
OSThread *head;
|
||||
OSThread *tail;
|
||||
void *parentStruct;
|
||||
u32 reserved;
|
||||
} OSThreadQueue;
|
||||
|
||||
typedef struct OSMessage {
|
||||
u32 message;
|
||||
u32 data0;
|
||||
u32 data1;
|
||||
u32 data2;
|
||||
} OSMessage;
|
||||
|
||||
typedef struct OSMessageQueue {
|
||||
u32 tag;
|
||||
char *name;
|
||||
u32 reserved;
|
||||
|
||||
OSThreadQueue sendQueue;
|
||||
OSThreadQueue recvQueue;
|
||||
OSMessage *messages;
|
||||
int msgCount;
|
||||
int firstIndex;
|
||||
int usedCount;
|
||||
} OSMessageQueue;
|
||||
|
||||
typedef struct OSContext {
|
||||
char tag[8];
|
||||
|
||||
u32 gpr[32];
|
||||
|
||||
u32 cr;
|
||||
u32 lr;
|
||||
u32 ctr;
|
||||
u32 xer;
|
||||
|
||||
u32 srr0;
|
||||
u32 srr1;
|
||||
|
||||
u32 ex0;
|
||||
u32 ex1;
|
||||
|
||||
u32 exception_type;
|
||||
u32 reserved;
|
||||
|
||||
double fpscr;
|
||||
double fpr[32];
|
||||
|
||||
u16 spinLockCount;
|
||||
u16 state;
|
||||
|
||||
u32 gqr[8];
|
||||
u32 pir;
|
||||
double psf[32];
|
||||
|
||||
u64 coretime[3];
|
||||
u64 starttime;
|
||||
|
||||
u32 error;
|
||||
u32 attributes;
|
||||
|
||||
u32 pmc1;
|
||||
u32 pmc2;
|
||||
u32 pmc3;
|
||||
u32 pmc4;
|
||||
u32 mmcr0;
|
||||
u32 mmcr1;
|
||||
} OSContext;
|
||||
|
||||
typedef int (*ThreadFunc)(int argc, void *argv);
|
||||
|
||||
typedef struct OSThread {
|
||||
OSContext context;
|
||||
|
||||
u32 txtTag;
|
||||
u8 state;
|
||||
u8 attr;
|
||||
|
||||
short threadId;
|
||||
int suspend;
|
||||
int priority;
|
||||
|
||||
char _[0x394 - 0x330];
|
||||
|
||||
void *stackBase;
|
||||
void *stackEnd;
|
||||
|
||||
ThreadFunc entryPoint;
|
||||
|
||||
char _3A0[0x6A0 - 0x3A0];
|
||||
} OSThread;
|
||||
|
||||
#endif
|
@ -2,12 +2,12 @@
|
||||
#define FS_DEFS_H
|
||||
|
||||
#include "types.h"
|
||||
#include "kernel_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* FS defines and types */
|
||||
#define FS_MAX_LOCALPATH_SIZE 511
|
||||
#define FS_MAX_MOUNTPATH_SIZE 128
|
||||
@ -31,7 +31,6 @@ extern "C" {
|
||||
|
||||
#define FS_SOURCETYPE_EXTERNAL 0
|
||||
#define FS_SOURCETYPE_HFIO 1
|
||||
#define FS_SOURCETYPE_HFIO 1
|
||||
/* FS data buffer alignment */
|
||||
#define FS_IO_BUFFER_ALIGN 64
|
||||
|
||||
|
10
src/common/kernel_types.h
Normal file
10
src/common/kernel_types.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
typedef unsigned char u8;
|
||||
// typedef unsigned int uint8_t;
|
||||
typedef unsigned short u16;
|
||||
// typedef unsigned int uint16_t;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned int uint32_t;
|
||||
// typedef unsigned long uint64_t;
|
||||
typedef unsigned long long u64;
|
@ -5,106 +5,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*struct OSThread;
|
||||
|
||||
struct OSThreadLink {
|
||||
OSThread *next;
|
||||
OSThread *prev;
|
||||
};
|
||||
|
||||
struct OSThreadQueue {
|
||||
OSThread *head;
|
||||
OSThread *tail;
|
||||
void *parentStruct;
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
struct OSMessage {
|
||||
u32 message;
|
||||
u32 data0;
|
||||
u32 data1;
|
||||
u32 data2;
|
||||
};
|
||||
|
||||
struct OSMessageQueue {
|
||||
u32 tag;
|
||||
char *name;
|
||||
u32 reserved;
|
||||
|
||||
OSThreadQueue sendQueue;
|
||||
OSThreadQueue recvQueue;
|
||||
OSMessage *messages;
|
||||
int msgCount;
|
||||
int firstIndex;
|
||||
int usedCount;
|
||||
};
|
||||
|
||||
struct OSContext {
|
||||
char tag[8];
|
||||
|
||||
u32 gpr[32];
|
||||
|
||||
u32 cr;
|
||||
u32 lr;
|
||||
u32 ctr;
|
||||
u32 xer;
|
||||
|
||||
u32 srr0;
|
||||
u32 srr1;
|
||||
|
||||
u32 ex0;
|
||||
u32 ex1;
|
||||
|
||||
u32 exception_type;
|
||||
u32 reserved;
|
||||
|
||||
double fpscr;
|
||||
double fpr[32];
|
||||
|
||||
u16 spinLockCount;
|
||||
u16 state;
|
||||
|
||||
u32 gqr[8];
|
||||
u32 pir;
|
||||
double psf[32];
|
||||
|
||||
u64 coretime[3];
|
||||
u64 starttime;
|
||||
|
||||
u32 error;
|
||||
u32 attributes;
|
||||
|
||||
u32 pmc1;
|
||||
u32 pmc2;
|
||||
u32 pmc3;
|
||||
u32 pmc4;
|
||||
u32 mmcr0;
|
||||
u32 mmcr1;
|
||||
};
|
||||
|
||||
typedef int (*ThreadFunc)(int argc, void *argv);
|
||||
|
||||
struct OSThread {
|
||||
OSContext context;
|
||||
|
||||
u32 txtTag;
|
||||
u8 state;
|
||||
u8 attr;
|
||||
|
||||
short threadId;
|
||||
int suspend;
|
||||
int priority;
|
||||
|
||||
char _[0x394 - 0x330];
|
||||
|
||||
void *stackBase;
|
||||
void *stackEnd;
|
||||
|
||||
ThreadFunc entryPoint;
|
||||
|
||||
char _3A0[0x6A0 - 0x3A0];
|
||||
};*/
|
||||
|
||||
typedef struct _OsSpecifics
|
||||
{
|
||||
unsigned int addr_OSDynLoad_Acquire;
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include <gctypes.h>
|
||||
#include "fs_defs.h"
|
||||
|
||||
u8 gSettingLaunchPyGecko __attribute__((section(".data"))) = 0;
|
||||
u8 gSettingUseUpdatepath __attribute__((section(".data"))) = 0;
|
||||
u8 gSettingPadconMode __attribute__((section(".data"))) = 0;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef RETAINS_VARS_H_
|
||||
#define RETAINS_VARS_H_
|
||||
#include <gctypes.h>
|
||||
#include "kernel_types.h"
|
||||
|
||||
extern u8 gSettingLaunchPyGecko;
|
||||
extern u8 gSettingUseUpdatepath;
|
||||
|
@ -22,6 +22,7 @@
|
||||
* distribution.
|
||||
***************************************************************************/
|
||||
#include "os_functions.h"
|
||||
#include "../common/fs_defs.h"
|
||||
|
||||
EXPORT_DECL(s32, AOC_Initialize, void);
|
||||
EXPORT_DECL(s32, AOC_Finalize, void);
|
||||
|
@ -62,6 +62,8 @@ EXPORT_DECL(int, OSIsDebuggerPresent, void);
|
||||
|
||||
EXPORT_DECL(void, OSRestoreInterrupts, void);
|
||||
|
||||
// EXPORT_DECL(bool, OSSendMessage, struct OSMessageQueue* mq, struct OSMessage* msg, s32 flags);
|
||||
|
||||
EXPORT_DECL(void, OSSetDABR, int, int, int, int);
|
||||
|
||||
EXPORT_DECL(void, OSSetIABR, int, int);
|
||||
@ -119,6 +121,8 @@ EXPORT_DECL(void, OSFatal, const char *msg);
|
||||
|
||||
EXPORT_DECL(void, OSSetExceptionCallback, u8 exceptionType, exception_callback callback);
|
||||
|
||||
EXPORT_DECL(void, OSSetExceptionCallbackEx, u8 exceptionMode, u8 exceptionType, exception_callback callback);
|
||||
|
||||
EXPORT_DECL(void, __OSSetInterruptHandler, u8 exceptionType, exception_callback callback);
|
||||
|
||||
EXPORT_DECL(void, DCFlushRange, const void *addr, u32
|
||||
@ -265,6 +269,7 @@ void InitOSFunctionPointers(void) {
|
||||
OS_FIND_EXPORT(coreinit_handle, OSFatal);
|
||||
OS_FIND_EXPORT(coreinit_handle, OSGetTitleID);
|
||||
OS_FIND_EXPORT(coreinit_handle, OSSetExceptionCallback);
|
||||
OS_FIND_EXPORT(coreinit_handle, OSSetExceptionCallbackEx);
|
||||
OS_FIND_EXPORT(coreinit_handle, __OSSetInterruptHandler);
|
||||
OS_FIND_EXPORT(coreinit_handle, DCFlushRange);
|
||||
OS_FIND_EXPORT(coreinit_handle, ICInvalidateRange);
|
||||
@ -300,6 +305,7 @@ void InitOSFunctionPointers(void) {
|
||||
OS_FIND_EXPORT(coreinit_handle, OSIsInterruptEnabled);
|
||||
OS_FIND_EXPORT(coreinit_handle, OSIsDebuggerPresent);
|
||||
OS_FIND_EXPORT(coreinit_handle, OSRestoreInterrupts);
|
||||
// OS_FIND_EXPORT(coreinit_handle, OSSendMessage);
|
||||
OS_FIND_EXPORT(coreinit_handle, OSSetDABR);
|
||||
OS_FIND_EXPORT(coreinit_handle, OSSetIABR);
|
||||
OS_FIND_EXPORT(coreinit_handle, OSGetCurrentThread);
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <gctypes.h>
|
||||
#include "common/os_defs.h"
|
||||
// #include "../cafe.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -148,6 +149,8 @@ extern int (*OSIsInterruptEnabled)(void);
|
||||
|
||||
extern int (*OSIsDebuggerPresent)(void);
|
||||
|
||||
// extern bool (*OSSendMessage)(struct OSMessageQueue*, struct OSMessage*, s32);
|
||||
|
||||
extern void (*OSRestoreInterrupts)(void);
|
||||
|
||||
extern void (*OSSetDABR)(int, int, int, int);
|
||||
@ -232,6 +235,8 @@ typedef unsigned char (*exception_callback)(void *interruptedContext);
|
||||
|
||||
extern void (*OSSetExceptionCallback)(u8 exceptionType, exception_callback callback);
|
||||
|
||||
extern void (*OSSetExceptionCallbackEx)(u8 exceptionMode, u8 exceptionType, exception_callback callback);
|
||||
|
||||
extern void (*__OSSetInterruptHandler)(u8 interruptType, exception_callback callback);
|
||||
|
||||
extern int (*OSAllocFromSystem)(unsigned int size, unsigned int align);
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <gctypes.h>
|
||||
#include "common/common.h"
|
||||
#include "../common/common.h"
|
||||
#include "memory_area_table.h"
|
||||
|
||||
typedef struct _memory_values_t
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include "../common/kernel_defs.h"
|
||||
#include "../common/common.h"
|
||||
#include "../dynamic_libs/os_functions.h"
|
||||
#include "../utils/utils.h"
|
||||
#include "syscalls.h"
|
||||
|
||||
extern void my_PrepareTitle_hook(void);
|
||||
|
105
src/pygecko.c
105
src/pygecko.c
@ -12,16 +12,12 @@
|
||||
#include "dynamic_libs/gx2_functions.h"
|
||||
#include "kernel/syscalls.h"
|
||||
#include "dynamic_libs/fs_functions.h"
|
||||
#include "system/exception_handler.h"
|
||||
#include "utils/logger.h"
|
||||
#include "system/memory.h"
|
||||
#include "system/breakpoints.h"
|
||||
#include "system/threads.h"
|
||||
#include "system/hardware_breakpoints.h"
|
||||
#include "utils/linked_list.h"
|
||||
#include "assertions.h"
|
||||
#include "kernel.h"
|
||||
#include "address.h"
|
||||
#include "disassembler.h"
|
||||
#include "system/stack.h"
|
||||
|
||||
void *client;
|
||||
void *commandBlock;
|
||||
@ -58,7 +54,8 @@ struct pygecko_bss_t {
|
||||
#define COMMAND_FOLLOW_POINTER 0x60
|
||||
#define COMMAND_REMOTE_PROCEDURE_CALL 0x70
|
||||
#define COMMAND_GET_SYMBOL 0x71
|
||||
#define COMMAND_MEMORY_SEARCH 0x73
|
||||
#define COMMAND_MEMORY_SEARCH 0x72
|
||||
#define COMMAND_ADVANCED_MEMORY_SEARCH 0x73
|
||||
#define COMMAND_EXECUTE_ASSEMBLY 0x81
|
||||
#define COMMAND_PAUSE_CONSOLE 0x82
|
||||
#define COMMAND_RESUME_CONSOLE 0x83
|
||||
@ -67,6 +64,10 @@ struct pygecko_bss_t {
|
||||
#define COMMAND_GET_OS_VERSION 0x9A
|
||||
#define COMMAND_SET_DATA_BREAKPOINT 0xA0
|
||||
#define COMMAND_SET_INSTRUCTION_BREAKPOINT 0xA2
|
||||
#define COMMAND_TOGGLE_BREAKPOINT 0xA5
|
||||
#define COMMAND_REMOVE_ALL_BREAKPOINTS 0xA6
|
||||
#define COMMAND_POKE_REGISTERS 0xA7
|
||||
#define COMMAND_GET_STACK_TRACE 0xA8
|
||||
#define COMMAND_RUN_KERNEL_COPY_SERVICE 0xCD
|
||||
#define COMMAND_IOSU_HAX_READ_FILE 0xD0
|
||||
#define COMMAND_GET_VERSION_HASH 0xE0
|
||||
@ -104,7 +105,8 @@ unsigned char *memcpy_buffer[DATA_BUFFER_SIZE];
|
||||
|
||||
void pygecko_memcpy(unsigned char *destinationBuffer, unsigned char *sourceBuffer, unsigned int length) {
|
||||
memcpy(memcpy_buffer, sourceBuffer, length);
|
||||
SC0x25_KernelCopyData((unsigned int) OSEffectiveToPhysical(destinationBuffer), (unsigned int) &memcpy_buffer, length);
|
||||
SC0x25_KernelCopyData((unsigned int) OSEffectiveToPhysical(destinationBuffer), (unsigned int) &memcpy_buffer,
|
||||
length);
|
||||
DCFlushRange(destinationBuffer, (u32) length);
|
||||
}
|
||||
|
||||
@ -121,7 +123,7 @@ unsigned long getConsoleStatePatchAddress() {
|
||||
// Acquire the RPL and function
|
||||
log_print("Acquiring...\n");
|
||||
unsigned int avm_handle;
|
||||
OSDynLoad_Acquire("avm.rpl", (u32 * ) & avm_handle);
|
||||
OSDynLoad_Acquire("avm.rpl", (u32 *) &avm_handle);
|
||||
ASSERT_ALLOCATED(avm_handle, "avm.rpl")
|
||||
OSDynLoad_FindExport((u32) avm_handle, 0, "AVMGetDRCScanMode", &AVMGetDRCScanMode);
|
||||
ASSERT_ALLOCATED(AVMGetDRCScanMode, "AVMGetDRCScanMode")
|
||||
@ -405,7 +407,6 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
|
||||
ret = sendByte(bss, clientfd, ONLY_ZEROS_READ);
|
||||
CHECK_ERROR(ret < 0)
|
||||
} else {
|
||||
// TODO Compression of ptr, sending of status, compressed size and data, length: 1 + 4 + len(data)
|
||||
buffer[0] = NON_ZEROS_READ;
|
||||
|
||||
if (useKernRead) {
|
||||
@ -968,7 +969,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
|
||||
ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (thread count)");
|
||||
|
||||
// Send the thread addresses and data
|
||||
struct node* currentThread = threads;
|
||||
struct node *currentThread = threads;
|
||||
while (currentThread != NULL) {
|
||||
int data = (int) currentThread->data;
|
||||
log_printf("Thread data: %08x\n", data);
|
||||
@ -1130,6 +1131,27 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
|
||||
break;
|
||||
}
|
||||
case COMMAND_MEMORY_SEARCH: {
|
||||
ret = recvwait(bss, clientfd, buffer, sizeof(int) * 3);
|
||||
CHECK_ERROR(ret < 0);
|
||||
int address = ((int *) buffer)[0];
|
||||
int value = ((int *) buffer)[1];
|
||||
int length = ((int *) buffer)[2];
|
||||
int index;
|
||||
int foundAddress = 0;
|
||||
for (index = address; index < address + length; index += sizeof(int)) {
|
||||
if (*(int *) index == value) {
|
||||
foundAddress = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
((int *) buffer)[0] = foundAddress;
|
||||
ret = sendwait(bss, clientfd, buffer, sizeof(int));
|
||||
CHECK_ERROR(ret < 0)
|
||||
|
||||
break;
|
||||
}
|
||||
case COMMAND_ADVANCED_MEMORY_SEARCH: {
|
||||
// Receive the initial data
|
||||
ret = recvwait(bss, clientfd, buffer, 4 * 6);
|
||||
ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (memory search information)")
|
||||
@ -1263,6 +1285,57 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
|
||||
setInstructionAddressBreakPointRegister(address);
|
||||
|
||||
break;
|
||||
}
|
||||
case COMMAND_TOGGLE_BREAKPOINT: {
|
||||
// Read the address
|
||||
ret = recvwait(bss, clientfd, buffer, sizeof(int));
|
||||
ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (toggle breakpoint)");
|
||||
u32 address = ((unsigned int *) buffer)[0];
|
||||
|
||||
struct Breakpoint *breakpoint = getBreakpoint(address, GENERAL_BREAKPOINTS_COUNT);
|
||||
|
||||
if (breakpoint != NULL) {
|
||||
breakpoint = removeBreakpoint(breakpoint);
|
||||
} else {
|
||||
breakpoint = allocateBreakpoint();
|
||||
|
||||
if (breakpoint != NULL) {
|
||||
breakpoint = setBreakpoint(breakpoint, address);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case COMMAND_REMOVE_ALL_BREAKPOINTS: {
|
||||
removeAllBreakpoints();
|
||||
break;
|
||||
}
|
||||
case COMMAND_GET_STACK_TRACE: {
|
||||
log_print("Getting stack trace...\n");
|
||||
struct node *stackTrace = getStackTrace(NULL);
|
||||
int stackTraceLength = length(stackTrace);
|
||||
|
||||
// Let the client know the length beforehand
|
||||
int bufferIndex = 0;
|
||||
((int *) buffer)[bufferIndex++] = stackTraceLength;
|
||||
|
||||
struct node *currentStackTraceElement = stackTrace;
|
||||
while (currentStackTraceElement != NULL) {
|
||||
int address = (int) currentStackTraceElement->data;
|
||||
log_printf("Stack trace element address: %08x\n", address);
|
||||
((int *) buffer)[bufferIndex++] = (int) currentStackTraceElement->data;
|
||||
|
||||
currentStackTraceElement = currentStackTraceElement->next;
|
||||
}
|
||||
|
||||
log_printf("Sending stack trace with length %i\n", stackTraceLength);
|
||||
ret = sendwait(bss, clientfd, buffer, sizeof(int) + stackTraceLength);
|
||||
ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (stack trace)");
|
||||
|
||||
break;
|
||||
}
|
||||
case COMMAND_POKE_REGISTERS: {
|
||||
|
||||
}
|
||||
case COMMAND_RUN_KERNEL_COPY_SERVICE: {
|
||||
if (!kernelCopyServiceStarted) {
|
||||
@ -1290,9 +1363,9 @@ struct sockaddr_in socketAddress;
|
||||
struct pygecko_bss_t *bss;
|
||||
|
||||
static int runTCPGeckoServer(int argc, void *argv) {
|
||||
bss = argv;
|
||||
bss = (struct pygecko_bss_t *) argv;
|
||||
|
||||
// setup_os_exceptions();
|
||||
setup_os_exceptions();
|
||||
socket_lib_init();
|
||||
|
||||
log_init(COMPUTER_IP_ADDRESS);
|
||||
@ -1307,17 +1380,17 @@ static int runTCPGeckoServer(int argc, void *argv) {
|
||||
CHECK_ERROR(sockfd == -1)
|
||||
|
||||
log_printf("bind()...\n");
|
||||
ret = bind(sockfd, (void *) &socketAddress, 16);
|
||||
ret = bind(sockfd, (struct sockaddr *) &socketAddress, (s32) 16);
|
||||
CHECK_ERROR(ret < 0)
|
||||
|
||||
log_printf("listen()...\n");
|
||||
ret = listen(sockfd, 20);
|
||||
ret = listen(sockfd, (s32) 20);
|
||||
CHECK_ERROR(ret < 0)
|
||||
|
||||
while (true) {
|
||||
log_printf("accept()...\n");
|
||||
len = 16;
|
||||
clientfd = accept(sockfd, (void *) &socketAddress, &len);
|
||||
clientfd = accept(sockfd, (struct sockaddr *) &socketAddress, (s32 * ) & len);
|
||||
CHECK_ERROR(clientfd == -1)
|
||||
log_printf("commands()...\n");
|
||||
ret = processCommands(bss, clientfd);
|
||||
|
@ -133,12 +133,12 @@ static unsigned char isi_exception_cb(void *context) {
|
||||
return exceptionCallback(context, 1);
|
||||
}
|
||||
|
||||
static unsigned char program_exception_cb(void *context) {
|
||||
unsigned char program_exception_cb(void *context) {
|
||||
return exceptionCallback(context, 2);
|
||||
}
|
||||
|
||||
void setup_os_exceptions() {
|
||||
OSSetExceptionCallback(OS_EXCEPTION_DSI, &dsi_exception_cb);
|
||||
OSSetExceptionCallback(OS_EXCEPTION_ISI, &isi_exception_cb);
|
||||
OSSetExceptionCallback(OS_EXCEPTION_PROGRAM, &program_exception_cb);
|
||||
// OSSetExceptionCallback(OS_EXCEPTION_PROGRAM, &program_exception_cb);
|
||||
}
|
@ -6,6 +6,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../utils/stringify.h"
|
||||
#include "../common/kernel_types.h"
|
||||
|
||||
#define OS_EXCEPTION_DSI 2
|
||||
#define OS_EXCEPTION_ISI 3
|
||||
|
249
src/system/software_breakpoints.h
Normal file
249
src/system/software_breakpoints.h
Normal file
@ -0,0 +1,249 @@
|
||||
// https://github.com/Kinnay/DiiBugger/blob/master/wiiu_code/server.cpp
|
||||
|
||||
#ifndef TCPGECKO_BREAKPOINT_EXECUTE_H
|
||||
#define TCPGECKO_BREAKPOINT_EXECUTE_H
|
||||
|
||||
#include "utilities.h"
|
||||
#include "exception_handler.h"
|
||||
|
||||
#define OS_EXCEPTION_DSI 2
|
||||
#define OS_EXCEPTION_ISI 3
|
||||
#define OS_EXCEPTION_PROGRAM 6
|
||||
|
||||
#define OS_EXCEPTION_MODE_THREAD 1
|
||||
#define OS_EXCEPTION_MODE_GLOBAL 2
|
||||
#define OS_EXCEPTION_MODE_THREAD_ALL_CORES 3
|
||||
#define OS_EXCEPTION_MODE_GLOBAL_ALL_CORES 4
|
||||
|
||||
struct Breakpoint {
|
||||
u32 address;
|
||||
u32 instruction;
|
||||
};
|
||||
|
||||
#define INSTRUCTION_TRAP 0x7FE00008 // https://stackoverflow.com/a/10286705/3764804
|
||||
#define INSTRUCTION_NOP 0x60000000
|
||||
|
||||
#define STEP1 10
|
||||
#define STEP2 11
|
||||
|
||||
#define GENERAL_BREAKPOINTS_COUNT 10
|
||||
#define STEP_BREAKPOINTS_COUNT 2
|
||||
|
||||
unsigned char ProgramHandler_Debug(void *interruptedContext) {
|
||||
OSFatal("Hi");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void installBreakpointHandler() {
|
||||
OSSetExceptionCallbackEx((u8) OS_EXCEPTION_MODE_GLOBAL_ALL_CORES, (u8) OS_EXCEPTION_PROGRAM, ProgramHandler_Debug);
|
||||
}
|
||||
|
||||
struct Breakpoint breakpoints[GENERAL_BREAKPOINTS_COUNT + STEP_BREAKPOINTS_COUNT];
|
||||
|
||||
struct Breakpoint *removeBreakpoint(struct Breakpoint *breakpoint) {
|
||||
writeCode(breakpoint->address, breakpoint->instruction);
|
||||
breakpoint->address = 0;
|
||||
breakpoint->instruction = 0;
|
||||
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
void removeAllBreakpoints() {
|
||||
for (int index = 0; index < GENERAL_BREAKPOINTS_COUNT; index++) {
|
||||
struct Breakpoint *breakpoint = &breakpoints[index];
|
||||
if (breakpoint->address != 0) {
|
||||
removeBreakpoint(breakpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Breakpoint *setBreakpoint(struct Breakpoint *breakpoint, u32 address) {
|
||||
breakpoint->address = address;
|
||||
breakpoint->instruction = *(u32 *) address;
|
||||
writeCode(address, (u32) INSTRUCTION_TRAP);
|
||||
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
struct Breakpoint *getBreakpoint(u32 address, int size) {
|
||||
for (int index = 0; index < GENERAL_BREAKPOINTS_COUNT; index++) {
|
||||
if (breakpoints[index].address == address) {
|
||||
return &breakpoints[index];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pokeRegisters(OSContext context, uint32_t gpr[32], double fpr[32]) {
|
||||
memcpy(&context.gpr, &gpr, sizeof(gpr));
|
||||
// memcpy(&context.fpr, &fpr, sizeof(fpr));
|
||||
}
|
||||
|
||||
struct Breakpoint *allocateBreakpoint() {
|
||||
for (int breakpointsIndex = 0; breakpointsIndex < GENERAL_BREAKPOINTS_COUNT; breakpointsIndex++) {
|
||||
if (breakpoints[breakpointsIndex].address == 0) {
|
||||
return &breakpoints[breakpointsIndex];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO
|
||||
u32 stepSource;
|
||||
|
||||
void RestoreStepInstructions() {
|
||||
writeCode(breakpoints[STEP1].address, breakpoints[STEP1].instruction);
|
||||
breakpoints[STEP1].address = 0;
|
||||
breakpoints[STEP1].instruction = 0;
|
||||
if (breakpoints[STEP2].address) {
|
||||
writeCode(breakpoints[STEP2].address, breakpoints[STEP2].instruction);
|
||||
breakpoints[STEP2].address = 0;
|
||||
breakpoints[STEP2].instruction = 0;
|
||||
}
|
||||
|
||||
struct Breakpoint *breakpoint = getBreakpoint(stepSource, GENERAL_BREAKPOINTS_COUNT);
|
||||
if (breakpoint) {
|
||||
writeCode(breakpoint->address, (u32) INSTRUCTION_TRAP);
|
||||
}
|
||||
}
|
||||
|
||||
u32 getInstruction(u32 address) {
|
||||
struct Breakpoint *breakpoint = getBreakpoint(address, GENERAL_BREAKPOINTS_COUNT + STEP_BREAKPOINTS_COUNT);
|
||||
if (breakpoint != NULL) {
|
||||
return breakpoint->instruction;
|
||||
}
|
||||
|
||||
return *(u32 *) address;
|
||||
}
|
||||
|
||||
struct Breakpoint *getBreakpointRange(u32 address, u32 length, struct Breakpoint *previousBreakpoint) {
|
||||
unsigned long startingIndex = 0;
|
||||
if (previousBreakpoint) {
|
||||
startingIndex = (previousBreakpoint - breakpoints) + 1;
|
||||
}
|
||||
|
||||
for (unsigned long index = startingIndex; index < GENERAL_BREAKPOINTS_COUNT + STEP_BREAKPOINTS_COUNT; index++) {
|
||||
struct Breakpoint breakpoint = breakpoints[index];
|
||||
|
||||
if (breakpoint.address >= address && breakpoint.address < address + length) {
|
||||
return &breakpoints[index];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO
|
||||
OSContext crashContext;
|
||||
|
||||
void predictStepAddresses(bool stepOver) {
|
||||
u32 currentAddress = crashContext.srr0;
|
||||
u32 instruction = getInstruction(currentAddress);
|
||||
|
||||
struct Breakpoint *step1 = &breakpoints[STEP1];
|
||||
struct Breakpoint *step2 = &breakpoints[STEP2];
|
||||
step1->address = currentAddress + 4;
|
||||
step2->address = 0;
|
||||
|
||||
u8 opcode = instruction >> 26;
|
||||
if (opcode == 19) {
|
||||
u16 XO = (instruction >> 1) & 0x3FF;
|
||||
bool LK = instruction & 1;
|
||||
if (!LK || !stepOver) {
|
||||
if (XO == 16) step2->address = crashContext.lr; // bclr
|
||||
if (XO == 528) step2->address = crashContext.ctr; // bcctr
|
||||
}
|
||||
} else if (opcode == 18) { //b
|
||||
bool AA = instruction & 2;
|
||||
bool LK = instruction & 1;
|
||||
u32 LI = instruction & 0x3FFFFFC;
|
||||
if (!LK || !stepOver) {
|
||||
if (AA) step1->address = LI;
|
||||
else {
|
||||
if (LI & 0x2000000) LI -= 0x4000000;
|
||||
step1->address = currentAddress + LI;
|
||||
}
|
||||
}
|
||||
} else if (opcode == 16) { //bc
|
||||
bool AA = instruction & 2;
|
||||
bool LK = instruction & 1;
|
||||
u32 BD = instruction & 0xFFFC;
|
||||
if (!LK || !stepOver) {
|
||||
if (AA) step2->address = BD;
|
||||
else {
|
||||
if (BD & 0x8000) BD -= 0x10000;
|
||||
step2->address = currentAddress + BD;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReportCrash(u32 msg) {
|
||||
/*crashState = CRASH_STATE_UNRECOVERABLE;
|
||||
|
||||
struct OSMessage messageStruct;
|
||||
messageStruct.message = msg;
|
||||
messageStruct.data0 = (u32) & crashContext;
|
||||
messageStruct.data1 = sizeof(crashContext);
|
||||
OSSendMessage(&serverQueue, &messageStruct, OS_MESSAGE_BLOCK);
|
||||
while (true) {
|
||||
OSSleepTicks((u64) 1000000);
|
||||
}*/
|
||||
}
|
||||
|
||||
/*void HandleProgram(OSContext crashContext) {
|
||||
//Check if the exception was caused by a breakpoint
|
||||
if (!(crashContext.srr1 & 0x20000)) {
|
||||
ReportCrash(SERVER_MESSAGE_PROGRAM);
|
||||
}
|
||||
|
||||
// Special case, the twu instruction at the start
|
||||
if (crashContext.srr0 == (u32) entryPoint + 0x48) {
|
||||
writeCode(crashContext.srr0, (u32) INSTRUCTION_NOP);
|
||||
}
|
||||
|
||||
if (stepState == STEP_STATE_RUNNING || stepState == STEP_STATE_STEPPING) {
|
||||
crashState = CRASH_STATE_BREAKPOINT;
|
||||
|
||||
OSMessage message;
|
||||
message.message = SERVER_MESSAGE_PROGRAM;
|
||||
message.data0 = (u32) & crashContext;
|
||||
message.data1 = sizeof(crashContext);
|
||||
OSSendMessage(&serverQueue, &message, OS_MESSAGE_BLOCK);
|
||||
OSReceiveMessage(&clientQueue, &message, OS_MESSAGE_BLOCK);
|
||||
|
||||
if (stepState == STEP_STATE_STEPPING) {
|
||||
RestoreStepInstructions();
|
||||
}
|
||||
|
||||
Breakpoint *breakpoint = getBreakpoint(crashContext.srr0);
|
||||
if (breakpoint != NULL) {
|
||||
writeCode(breakpoint->address, breakpoint->instruction);
|
||||
}
|
||||
|
||||
PredictStepAddresses((u32) message.message == CLIENT_MESSAGE_STEP_OVER);
|
||||
breakpoints[STEP1].instruction = *(u32 * )(breakpoints[STEP1].address);
|
||||
writeCode(breakpoints[STEP1].address, TRAP);
|
||||
if (breakpoints[STEP2].address) {
|
||||
breakpoints[STEP2].instruction = *(u32 * )(breakpoints[STEP2].address);
|
||||
writeCode(breakpoints[STEP2].address, TRAP);
|
||||
}
|
||||
|
||||
stepSource = crashContext.srr0;
|
||||
|
||||
if ((u32) message.message == CLIENT_MESSAGE_CONTINUE) stepState = STEP_STATE_CONTINUE;
|
||||
else stepState = STEP_STATE_STEPPING;
|
||||
} else if (stepState == STEP_STATE_CONTINUE) {
|
||||
RestoreStepInstructions();
|
||||
stepState = STEP_STATE_RUNNING;
|
||||
crashState = CRASH_STATE_NONE;
|
||||
}
|
||||
|
||||
// Resume execution
|
||||
OSLoadContext(&crashContext);
|
||||
}*/
|
||||
|
||||
#endif
|
30
src/system/stack.h
Normal file
30
src/system/stack.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef TCPGECKO_STACK_H
|
||||
#define TCPGECKO_STACK_H
|
||||
|
||||
#include "../utils/linked_list.h"
|
||||
#include "../common/cafe.h"
|
||||
|
||||
bool isValidStackPointer(u32 stackPointer) {
|
||||
return stackPointer >= 0x10000000 && stackPointer < 0x20000000;
|
||||
}
|
||||
|
||||
struct node *getStackTrace(OSContext *context) {
|
||||
struct node *stackTrace = NULL;
|
||||
u32 stackPointer = context->gpr[1];
|
||||
u32 stackPointersCount = 0;
|
||||
|
||||
while (isValidStackPointer(stackPointer)) {
|
||||
stackPointer = *(u32 *) stackPointer;
|
||||
if (!isValidStackPointer(stackPointer)) {
|
||||
break;
|
||||
}
|
||||
|
||||
int data = *(u32 * )(stackPointer + 4);
|
||||
stackTrace = insert(stackTrace, (void *) data);
|
||||
stackPointersCount++;
|
||||
}
|
||||
|
||||
return stackTrace;
|
||||
}
|
||||
|
||||
#endif
|
24
src/system/utilities.h
Normal file
24
src/system/utilities.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef TCPGECKO_UTILITIES_H
|
||||
#define TCPGECKO_UTILITIES_H
|
||||
|
||||
#include "../dynamic_libs/os_functions.h"
|
||||
#include "../utils/logger.h"
|
||||
#include "../kernel.h"
|
||||
#include "../common/kernel_types.h"
|
||||
|
||||
void writeCode(u32 address, u32 instruction) {
|
||||
u32 *pointer = (u32 *) (address + 0xA0000000);
|
||||
*pointer = instruction;
|
||||
DCFlushRange(pointer, 4);
|
||||
ICInvalidateRange(pointer, 4);
|
||||
}
|
||||
|
||||
void patchFunction(void *function, char *patchBytes, unsigned int patchBytesSize, int functionOffset) {
|
||||
log_print("Patching function...\n");
|
||||
void *patchAddress = function + functionOffset;
|
||||
log_printf("Patch address: %p\n", patchAddress);
|
||||
kernelCopy((unsigned char *) patchAddress, (unsigned char *) patchBytes, patchBytesSize);
|
||||
log_print("Successfully patched!\n");
|
||||
}
|
||||
|
||||
#endif
|
BIN
tcpgecko.elf
BIN
tcpgecko.elf
Binary file not shown.
Loading…
Reference in New Issue
Block a user