diff --git a/src/system/exception_handler.cpp b/src/system/exception_handler.cpp index dee3ecb..701f2b0 100644 --- a/src/system/exception_handler.cpp +++ b/src/system/exception_handler.cpp @@ -125,11 +125,11 @@ static unsigned char exceptionCallback(void *c, unsigned char exception_type) { return 1; } -static unsigned char dsi_exception_cb(void *context) { +unsigned char dsi_exception_cb(void *context) { return exceptionCallback(context, 0); } -static unsigned char isi_exception_cb(void *context) { +unsigned char isi_exception_cb(void *context) { return exceptionCallback(context, 1); } diff --git a/src/system/exception_handler.h b/src/system/exception_handler.h index 707960d..fbd3ea6 100644 --- a/src/system/exception_handler.h +++ b/src/system/exception_handler.h @@ -78,6 +78,10 @@ typedef struct _framerec { void setup_os_exceptions(void); +unsigned char dsi_exception_cb(void *context); +unsigned char isi_exception_cb(void *context); +unsigned char program_exception_cb(void *context); + #ifdef __cplusplus } #endif diff --git a/src/tcpgecko/hardware_breakpoints.S b/src/tcpgecko/hardware_breakpoints.S new file mode 100644 index 0000000..c203bfe --- /dev/null +++ b/src/tcpgecko/hardware_breakpoints.S @@ -0,0 +1,17 @@ +#include "../utils/ppc_asm.h" + +.set dabr, 0x3F5 + +# .section text + +.global KernelSetDABR +KernelSetDABR: + mtspr dabr, r3 + blr + +.global SC0x2D_KernelSetDABR +SC0x2D_KernelSetDABR: + li r0, 0x2D00 + sc + nop + blr diff --git a/src/tcpgecko/hardware_breakpoints.hpp b/src/tcpgecko/hardware_breakpoints.h similarity index 59% rename from src/tcpgecko/hardware_breakpoints.hpp rename to src/tcpgecko/hardware_breakpoints.h index 2b4e2c2..6e5f78f 100644 --- a/src/tcpgecko/hardware_breakpoints.hpp +++ b/src/tcpgecko/hardware_breakpoints.h @@ -1,13 +1,105 @@ -#include "stringify.h" +#include #include "../dynamic_libs/os_functions.h" -#include "threads.h" +#include "../system/exception_handler.h" +#include "../kernel/syscalls.h" +#include "../common/common.h" #include "../utils/logger.h" -#include "main.h" -#include "utilities.h" #include "software_breakpoints.h" -#ifndef TCPGECKO_BREAKPOINTS_H -#define TCPGECKO_BREAKPOINTS_H +#ifndef TCPGECKO_HARDWARE_BREAKPOINTS_H +#define TCPGECKO_HARDWARE_BREAKPOINTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Fix a gap in exception_handler.h + Yes, this is the dsisr. +*/ +#define dsisr exception_specific0 +#define DSISR_DABR_MATCH 0x400000 + +extern /* kernelmode */ void KernelSetDABR(unsigned int dabr); + +extern void SC0x2D_KernelSetDABR(unsigned int dabr); + +static void RegisterDataBreakpointHandler(unsigned char (*breakpointHandler)(OSContext *ctx)); + +static void DataBreakpoints_Install(); + +static unsigned char DataBreakpoints_DSIHandler(void *ctx); + +static unsigned char (*bHandler)(OSContext *ctx); + +static void RegisterDataBreakpointHandler(unsigned char (*breakpointHandler)(OSContext *ctx)) { + bHandler = breakpointHandler; +} + +static inline int getDABRAddress(void *interruptedContext) { + OSContext *context = (OSContext *) interruptedContext; + return (int) context->srr0; // Offset 0xA4 +} + +unsigned char basicDABRBreakpointHandler(OSContext *context) { + log_print("Getting DABR address\n"); + int address = getDABRAddress(context); + log_printf("Got DABR address: %08x\n", address); + + if (OSIsAddressValid((const void *) address)) { + log_printf("Data breakpoint address: %x08\n", address); + } else { + log_printf("Data breakpoint invalid address: %x08\n", address); + } + + return 0; +} + +static void SetDataBreakpoint(unsigned int address, bool read, bool write) { + log_print("Before installing...\n"); + DataBreakpoints_Install(); + log_print("After installing...\n"); + RegisterDataBreakpointHandler(basicDABRBreakpointHandler); + log_print("After registering...\n"); + + unsigned int dabr = address & ~0b00000111; //GCC \o/ + log_printf("DABR 1: %08x\n", dabr); + dabr |= 0b00000100; //enable translation + log_printf("DABR 2: %08x\n", dabr); + if (read) { + dabr |= 0b00000001; //break on read + log_printf("DABR 3: %08x\n", dabr); + } + if (write) { + dabr |= 0b00000010; //break on write + log_printf("DABR 4: %08x\n", dabr); + } + + log_print("Setting DABR...\n"); + SC0x2D_KernelSetDABR(dabr); + log_print("DABR set!\n"); +} + +static unsigned char DataBreakpoints_DSIHandler(void *ctx) { + log_print("DSI handler\n"); + OSContext *context = (OSContext *) ctx; + if (context->dsisr & DSISR_DABR_MATCH) { + log_print("Running BP handler\n"); + return bHandler(context); + } + + log_print("DSI exception\n"); + return dsi_exception_cb(ctx); +} + +static void DataBreakpoints_Install() { + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl1 + (0x2D * 4)), (unsigned int) &KernelSetDABR); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl2 + (0x2D * 4)), (unsigned int) &KernelSetDABR); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl3 + (0x2D * 4)), (unsigned int) &KernelSetDABR); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl4 + (0x2D * 4)), (unsigned int) &KernelSetDABR); + kern_write((void *) (OS_SPECIFICS->addr_KernSyscallTbl5 + (0x2D * 4)), (unsigned int) &KernelSetDABR); + + OSSetExceptionCallback((u8) OS_EXCEPTION_DSI, &DataBreakpoints_DSIHandler); +} // Special purpose registers #define IABR 0x3F2 @@ -44,11 +136,6 @@ static inline int getIABRAddress() { return mfspr(IABR); } -static inline int getDABRAddress(void *interruptedContext) { - OSContext *context = (OSContext *) interruptedContext; - return (int) context->srr0; // Offset 0xA4 -} - static inline int getIABRMatch(void *interruptedContext) { OSContext *context = (OSContext *) interruptedContext; return (int) context->exception_specific1; // Offset 0x98 @@ -145,4 +232,8 @@ unsigned char breakPointHandler(void *interruptedContext) { return 0; } -#endif \ No newline at end of file +#ifdef __cplusplus +} //extern "C" +#endif + +#endif //TCPGECKO_HARDWARE_BREAKPOINTS_H diff --git a/src/tcpgecko/tcp_gecko.cpp b/src/tcpgecko/tcp_gecko.cpp index 96eed7e..9deaa88 100644 --- a/src/tcpgecko/tcp_gecko.cpp +++ b/src/tcpgecko/tcp_gecko.cpp @@ -14,7 +14,7 @@ #include "../dynamic_libs/gx2_functions.h" #include "../dynamic_libs/fs_functions.h" #include "../utils/logger.h" -#include "hardware_breakpoints.hpp" +#include "hardware_breakpoints.h" #include "linked_list.h" #include "address.h" #include "stack.h" @@ -23,6 +23,8 @@ #include "../patcher/function_patcher_gx2.h" #include "raw_assembly_cheats.h" #include "sd_cheats.h" +#include "threads.h" +#include "software_breakpoints.h" void *client; void *commandBlock; @@ -199,6 +201,12 @@ unsigned int receiveString(struct pygecko_bss_t *bss, OSScreenFlipBuffersEx(1); }*/ + +/* TODO + https://github.com/dimok789/ddd/blob/ca33ad1c759a0b67db33eedcf7fc4537198aad9c/src/discdumper.c#L667-L693 + int ret = FSBindMount(pClient, pCmd, metaDir, "/vol/meta", -1); + FSBindUnmount(pClient, pCmd, metaDir, -1); + */ void considerInitializingFileSystem() { if (!client) { // Initialize the file system @@ -1324,7 +1332,8 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { bufferIndex += sizeof(bool); bool write = buffer[bufferIndex]; bufferIndex += sizeof(bool); - setDataBreakpoint(address, read, write); + SetDataBreakpoint(address, read, write); + // setDataBreakpoint(address, read, write); break; } @@ -1570,4 +1579,4 @@ void startTCPGecko() { OSResumeThread(thread); log_print("TCP Gecko started...\n"); -} \ No newline at end of file +} diff --git a/src/utils/ppc_asm.h b/src/utils/ppc_asm.h new file mode 100644 index 0000000..da07031 --- /dev/null +++ b/src/utils/ppc_asm.h @@ -0,0 +1,62 @@ +#ifndef PPC_ASM_H +#define PPC_ASM_H +/* + * + * Definitions used by various bits of low-level assembly code on PowerPC. + * + * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* Condition Register Bit Fields */ + +#define cr0 0 +#define cr1 1 +#define cr2 2 +#define cr3 3 +#define cr4 4 +#define cr5 5 +#define cr6 6 +#define cr7 7 + + +/* General Purpose Registers (GPRs) */ + +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 + +#endif /* PPC_ASM_H */ diff --git a/tcpgecko.elf b/tcpgecko.elf index 906dc41..86a3dda 100644 Binary files a/tcpgecko.elf and b/tcpgecko.elf differ