From c2fd5d1bb254e0248771097e1dd43530f7151666 Mon Sep 17 00:00:00 2001 From: BullyWiiPlaza Date: Wed, 17 May 2017 15:45:45 +0200 Subject: [PATCH] Implement untested breakpoints --- src/breakpoints/bit.h | 13 +++++ src/breakpoints/breakpoints.h | 87 ++++++++++++++++++++++++++++++++++ src/breakpoints/stringify.h | 8 ++++ src/entry.c | 1 - src/main.c | 2 - src/pygecko.c | 65 ++++++++++++++++++++++--- tcpgecko.elf | Bin 140748 -> 141612 bytes 7 files changed, 166 insertions(+), 10 deletions(-) create mode 100644 src/breakpoints/bit.h create mode 100644 src/breakpoints/breakpoints.h create mode 100644 src/breakpoints/stringify.h diff --git a/src/breakpoints/bit.h b/src/breakpoints/bit.h new file mode 100644 index 0000000..b1facd6 --- /dev/null +++ b/src/breakpoints/bit.h @@ -0,0 +1,13 @@ +#ifndef TCPGECKO_BIT_UTILITIES_H +#define TCPGECKO_BIT_UTILITIES_H + +// http://stackoverflow.com/a/47990/3764804 +inline unsigned int setBit(unsigned int value, bool bit, int bitIndex) { + return value | (bit << bitIndex); +} + +inline bool getBit(unsigned int value, int bitIndex) { + return ((value >> bitIndex) & 1) == 1; +} + +#endif \ No newline at end of file diff --git a/src/breakpoints/breakpoints.h b/src/breakpoints/breakpoints.h new file mode 100644 index 0000000..73f2e2b --- /dev/null +++ b/src/breakpoints/breakpoints.h @@ -0,0 +1,87 @@ +#include "bit.h" +#include "stringify.h" + +#ifndef TCPGECKO_BREAKPOINTS_H +#define TCPGECKO_BREAKPOINTS_H + +/* Breakpoint types +#define BREAKPOINT_READ 0x01 +#define BREAKPOINT_WRITE 0x02 */ + +struct DataBreakpoint { + unsigned int value; + bool translate; + bool write; + bool read; +} __attribute__((packed)); + +// Special purpose registers +#define INSTRUCTION_ADDRESS_BREAKPOINT_REGISTER 0x3F2 +#define DATA_ADDRESS_BREAKPOINT_REGISTER 0x3F5 + +// Data address breakpoint bit indices +#define TRANSLATE_BIT_INDEX 29 +#define WRITE_BIT_INDEX 30 +#define READ_BIT_INDEX 31 + +// http://www.ds.ewi.tudelft.nl/vakken/in1006/instruction-set/mtspr.html +#define moveToSpecialPurposeRegister(specialPurposeRegister, value) \ + __asm__ __volatile__ ("mtspr %0, %1" : : "K" (specialPurposeRegister), "r" (value)) \ + +// http://elixir.free-electrons.com/linux/v2.6.24/source/include/asm-powerpc/reg.h#L713 +#define moveFromSpecialPurposeRegister(specialPurposeRegister) \ +({unsigned int value; \ +asm volatile("mfspr %0, " __stringify(specialPurposeRegister) : "=r" (value)); \ +value;}) \ + + +// https://www.ibm.com/support/knowledgecenter/en/ssw_aix_71/com.ibm.aix.alangref/idalangref_isync_ics_instrs.htm +static inline void synchronizeInstructions() { + __asm__ __volatile__ ("isync" : : : "memory"); +} + +// https://www.ibm.com/support/knowledgecenter/en/ssw_aix_61/com.ibm.aix.alangref/idalangref_eieio_instrs.htm +static inline void enforeInOrderExecutionOfIO() { + __asm__ __volatile__ ("eieio" : : : "memory"); +} + +static inline void setDataAddressBreakpointRegister(struct DataBreakpoint dataBreakpoint) { + unsigned int value = dataBreakpoint.value; + + // Breakpoint translation + value = setBit(value, dataBreakpoint.translate, TRANSLATE_BIT_INDEX); + + // Write breakpoint + value = setBit(value, dataBreakpoint.write, WRITE_BIT_INDEX); + + // Read breakpoint + value = setBit(value, dataBreakpoint.read, READ_BIT_INDEX); + + moveToSpecialPurposeRegister(DATA_ADDRESS_BREAKPOINT_REGISTER, value); + synchronizeInstructions(); +} + +static inline struct DataBreakpoint getDataAddressBreakpointRegisterContents(struct DataBreakpoint dataBreakpoint) { + unsigned int value = moveFromSpecialPurposeRegister(DATA_ADDRESS_BREAKPOINT_REGISTER); + dataBreakpoint.translate = getBit(value, TRANSLATE_BIT_INDEX); + dataBreakpoint.write = getBit(value, WRITE_BIT_INDEX); + dataBreakpoint.read = getBit(value, READ_BIT_INDEX); + value = setBit(value, 0, TRANSLATE_BIT_INDEX); + value = setBit(value, 0, WRITE_BIT_INDEX); + value = setBit(value, 0, READ_BIT_INDEX); + dataBreakpoint.value = value; + + return dataBreakpoint; +} + +// https://www.manualslib.com/manual/606065/Ibm-Powerpc-750gx.html?page=64 +static inline void setInstructionAddressBreakpointRegister(unsigned int address) { + moveToSpecialPurposeRegister(INSTRUCTION_ADDRESS_BREAKPOINT_REGISTER, address); + synchronizeInstructions(); +} + +static inline int getInstructionAddressBreakpointRegister() { + return moveFromSpecialPurposeRegister(INSTRUCTION_ADDRESS_BREAKPOINT_REGISTER); +} + +#endif \ No newline at end of file diff --git a/src/breakpoints/stringify.h b/src/breakpoints/stringify.h new file mode 100644 index 0000000..b4dd0a7 --- /dev/null +++ b/src/breakpoints/stringify.h @@ -0,0 +1,8 @@ +#ifndef TCPGECKO_STRING_H +#define TCPGECKO_STRING_H + +// http://elixir.free-electrons.com/linux/v2.6.24/source/include/linux/stringify.h#L9 +#define __stringify_1(x) #x +#define __stringify(x) __stringify_1(x) + +#endif \ No newline at end of file diff --git a/src/entry.c b/src/entry.c index e960fb1..28f12c8 100644 --- a/src/entry.c +++ b/src/entry.c @@ -1,4 +1,3 @@ -#include #include "dynamic_libs/os_functions.h" #include "dynamic_libs/gx2_functions.h" #include "dynamic_libs/socket_functions.h" diff --git a/src/main.c b/src/main.c index 90231c1..158ed0d 100644 --- a/src/main.c +++ b/src/main.c @@ -19,8 +19,6 @@ bool isCodeHandlerInstalled; -// TODO Make sure accessing the browser does not freeze the console - #define PRINT_TEXT2(x, y, ...) { snprintf(messageBuffer, 80, __VA_ARGS__); OSScreenPutFontEx(0, x, y, messageBuffer); OSScreenPutFontEx(1, x, y, messageBuffer); } typedef enum { diff --git a/src/pygecko.c b/src/pygecko.c index b5531ae..eddfefe 100644 --- a/src/pygecko.c +++ b/src/pygecko.c @@ -15,6 +15,7 @@ #include "system/exception_handler.h" #include "utils/logger.h" #include "system/memory.h" +#include "breakpoints/breakpoints.h" void *client; void *commandBlock; @@ -58,7 +59,11 @@ struct pygecko_bss_t { #define COMMAND_RESUME_CONSOLE 0x83 #define COMMAND_IS_CONSOLE_PAUSED 0x84 #define COMMAND_SERVER_VERSION 0x99 -#define COMMAND_OS_VERSION 0x9A +#define COMMAND_GET_OS_VERSION 0x9A +#define COMMAND_SET_DATA_BREAKPOINT 0xA0 +#define COMMAND_GET_DATA_BREAKPOINT 0xA1 +#define COMMAND_SET_INSTRUCTION_BREAKPOINT 0xA2 +#define COMMAND_GET_INSTRUCTION_BREAKPOINT 0xA3 #define COMMAND_RUN_KERNEL_COPY_SERVICE 0xCD #define COMMAND_IOSUHAX_READ_FILE 0xD0 #define COMMAND_GET_VERSION_HASH 0xE0 @@ -1420,18 +1425,63 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { strcpy(versionBuffer, SERVER_VERSION); int versionLength = strlen(versionBuffer); ((int *) buffer)[0] = versionLength; - memcpy(buffer + 4, versionBuffer, versionLength); + memcpy(buffer + sizeof(int), versionBuffer, versionLength); // Send the length and the version string - ret = sendwait(bss, clientfd, buffer, 4 + versionLength); + ret = sendwait(bss, clientfd, buffer, sizeof(int) + versionLength); ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (server version)"); break; } - case COMMAND_OS_VERSION: { + case COMMAND_GET_OS_VERSION: { ((int *) buffer)[0] = (int) OS_FIRMWARE; - ret = sendwait(bss, clientfd, buffer, 4); - CHECK_ERROR(ret < 0) + ret = sendwait(bss, clientfd, buffer, sizeof(int)); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (OS version)"); + + break; + } + case COMMAND_SET_DATA_BREAKPOINT: { + ret = recvwait(bss, clientfd, buffer, 4 + 3 * 1); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (data breakpoint)"); + int bufferIndex = 0; + unsigned int address = ((unsigned int *) buffer)[bufferIndex]; + bufferIndex += 4; + bool translate = buffer[bufferIndex++]; + bool write = buffer[bufferIndex++]; + bool read = buffer[bufferIndex]; + struct DataBreakpoint dataBreakpoint; + dataBreakpoint.value = address; + dataBreakpoint.translate = translate; + dataBreakpoint.write = write; + dataBreakpoint.read = read; + setDataAddressBreakpointRegister(dataBreakpoint); + + break; + } + case COMMAND_GET_DATA_BREAKPOINT: { + struct DataBreakpoint dataBreakpoint; + getDataAddressBreakpointRegisterContents(dataBreakpoint); + int structureSize = sizeof(dataBreakpoint); + memcpy(buffer, (const void *) &dataBreakpoint, structureSize); + ret = sendwait(bss, clientfd, buffer, structureSize); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (data breakpoint)"); + + break; + } + case COMMAND_SET_INSTRUCTION_BREAKPOINT: { + // Read the address and set the breakpoint execute + ret = recvwait(bss, clientfd, buffer, sizeof(int)); + ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (instruction breakpoint)"); + unsigned int address = ((unsigned int *) buffer)[0]; + setInstructionAddressBreakpointRegister(address); + + break; + } + case COMMAND_GET_INSTRUCTION_BREAKPOINT: { + int address = getInstructionAddressBreakpointRegister(); + ((int *) buffer)[0] = address; + ret = sendwait(bss, clientfd, buffer, sizeof(int)); + ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (instruction breakpoint)"); break; } @@ -1443,10 +1493,11 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) { break; } - default: + default: { reportIllegalCommandByte(ret); break; + } } } diff --git a/tcpgecko.elf b/tcpgecko.elf index e4b7bad1a7765534a28c3bce568afcd7c0fbedf1..89308fe716649aadc95e2b8446b1492641336f4f 100644 GIT binary patch delta 25668 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
    Q=}1KuNWO>@5P`@RGpO!(oG(C%a3)T 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 Bw