Add the old memory search back to support the VC injection tool again

This commit is contained in:
BullyWiiPlaza 2017-05-30 11:03:23 +02:00
parent 0e018f8392
commit 60df33bb23
18 changed files with 537 additions and 131 deletions

106
src/common/cafe.h Normal file
View 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

View File

@ -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
View 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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);
@ -1018,16 +1019,16 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
break;
}
/*case COMMAND_WRITE_SCREEN: {
char message[WRITE_SCREEN_MESSAGE_BUFFER_SIZE];
ret = recvwait(bss, clientfd, buffer, 4);
ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (write screen seconds)")
int seconds = ((int *) buffer)[0];
receiveString(bss, clientfd, message, WRITE_SCREEN_MESSAGE_BUFFER_SIZE);
writeScreen(message, seconds);
/*case COMMAND_WRITE_SCREEN: {
char message[WRITE_SCREEN_MESSAGE_BUFFER_SIZE];
ret = recvwait(bss, clientfd, buffer, 4);
ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (write screen seconds)")
int seconds = ((int *) buffer)[0];
receiveString(bss, clientfd, message, WRITE_SCREEN_MESSAGE_BUFFER_SIZE);
writeScreen(message, seconds);
break;
}*/
break;
}*/
case COMMAND_FOLLOW_POINTER: {
ret = recvwait(bss, clientfd, buffer, 8);
ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (Pointer address and offsets count)")
@ -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);

View File

@ -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);
}

View File

@ -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

View 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
View 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
View 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

Binary file not shown.