Release development version

This commit is contained in:
BullyWiiPlaza 2017-05-24 18:48:20 +02:00
parent bd01f31bfc
commit 0e018f8392
14 changed files with 275 additions and 591 deletions

View File

@ -1,13 +0,0 @@
#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

View File

@ -1,87 +0,0 @@
#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

View File

@ -1,8 +0,0 @@
#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

View File

@ -52,6 +52,20 @@ EXPORT_DECL(int, OSCreateThread, void *thread, s32(*callback)(s32, void * ), s32
priority, u32
attr);
EXPORT_DECL(void, OSEnableInterrupts, void);
EXPORT_DECL(void, __OSClearAndEnableInterrupt, void);
EXPORT_DECL(int, OSIsInterruptEnabled, void);
EXPORT_DECL(int, OSIsDebuggerPresent, void);
EXPORT_DECL(void, OSRestoreInterrupts, void);
EXPORT_DECL(void, OSSetDABR, int, int, int, int);
EXPORT_DECL(void, OSSetIABR, int, int);
EXPORT_DECL(int, OSGetCurrentThread, void);
EXPORT_DECL(int, OSResumeThread, void *thread);
@ -103,8 +117,9 @@ EXPORT_DECL(void, __Exit, void);
EXPORT_DECL(void, OSFatal, const char *msg);
EXPORT_DECL(void, OSSetExceptionCallback, u8
exceptionType, exception_callback newCallback);
EXPORT_DECL(void, OSSetExceptionCallback, u8 exceptionType, exception_callback callback);
EXPORT_DECL(void, __OSSetInterruptHandler, u8 exceptionType, exception_callback callback);
EXPORT_DECL(void, DCFlushRange, const void *addr, u32
length);
@ -250,6 +265,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, __OSSetInterruptHandler);
OS_FIND_EXPORT(coreinit_handle, DCFlushRange);
OS_FIND_EXPORT(coreinit_handle, ICInvalidateRange);
OS_FIND_EXPORT(coreinit_handle, OSEffectiveToPhysical);
@ -279,6 +295,13 @@ void InitOSFunctionPointers(void) {
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! Thread functions
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OS_FIND_EXPORT(coreinit_handle, OSEnableInterrupts);
OS_FIND_EXPORT(coreinit_handle, __OSClearAndEnableInterrupt);
OS_FIND_EXPORT(coreinit_handle, OSIsInterruptEnabled);
OS_FIND_EXPORT(coreinit_handle, OSIsDebuggerPresent);
OS_FIND_EXPORT(coreinit_handle, OSRestoreInterrupts);
OS_FIND_EXPORT(coreinit_handle, OSSetDABR);
OS_FIND_EXPORT(coreinit_handle, OSSetIABR);
OS_FIND_EXPORT(coreinit_handle, OSGetCurrentThread);
OS_FIND_EXPORT(coreinit_handle, OSCreateThread);
OS_FIND_EXPORT(coreinit_handle, OSResumeThread);

View File

@ -140,6 +140,20 @@ extern int
(*OSCreateThread)(void *thread, s32 (*callback)(s32, void *), s32 argc, void *args, u32 stack, u32 stack_size,
s32 priority, u32 attr);
extern void (*OSEnableInterrupts)(void);
extern void (*__OSClearAndEnableInterrupt)(void);
extern int (*OSIsInterruptEnabled)(void);
extern int (*OSIsDebuggerPresent)(void);
extern void (*OSRestoreInterrupts)(void);
extern void (*OSSetDABR)(int, int, int, int);
extern void (*OSSetIABR)(int, int);
extern int (*OSGetCurrentThread)(void);
extern int (*OSResumeThread)(void *thread);
@ -216,7 +230,9 @@ extern int (*OSScreenEnableEx)(unsigned int bufferNum, int enable);
typedef unsigned char (*exception_callback)(void *interruptedContext);
extern void (*OSSetExceptionCallback)(u8 exceptionType, exception_callback newCallback);
extern void (*OSSetExceptionCallback)(u8 exceptionType, exception_callback callback);
extern void (*__OSSetInterruptHandler)(u8 interruptType, exception_callback callback);
extern int (*OSAllocFromSystem)(unsigned int size, unsigned int align);

View File

@ -5,25 +5,10 @@
#include "pygecko.h"
#include "main.h"
#include "utils/logger.h"
#define TITLE_ID_MII_VERSE 0x000500301001600A
#define TITLE_ID_MII_MAKER 0x000500101004A000
#define TITLE_ID_BAYONETTA_2 0x0005000010172500
#define TITLE_ID_INTERNET_BROWSER 0x000500301001200A
bool isRunningTitleID(unsigned long long int japaneseTitleID) {
unsigned long long int currentTitleID = (unsigned long long int) OSGetTitleID();
return currentTitleID == japaneseTitleID // JAP
|| currentTitleID == japaneseTitleID + 0x100 // USA
|| currentTitleID == japaneseTitleID + 0x200; // EUR
}
#include "title.h"
int __entry_menu(int argc, char **argv) {
if (OSGetTitleID != 0
&& !isRunningTitleID(TITLE_ID_MII_VERSE)
&& !isRunningTitleID(TITLE_ID_MII_MAKER)
&& !isRunningTitleID(TITLE_ID_BAYONETTA_2)
&& !isRunningTitleID(TITLE_ID_INTERNET_BROWSER)) {
if (isRunningAllowedTitleID()) {
InitOSFunctionPointers();
InitSocketFunctionPointers();
InitGX2FunctionPointers();

View File

@ -1,6 +0,0 @@
#ifndef TCPGECKO_ENTRY_H
#define TCPGECKO_ENTRY_H
bool isRunningTitleID(unsigned long long int japaneseTitleID);
#endif

View File

@ -7,19 +7,24 @@ extern "C" {
#include <gctypes.h>
#include "common/kernel_defs.h"
#include "../common/kernel_defs.h"
void KernelSetupSyscalls(void);
void KernelRestoreInstructions(void);
void SC0x25_KernelCopyData(unsigned int addr, unsigned int src, unsigned int len);
void SC0x36_KernelReadDBATs(bat_table_t * table);
void SC0x37_KernelWriteDBATs(bat_table_t * table);
void SC0x36_KernelReadDBATs(bat_table_t *table);
void SC0x37_KernelWriteDBATs(bat_table_t *table);
uint32_t __attribute__ ((noinline)) kern_read(const void *addr);
void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value);
#ifdef __cplusplus
}
#endif
#endif // __KERNEL_FUNCTIONS_H_
#endif

View File

@ -15,7 +15,13 @@
#include "system/exception_handler.h"
#include "utils/logger.h"
#include "system/memory.h"
#include "breakpoints/breakpoints.h"
#include "system/breakpoints.h"
#include "system/threads.h"
#include "utils/linked_list.h"
#include "assertions.h"
#include "kernel.h"
#include "address.h"
#include "disassembler.h"
void *client;
void *commandBlock;
@ -48,12 +54,11 @@ struct pygecko_bss_t {
#define COMMAND_GET_CODE_HANDLER_ADDRESS 0x55
#define COMMAND_READ_THREADS 0x56
#define COMMAND_ACCOUNT_IDENTIFIER 0x57
#define COMMAND_WRITE_SCREEN 0x58 // TODO Exception DSI
// #define COMMAND_WRITE_SCREEN 0x58 // TODO Exception DSI
#define COMMAND_FOLLOW_POINTER 0x60
#define COMMAND_REMOTE_PROCEDURE_CALL 0x70
#define COMMAND_GET_SYMBOL 0x71
#define COMMAND_MEMORY_SEARCH 0x73
// #define COMMAND_SYSTEM_CALL 0x80
#define COMMAND_EXECUTE_ASSEMBLY 0x81
#define COMMAND_PAUSE_CONSOLE 0x82
#define COMMAND_RESUME_CONSOLE 0x83
@ -61,74 +66,23 @@ struct pygecko_bss_t {
#define COMMAND_SERVER_VERSION 0x99
#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_IOSU_HAX_READ_FILE 0xD0
#define COMMAND_GET_VERSION_HASH 0xE0
#define CHECK_ERROR(cond) if (cond) { bss->line = __LINE__; goto error; }
#define errno (*__gh_errno_ptr())
#define MSG_DONTWAIT 32
#define MSG_DONT_WAIT 32
#define EWOULDBLOCK 6
#define DATA_BUFFER_SIZE 0x5000
#define WRITE_SCREEN_MESSAGE_BUFFER_SIZE 100
// #define WRITE_SCREEN_MESSAGE_BUFFER_SIZE 100
#define SERVER_VERSION "05/24/2017"
#define ONLY_ZEROS_READ 0xB0
#define NON_ZEROS_READ 0xBD
#define VERSION_HASH 0x39C9444B
#define ASSERT_MINIMUM_HOLDS(actual, minimum, variableName) \
if(actual < minimum) { \
char buffer[100] = {0}; \
__os_snprintf(buffer, 100, "%s: Limit exceeded (minimum: %i, actual: %i)", variableName, minimum, actual); \
OSFatal(buffer); \
} \
#define ASSERT_MAXIMUM_HOLDS(maximum, actual, variableName) \
if(actual > maximum) { \
char buffer[100] = {0}; \
__os_snprintf(buffer, 100, "%s: Limit exceeded (maximum: %i, actual: %i)", variableName, maximum, actual); \
OSFatal(buffer); \
} \
#define ASSERT_FUNCTION_SUCCEEDED(returnValue, functionName) \
if (returnValue < 0) { \
char buffer[100] = {0}; \
__os_snprintf(buffer, 100, "%s failed with return value: %i", functionName, returnValue); \
OSFatal(buffer); \
} \
#define ASSERT_VALID_EFFECTIVE_ADDRESS(effectiveAddress, message) \
if(!OSIsAddressValid((void *) effectiveAddress)) { \
char buffer[100] = {0}; \
__os_snprintf(buffer, 100, "Address %04x invalid: %s", effectiveAddress, message); \
OSFatal(buffer); \
} \
#define ASSERT_INTEGER(actual, expected, name) \
if(actual != expected) { \
char buffer[50] = {0}; \
__os_snprintf(buffer, 50, "%s assertion failed: %i == %i", name, actual, expected); \
OSFatal(buffer); \
} \
#define ASSERT_STRING(actual, expected) \
if(strcmp(actual, expected) != 0) { \
char buffer[50] = {0}; \
__os_snprintf(buffer, 50, "String assertion failed: \"%s\" == \"%s\"", actual, expected); \
OSFatal(buffer); \
} \
#define ASSERT_ALLOCATED(variable, name) \
if(variable == 0) { \
char buffer[50] = {0}; \
__os_snprintf(buffer, 50, "%s allocation failed", name); \
OSFatal(buffer); \
} \
ZEXTERN int ZEXPORT
deflateEnd OF((z_streamp
strm));
@ -143,75 +97,20 @@ strm,
int flush
));
/*struct breakpoint {
u32 address;
u32 instruction;
};
// 10 general breakpoints + 2 step breakpoints
breakpoint breakpoints[12];
breakpoint *getBreakpoint(u32 address, int size) {
breakpoint *breakpointsList = breakpoints;
for (int breakpointIndex = 0; breakpointIndex < size; breakpointIndex++) {
if (breakpointsList[breakpointIndex].address == address) {
return &breakpointsList[breakpointIndex];
}
}
return 0;
}*/
// ########## Being kernel_copy.h ############
// TODO Variable size, not hard-coded
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);
}
unsigned char *kernelCopyBuffer[4];
// ########## End kernel_copy.h ############
void kernelCopy(unsigned char *destinationBuffer, unsigned char *sourceBuffer, unsigned int length) {
memcpy(kernelCopyBuffer, sourceBuffer, length);
unsigned int destinationAddress = (unsigned int) OSEffectiveToPhysical(destinationBuffer);
SC0x25_KernelCopyData(destinationAddress, (unsigned int) &kernelCopyBuffer, length);
DCFlushRange(destinationBuffer, (u32) length);
}
#define KERNEL_COPY_SOURCE_ADDRESS 0x10100000
int kernelCopyService(int argc, void *argv) {
while (true) {
// Read the destination address from the source address
int destinationAddress = *(int *) KERNEL_COPY_SOURCE_ADDRESS;
// Avoid crashing
if (OSIsAddressValid((const void *) destinationAddress)) {
// Perform memory copy
unsigned char *valueBuffer = (unsigned char *) (KERNEL_COPY_SOURCE_ADDRESS + 4);
kernelCopy((unsigned char *) destinationAddress, valueBuffer, 4);
// "Consume" address and value for synchronization with the code handler for instance
*(int *) KERNEL_COPY_SOURCE_ADDRESS = 0;
*(((int *) KERNEL_COPY_SOURCE_ADDRESS) + 1) = 0;
}
}
}
void startKernelCopyService() {
unsigned int stack = (unsigned int) memalign(0x40, 0x100);
ASSERT_ALLOCATED(stack, "Kernel copy thread stack")
stack += 0x100;
void *thread = memalign(0x40, 0x1000);
ASSERT_ALLOCATED(thread, "Kernel copy thread")
int status = OSCreateThread(thread, kernelCopyService, 1, NULL, (u32) stack + sizeof(stack), sizeof(stack), 31,
OS_THREAD_ATTR_AFFINITY_CORE1 | OS_THREAD_ATTR_PINNED_AFFINITY | OS_THREAD_ATTR_DETACH);
ASSERT_INTEGER(status, 1, "Creating kernel copy thread")
// OSSetThreadName(thread, "Kernel Copier");
OSResumeThread(thread);
}
// ########## Being pause.h ############
int (*AVMGetDRCScanMode)(int);
@ -255,10 +154,9 @@ bool isConsolePaused() {
return value == PAUSED;
}
/*Validates the address range (last address inclusive) but is SLOW on bigger ranges */
static int validateAddressRange(int starting_address, int ending_address) {
return __OSValidateAddressSpaceRange(1, (void *) starting_address, ending_address - starting_address + 1);
}
// ########## End pause.h ############
// ########## Being socket_functions.h ############
static int recvwait(struct pygecko_bss_t *bss, int sock, void *buffer, int len) {
int ret;
@ -288,7 +186,7 @@ static int checkbyte(int sock) {
unsigned char buffer[1];
int ret;
ret = recv(sock, buffer, 1, MSG_DONTWAIT);
ret = recv(sock, buffer, 1, MSG_DONT_WAIT);
if (ret < 0) return ret;
if (ret == 0) return -1;
return buffer[0];
@ -315,32 +213,6 @@ static int sendByte(struct pygecko_bss_t *bss, int sock, unsigned char byte) {
return sendwait(bss, sock, buffer, 1);
}
/*void performSystemCall(int value) {
// TODO Exception DSI?
asm(
"li 0, %0\n"
"sc\n"
"blr\n"
: // No output
:"r"(value) // Input
:"0" // Overwritten register
);
}*/
void writeScreen(char message[100], int secondsDelay) {
// TODO Does nothing then crashes (in games)?
OSScreenClearBufferEx(0, 0);
OSScreenClearBufferEx(1, 0);
OSScreenPutFontEx(0, 14, 1, message);
OSScreenPutFontEx(1, 14, 1, message);
sleep(secondsDelay);
OSScreenFlipBuffersEx(0);
OSScreenFlipBuffersEx(1);
}
void receiveString(struct pygecko_bss_t *bss,
int clientfd,
char *stringBuffer,
@ -360,6 +232,22 @@ void receiveString(struct pygecko_bss_t *bss,
}
}
// ########## End socket_functions.h ############
/*void writeScreen(char message[100], int secondsDelay) {
// TODO Does nothing then crashes (in games)?
OSScreenClearBufferEx(0, 0);
OSScreenClearBufferEx(1, 0);
OSScreenPutFontEx(0, 14, 1, message);
OSScreenPutFontEx(1, 14, 1, message);
sleep(secondsDelay);
OSScreenFlipBuffersEx(0);
OSScreenFlipBuffersEx(1);
}*/
void considerInitializingFileSystem() {
if (!client) {
// Initialize the file system
@ -382,45 +270,6 @@ void considerInitializingFileSystem() {
}
}
char *disassemblerBuffer;
void *disassemblerBufferPointer;
#define DISASSEMBLER_BUFFER_SIZE 0x1024
void formatDisassembled(char *format, ...) {
if (!disassemblerBuffer) {
disassemblerBuffer = malloc(DISASSEMBLER_BUFFER_SIZE);
ASSERT_ALLOCATED(disassemblerBuffer, "Disassembler buffer")
disassemblerBufferPointer = disassemblerBuffer;
}
va_list variableArguments;
va_start(variableArguments, format);
char *temporaryBuffer;
int printedBytesCount = vasprintf(&temporaryBuffer, format, variableArguments);
ASSERT_ALLOCATED(temporaryBuffer, "Temporary buffer")
ASSERT_MINIMUM_HOLDS(printedBytesCount, 1, "Printed bytes count")
va_end(variableArguments);
// Do not smash the buffer
long projectedSize = (void *) disassemblerBuffer - disassemblerBufferPointer + printedBytesCount;
if (projectedSize < DISASSEMBLER_BUFFER_SIZE) {
memcpy(disassemblerBuffer, temporaryBuffer, printedBytesCount);
disassemblerBuffer += printedBytesCount;
}
free(temporaryBuffer);
}
bool isValidDataAddress(int address) {
return OSIsAddressValid((const void *) address)
&& address >= 0x10000000
&& address < 0x50000000;
}
int roundUpToAligned(int number) {
return (number + 3) & ~0x03;
}
#define ERROR_BUFFER_SIZE 150
void reportIllegalCommandByte(int commandByte) {
@ -431,37 +280,6 @@ void reportIllegalCommandByte(int commandByte) {
OSFatal(errorBuffer);
}
#define MINIMUM_KERNEL_COMPARE_LENGTH 4
#define KERNEL_MEMORY_COMPARE_STEP_SIZE 1
int kernelMemoryCompare(const void *sourceBuffer,
const void *destinationBuffer,
int length) {
if (length < MINIMUM_KERNEL_COMPARE_LENGTH) {
ASSERT_MINIMUM_HOLDS(length, MINIMUM_KERNEL_COMPARE_LENGTH, "length");
}
bool loopEntered = false;
while (kern_read(sourceBuffer) == kern_read(destinationBuffer)) {
loopEntered = true;
sourceBuffer = (char *) sourceBuffer + KERNEL_MEMORY_COMPARE_STEP_SIZE;
destinationBuffer = (char *) destinationBuffer + KERNEL_MEMORY_COMPARE_STEP_SIZE;
length -= KERNEL_MEMORY_COMPARE_STEP_SIZE;
if (length <= MINIMUM_KERNEL_COMPARE_LENGTH - 1) {
break;
}
}
if (loopEntered) {
sourceBuffer -= KERNEL_MEMORY_COMPARE_STEP_SIZE;
destinationBuffer -= KERNEL_MEMORY_COMPARE_STEP_SIZE;
}
return kern_read(sourceBuffer) - kern_read(destinationBuffer);
}
static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
int ret;
@ -1043,7 +861,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
break;
}
case COMMAND_IOSUHAX_READ_FILE: {
case COMMAND_IOSU_HAX_READ_FILE: {
log_print("COMMAND_IOSUHAX_READ_FILE");
// TODO Crashes console on this call
@ -1139,43 +957,31 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
break;
}
case COMMAND_READ_THREADS: {
int OS_THREAD_SIZE = 0x6A0;
struct node *threads = getAllThreads();
int threadCount = length(threads);
log_printf("Thread Count: %i\n", threadCount);
int currentThreadAddress = OSGetCurrentThread();
ASSERT_VALID_EFFECTIVE_ADDRESS(currentThreadAddress, "OSGetCurrentThread")
int iterationThreadAddress = currentThreadAddress;
int temporaryThreadAddress;
// Send the thread count
log_print("Sending thread count...\n");
((int *) buffer)[0] = threadCount;
ret = sendwait(bss, clientfd, buffer, sizeof(int));
ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (thread count)");
// Follow "previous thread" pointers back to the beginning
while ((temporaryThreadAddress = *(int *) (iterationThreadAddress + 0x390)) != 0) {
iterationThreadAddress = temporaryThreadAddress;
ASSERT_VALID_EFFECTIVE_ADDRESS(iterationThreadAddress, "iterationThreadAddress going backwards")
// Send the thread addresses and data
struct node* currentThread = threads;
while (currentThread != NULL) {
int data = (int) currentThread->data;
log_printf("Thread data: %08x\n", data);
((int *) buffer)[0] = (int) currentThread->data;
memcpy(buffer + sizeof(int), currentThread->data, THREAD_SIZE);
log_print("Sending node...\n");
ret = sendwait(bss, clientfd, buffer, sizeof(int) + THREAD_SIZE);
ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (thread address and data)")
currentThread = currentThread->next;
}
// Send all threads by following the "next thread" pointers
while ((temporaryThreadAddress = *(int *) (iterationThreadAddress + 0x38C)) != 0) {
// Send the starting thread's address
((int *) buffer)[0] = iterationThreadAddress;
// Send the thread struct itself
memcpy(buffer + 4, (void *) iterationThreadAddress, OS_THREAD_SIZE);
ret = sendwait(bss, clientfd, buffer, 4 + OS_THREAD_SIZE);
CHECK_ERROR(ret < 0)
iterationThreadAddress = temporaryThreadAddress;
ASSERT_VALID_EFFECTIVE_ADDRESS(iterationThreadAddress, "iterationThreadAddress going forwards")
}
// The previous while would skip the last thread so send it also
((int *) buffer)[0] = iterationThreadAddress;
memcpy(buffer + 4, (void *) iterationThreadAddress, OS_THREAD_SIZE);
ret = sendwait(bss, clientfd, buffer, 4 + OS_THREAD_SIZE);
CHECK_ERROR(ret < 0)
// Let the client know that no more threads are coming
((int *) buffer)[0] = 0;
ret = sendwait(bss, clientfd, buffer, 4);
CHECK_ERROR(ret < 0)
destroy(threads);
break;
}
@ -1212,7 +1018,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
break;
}
case COMMAND_WRITE_SCREEN: {
/*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)")
@ -1221,7 +1027,7 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
writeScreen(message, seconds);
break;
}
}*/
case COMMAND_FOLLOW_POINTER: {
ret = recvwait(bss, clientfd, buffer, 8);
ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (Pointer address and offsets count)")
@ -1374,16 +1180,6 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
break;
}
/*case COMMAND_SYSTEM_CALL: {
ret = recvwait(bss, clientfd, buffer, 4);
ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (system call)")
int value = ((int *) buffer)[0];
performSystemCall(value);
break;
}*/
case COMMAND_EXECUTE_ASSEMBLY: {
// Receive the assembly
receiveString(bss, clientfd, (char *) buffer, DATA_BUFFER_SIZE);
@ -1441,47 +1237,30 @@ static int processCommands(struct pygecko_bss_t *bss, int clientfd) {
break;
}
case COMMAND_SET_DATA_BREAKPOINT: {
ret = recvwait(bss, clientfd, buffer, 4 + 3 * 1);
// Read the data from the client
ret = recvwait(bss, clientfd, buffer, sizeof(int) + sizeof(bool) * 2);
ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (data breakpoint)");
// Parse the data and set the breakpoint
int bufferIndex = 0;
unsigned int address = ((unsigned int *) buffer)[bufferIndex];
bufferIndex += 4;
bool translate = buffer[bufferIndex++];
bool write = buffer[bufferIndex++];
bufferIndex += sizeof(int);
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)");
bufferIndex += sizeof(bool);
bool write = buffer[bufferIndex];
bufferIndex += sizeof(bool);
setDataAddressBreakPointRegister(address, read, write);
break;
}
case COMMAND_SET_INSTRUCTION_BREAKPOINT: {
// Read the address and set the breakpoint execute
// Read the address
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)");
// Parse the address and set the breakpoint
unsigned int address = ((unsigned int *) buffer)[0];
setInstructionAddressBreakPointRegister(address);
break;
}
@ -1513,7 +1292,7 @@ struct pygecko_bss_t *bss;
static int runTCPGeckoServer(int argc, void *argv) {
bss = argv;
setup_os_exceptions();
// setup_os_exceptions();
socket_lib_init();
log_init(COMPUTER_IP_ADDRESS);

View File

@ -1,15 +1,11 @@
#ifndef _PYGECKO_H_
#define _PYGECKO_H_
#include "common/types.h"
#include "dynamic_libs/os_functions.h"
/* Main */
#ifdef __cplusplus
extern "C" {
#endif
//! C wrapper for our C++ functions
void startTCPGecko(void);
#ifdef __cplusplus

View File

@ -3,167 +3,142 @@
#include "../utils/logger.h"
#include "exception_handler.h"
#define OS_EXCEPTION_MODE_GLOBAL_ALL_CORES 4
#define OS_EXCEPTION_DSI 2
#define OS_EXCEPTION_ISI 3
#define OS_EXCEPTION_PROGRAM 6
/* Exceptions */
typedef struct OSContext
{
/* OSContext identifier */
uint32_t tag1;
uint32_t tag2;
/* GPRs */
uint32_t gpr[32];
/* Special registers */
uint32_t cr;
uint32_t lr;
uint32_t ctr;
uint32_t xer;
/* Initial PC and MSR */
uint32_t srr0;
uint32_t srr1;
/* Only valid during DSI exception */
uint32_t exception_specific0;
uint32_t exception_specific1;
/* There is actually a lot more here but we don't need the rest*/
} OSContext;
#define CPU_STACK_TRACE_DEPTH 10
#define __stringify(rn) #rn
#define mfspr(_rn) \
({ register uint32_t _rval = 0; \
asm volatile("mfspr %0," __stringify(_rn) \
: "=r" (_rval));\
_rval; \
})
typedef struct _framerec {
struct _framerec *up;
void *lr;
} frame_rec, *frame_rec_t;
static const char *exception_names[] = {
"DSI",
"ISI",
"PROGRAM"
"DSI",
"ISI",
"PROGRAM"
};
static const char exception_print_formats[18][45] = {
"Exception type %s occurred!\n", // 0
"GPR00 %08X GPR08 %08X GPR16 %08X GPR24 %08X\n", // 1
"GPR01 %08X GPR09 %08X GPR17 %08X GPR25 %08X\n", // 2
"GPR02 %08X GPR10 %08X GPR18 %08X GPR26 %08X\n", // 3
"GPR03 %08X GPR11 %08X GPR19 %08X GPR27 %08X\n", // 4
"GPR04 %08X GPR12 %08X GPR20 %08X GPR28 %08X\n", // 5
"GPR05 %08X GPR13 %08X GPR21 %08X GPR29 %08X\n", // 6
"GPR06 %08X GPR14 %08X GPR22 %08X GPR30 %08X\n", // 7
"GPR07 %08X GPR15 %08X GPR23 %08X GPR31 %08X\n", // 8
"LR %08X SRR0 %08x SRR1 %08x\n", // 9
"DAR %08X DSISR %08X\n", // 10
"\nSTACK DUMP:", // 11
" --> ", // 12
" -->\n", // 13
"\n", // 14
"%p", // 15
"\nCODE DUMP:\n", // 16
"%p: %08X %08X %08X %08X\n", // 17
"Exception type %s occurred!\n", // 0
"GPR00 %08X GPR08 %08X GPR16 %08X GPR24 %08X\n", // 1
"GPR01 %08X GPR09 %08X GPR17 %08X GPR25 %08X\n", // 2
"GPR02 %08X GPR10 %08X GPR18 %08X GPR26 %08X\n", // 3
"GPR03 %08X GPR11 %08X GPR19 %08X GPR27 %08X\n", // 4
"GPR04 %08X GPR12 %08X GPR20 %08X GPR28 %08X\n", // 5
"GPR05 %08X GPR13 %08X GPR21 %08X GPR29 %08X\n", // 6
"GPR06 %08X GPR14 %08X GPR22 %08X GPR30 %08X\n", // 7
"GPR07 %08X GPR15 %08X GPR23 %08X GPR31 %08X\n", // 8
"LR %08X SRR0 %08x SRR1 %08x\n", // 9
"DAR %08X DSISR %08X\n", // 10
"\nSTACK DUMP:", // 11
" --> ", // 12
" -->\n", // 13
"\n", // 14
"%p", // 15
"\nCODE DUMP:\n", // 16
"%p: %08X %08X %08X %08X\n", // 17
};
static unsigned char exception_cb(void * c, unsigned char exception_type) {
char buf[850];
int pos = 0;
static unsigned char exceptionCallback(void *c, unsigned char exception_type) {
char stackTraceBuffer[850];
int pos = 0;
OSContext *context = (OSContext *) c;
/*
* This part is mostly from libogc. Thanks to the devs over there.
*/
pos += sprintf(buf + pos, exception_print_formats[0], exception_names[exception_type]);
pos += sprintf(buf + pos, exception_print_formats[1], context->gpr[0], context->gpr[8], context->gpr[16], context->gpr[24]);
pos += sprintf(buf + pos, exception_print_formats[2], context->gpr[1], context->gpr[9], context->gpr[17], context->gpr[25]);
pos += sprintf(buf + pos, exception_print_formats[3], context->gpr[2], context->gpr[10], context->gpr[18], context->gpr[26]);
pos += sprintf(buf + pos, exception_print_formats[4], context->gpr[3], context->gpr[11], context->gpr[19], context->gpr[27]);
pos += sprintf(buf + pos, exception_print_formats[5], context->gpr[4], context->gpr[12], context->gpr[20], context->gpr[28]);
pos += sprintf(buf + pos, exception_print_formats[6], context->gpr[5], context->gpr[13], context->gpr[21], context->gpr[29]);
pos += sprintf(buf + pos, exception_print_formats[7], context->gpr[6], context->gpr[14], context->gpr[22], context->gpr[30]);
pos += sprintf(buf + pos, exception_print_formats[8], context->gpr[7], context->gpr[15], context->gpr[23], context->gpr[31]);
pos += sprintf(buf + pos, exception_print_formats[9], context->lr, context->srr0, context->srr1);
OSContext *context = (OSContext *) c;
/*
* This part is mostly from libogc. Thanks to the devs over there.
*/
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[0], exception_names[exception_type]);
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[1], context->gpr[0], context->gpr[8],
context->gpr[16],
context->gpr[24]);
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[2], context->gpr[1], context->gpr[9],
context->gpr[17],
context->gpr[25]);
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[3], context->gpr[2], context->gpr[10],
context->gpr[18],
context->gpr[26]);
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[4], context->gpr[3], context->gpr[11],
context->gpr[19],
context->gpr[27]);
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[5], context->gpr[4], context->gpr[12],
context->gpr[20],
context->gpr[28]);
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[6], context->gpr[5], context->gpr[13],
context->gpr[21],
context->gpr[29]);
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[7], context->gpr[6], context->gpr[14],
context->gpr[22],
context->gpr[30]);
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[8], context->gpr[7], context->gpr[15],
context->gpr[23],
context->gpr[31]);
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[9], context->lr, context->srr0, context->srr1);
//if(exception_type == OS_EXCEPTION_DSI) {
pos += sprintf(buf + pos, exception_print_formats[10], context->exception_specific1, context->exception_specific0); // this freezes
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[10], context->exception_specific1,
context->exception_specific0); // this freezes
//}
void *pc = (void*)context->srr0;
void *lr = (void*)context->lr;
void *r1 = (void*)context->gpr[1];
register uint32_t i = 0;
register frame_rec_t l,p = (frame_rec_t)lr;
void *pc = (void *) context->srr0;
void *lr = (void *) context->lr;
void *r1 = (void *) context->gpr[1];
register uint32_t currentStackTraceDepth = 0;
register frame_rec_t l, p = (frame_rec_t) lr;
l = p;
p = r1;
if(!p)
asm volatile("mr %0,%%r1" : "=r"(p));
if (!p)
asm volatile("mr %0,%%r1" : "=r"(p));
pos += sprintf(buf + pos, exception_print_formats[11]);
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[11]);
for(i = 0; i < CPU_STACK_TRACE_DEPTH-1 && p->up; p = p->up, i++) {
if(i % 4)
pos += sprintf(buf + pos, exception_print_formats[12]);
for (currentStackTraceDepth = 0;
currentStackTraceDepth < CPU_STACK_TRACE_DEPTH - 1 && p->up; p = p->up, currentStackTraceDepth++) {
if (currentStackTraceDepth % 4)
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[12]);
else {
if(i > 0)
pos += sprintf(buf + pos, exception_print_formats[13]);
if (currentStackTraceDepth > 0)
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[13]);
else
pos += sprintf(buf + pos, exception_print_formats[14]);
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[14]);
}
switch(i) {
switch (currentStackTraceDepth) {
case 0:
if(pc)
pos += sprintf(buf + pos, exception_print_formats[15],pc);
if (pc)
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[15], pc);
break;
case 1:
if(!l)
l = (frame_rec_t)mfspr(8);
pos += sprintf(buf + pos, exception_print_formats[15],(void*)l);
if (!l)
l = (frame_rec_t) mfspr(8);
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[15], (void *) l);
break;
default:
pos += sprintf(buf + pos, exception_print_formats[15],(void*)(p->up->lr));
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[15], (void *) (p->up->lr));
break;
}
}
//if(exception_type == OS_EXCEPTION_DSI) {
uint32_t *pAdd = (uint32_t*)context->srr0;
pos += sprintf(buf + pos, exception_print_formats[16]);
// TODO by Dimok: this was actually be 3 instead of 2 lines in libogc .... but there is just no more space anymore on the screen
for (i = 0; i < 8; i += 4)
pos += sprintf(buf + pos, exception_print_formats[17], &(pAdd[i]),pAdd[i], pAdd[i+1], pAdd[i+2], pAdd[i+3]);
uint32_t *pAdd = (uint32_t *) context->srr0;
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[16]);
// TODO by Dimok: this was actually be 3 instead of 2 lines in libogc .... but there is just no more space anymore on the screen
for (currentStackTraceDepth = 0; currentStackTraceDepth < 8; currentStackTraceDepth += 4)
pos += sprintf(stackTraceBuffer + pos, exception_print_formats[17], &(pAdd[currentStackTraceDepth]),
pAdd[currentStackTraceDepth], pAdd[currentStackTraceDepth + 1], pAdd[currentStackTraceDepth + 2],
pAdd[currentStackTraceDepth + 3]);
//}
log_print(buf);
OSFatal(buf);
return 1;
log_print(stackTraceBuffer);
OSFatal(stackTraceBuffer);
return 1;
}
static unsigned char dsi_exception_cb(void * context) {
return exception_cb(context, 0);
}
static unsigned char isi_exception_cb(void * context) {
return exception_cb(context, 1);
}
static unsigned char program_exception_cb(void * context) {
return exception_cb(context, 2);
static unsigned char dsi_exception_cb(void *context) {
return exceptionCallback(context, 0);
}
void setup_os_exceptions(void) {
OSSetExceptionCallback(OS_EXCEPTION_DSI, &dsi_exception_cb);
OSSetExceptionCallback(OS_EXCEPTION_ISI, &isi_exception_cb);
OSSetExceptionCallback(OS_EXCEPTION_PROGRAM, &program_exception_cb);
static unsigned char isi_exception_cb(void *context) {
return exceptionCallback(context, 1);
}
static 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);
}

View File

@ -5,6 +5,52 @@
extern "C" {
#endif
#include "../utils/stringify.h"
#define OS_EXCEPTION_DSI 2
#define OS_EXCEPTION_ISI 3
#define OS_EXCEPTION_PROGRAM 6
/* Exceptions */
typedef struct OSContext {
/* OSContext identifier */
uint32_t tag1;
uint32_t tag2;
/* GPRs */
uint32_t gpr[32];
/* Special registers */
uint32_t cr;
uint32_t lr;
uint32_t ctr;
uint32_t xer;
/* Initial PC and MSR */
uint32_t srr0;
uint32_t srr1;
/* Only valid during DSI exception */
uint32_t exception_specific0;
uint32_t exception_specific1;
/* There is actually a lot more here but we don't need the rest*/
} OSContext;
#define CPU_STACK_TRACE_DEPTH 10
#define mfspr(_rn) \
({ register uint32_t _rval = 0; \
asm volatile("mfspr %0," __stringify(_rn) \
: "=r" (_rval));\
_rval; \
})
typedef struct _framerec {
struct _framerec *up;
void *lr;
} frame_rec, *frame_rec_t;
void setup_os_exceptions(void);
#ifdef __cplusplus

View File

@ -1,27 +0,0 @@
void m_DCFlushRange(unsigned int startAddr, unsigned int size)
{
register unsigned int addr = startAddr & ~0x1F;
register unsigned int end_addr = startAddr + size;
while(addr < end_addr)
{
asm volatile("dcbf 0, %0" : : "r"(addr));
addr += 0x20;
}
asm volatile("sync; eieio");
}
void m_DCInvalidateRange(unsigned int startAddr, unsigned int size)
{
register unsigned int addr = startAddr & ~0x1F;
register unsigned int end_addr = startAddr + size;
while(addr < end_addr)
{
asm volatile("dcbi 0, %0" : : "r"(addr));
addr += 0x20;
}
}

Binary file not shown.