Release development version
This commit is contained in:
parent
bd01f31bfc
commit
0e018f8392
@ -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
|
@ -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
|
@ -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
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
19
src/entry.c
19
src/entry.c
@ -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();
|
||||
|
@ -1,6 +0,0 @@
|
||||
#ifndef TCPGECKO_ENTRY_H
|
||||
#define TCPGECKO_ENTRY_H
|
||||
|
||||
bool isRunningTitleID(unsigned long long int japaneseTitleID);
|
||||
|
||||
#endif
|
@ -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
|
369
src/pygecko.c
369
src/pygecko.c
@ -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);
|
||||
|
@ -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
|
||||
|
@ -3,54 +3,6 @@
|
||||
#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",
|
||||
@ -78,91 +30,114 @@ static const char exception_print_formats[18][45] = {
|
||||
"%p: %08X %08X %08X %08X\n", // 17
|
||||
};
|
||||
|
||||
static unsigned char exception_cb(void * c, unsigned char exception_type) {
|
||||
char buf[850];
|
||||
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);
|
||||
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)
|
||||
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]);
|
||||
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 (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]);
|
||||
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);
|
||||
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) {
|
||||
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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
BIN
tcpgecko.elf
BIN
tcpgecko.elf
Binary file not shown.
Loading…
Reference in New Issue
Block a user