Splitted the function patcher

- Now the actual patcher and the functions to be patched are splitted into seperate files.
- Using now the same method to copy the kerneldata (no manual dbat setting setting needed anymore)
- Some code cleanup
This commit is contained in:
Maschell 2016-08-09 17:36:42 +02:00
parent c702ac015f
commit d2c4435a31
12 changed files with 286 additions and 230 deletions

View File

@ -51,18 +51,6 @@ extern "C" {
#define EXIT_HBL_EXIT 0xFFFFFFFE #define EXIT_HBL_EXIT 0xFFFFFFFE
#define EXIT_RELAUNCH_ON_LOAD 0xFFFFFFFD #define EXIT_RELAUNCH_ON_LOAD 0xFFFFFFFD
#define RESTORE_INSTR_MAGIC 0xC001C0DE
#define RESTORE_INSTR_ADDR ((restore_instructions_t*)(MEM_BASE + 0x1600))
typedef struct _restore_instructions_t {
unsigned int magic;
unsigned int instr_count;
struct {
unsigned int addr;
unsigned int instr;
} data[0];
} restore_instructions_t;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -1 +1 @@
Subproject commit 4c496011da4937e9b518961f374d7f0693874bf1 Subproject commit 4e38178c16f49e44900db0279494c8f1e605df54

View File

@ -47,44 +47,3 @@ void SetupKernelCallback(void)
KernelSetupSyscalls(); KernelSetupSyscalls();
} }
void KernelSetDBATs(bat_table_t * table)
{
KernelSetDBATsInternal(table,0xC0001FFF,0x30000012);
}
/* physical_address is the physical address*/
void KernelSetDBATsForDynamicFuction(bat_table_t * table, unsigned int physical_address)
{
KernelSetDBATsInternal(table,(physical_address & 0xFFFC0000) | 0x0F,(physical_address & 0xFFFC0000) | 0x32);
}
void KernelSetDBATsInternal(bat_table_t * table, unsigned int high_address, unsigned int low_address)
{
SC0x36_KernelReadDBATs(table);
bat_table_t bat_table_copy = *table;
// try to use a free slot
int iUse;
for(iUse = 0; iUse < 7; iUse++)
{
// skip position 5 as it is our main DBAT for our code data
if(iUse == 5)
continue;
if(bat_table_copy.bat[iUse].h == 0 || bat_table_copy.bat[iUse].l == 0)
{
break;
}
}
bat_table_copy.bat[iUse].h = high_address;
bat_table_copy.bat[iUse].l = low_address;
SC0x37_KernelWriteDBATs(&bat_table_copy);
}
void KernelRestoreDBATs(bat_table_t * table)
{
SC0x37_KernelWriteDBATs(table);
}

View File

@ -8,14 +8,9 @@ extern "C" {
#include "common/kernel_defs.h" #include "common/kernel_defs.h"
#include "syscalls.h" #include "syscalls.h"
extern ReducedCosAppXmlInfo cosAppXmlInfoStruct;
void SetupKernelCallback(void); void SetupKernelCallback(void);
void KernelRestoreDBATs(bat_table_t * table); extern ReducedCosAppXmlInfo cosAppXmlInfoStruct;
void KernelSetDBATs(bat_table_t * table);
void KernelSetDBATsForDynamicFuction(bat_table_t * table, unsigned int physical_address);
void KernelSetDBATsInternal(bat_table_t * table, unsigned int high_address, unsigned int low_address);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -12,64 +12,83 @@ static unsigned int origPrepareTitleInstr __attribute__((section(".data"))) = 0;
static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len) static void KernelCopyData(unsigned int addr, unsigned int src, unsigned int len)
{ {
/* /*
* Setup a DBAT access for our 0xC0800000 area and our 0xBC000000 area which hold our variables like GAME_LAUNCHED and our BSS/rodata section * Setup a DBAT access with cache inhibited to write through and read directly from memory
*/ */
register int dbatu0, dbatl0, dbatu1, dbatl1; unsigned int dbatu0, dbatl0, dbatu1, dbatl1;
// save the original DBAT value // save the original DBAT value
asm volatile("mfdbatu %0, 0" : "=r" (dbatu0)); asm volatile("mfdbatu %0, 0" : "=r" (dbatu0));
asm volatile("mfdbatl %0, 0" : "=r" (dbatl0)); asm volatile("mfdbatl %0, 0" : "=r" (dbatl0));
asm volatile("mfdbatu %0, 1" : "=r" (dbatu1)); asm volatile("mfdbatu %0, 1" : "=r" (dbatu1));
asm volatile("mfdbatl %0, 1" : "=r" (dbatl1)); asm volatile("mfdbatl %0, 1" : "=r" (dbatl1));
// write our own DBATs into the array unsigned int target_dbatu0 = 0;
if( ((addr & 0xFFF00000) == 0xFFF00000) || ((src & 0xFFF00000) == 0xFFF00000) ) unsigned int target_dbatl0 = 0;
{ unsigned int target_dbatu1 = 0;
// setup kernel code access unsigned int target_dbatl1 = 0;
unsigned int dbatu = 0;
unsigned int dbatl = 0;
if((src & 0xFFF00000) == 0xFFF00000) {
dbatu = (src & 0xFFF00000) | 0x02;
dbatl = (src & 0xFFF00000) | 0x32;
}
else {
dbatu = (addr & 0xFFF00000) | 0x02;
dbatl = (addr & 0xFFF00000) | 0x32;
}
if( ((addr & 0xFFF00000) != (dbatu0 & 0xFFF00000)) && ((src & 0xFFF00000) != (dbatu0 & 0xFFF00000)) )
{
asm volatile("mtdbatu 0, %0" : : "r" (dbatu));
asm volatile("mtdbatl 0, %0" : : "r" (dbatl));
}
else
{
asm volatile("mtdbatu 1, %0" : : "r" (dbatu));
asm volatile("mtdbatl 1, %0" : : "r" (dbatl));
}
}
else
{
asm volatile("mtdbatu 0, %0" : : "r" (0xC0001FFF));
asm volatile("mtdbatl 0, %0" : : "r" (0x30000012));
asm volatile("mtdbatu 1, %0" : : "r" (0xB0801FFF));
asm volatile("mtdbatl 1, %0" : : "r" (0x20800012));
}
asm volatile("eieio; isync");
unsigned char *src_p = (unsigned char*)src;
unsigned char *dst_p = (unsigned char*)addr; unsigned char *dst_p = (unsigned char*)addr;
unsigned char *src_p = (unsigned char*)src;
// we only need DBAT modification for addresses out of our own DBAT range
// as our own DBAT is available everywhere for user and supervisor
// since our own DBAT is on DBAT5 position we don't collide here
if(addr < 0x00800000 || addr >= 0x01000000)
{
target_dbatu0 = (addr & 0x00F00000) | 0xC0000000 | 0x1F;
target_dbatl0 = (addr & 0xFFF00000) | 0x32;
asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0));
asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0));
dst_p = (unsigned char*)((addr & 0xFFFFFF) | 0xC0000000);
}
if(src < 0x00800000 || src >= 0x01000000)
{
target_dbatu1 = (src & 0x00F00000) | 0xB0000000 | 0x1F;
target_dbatl1 = (src & 0xFFF00000) | 0x32;
asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1));
asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1));
src_p = (unsigned char*)((src & 0xFFFFFF) | 0xB0000000);
}
asm volatile("eieio; isync");
unsigned int i; unsigned int i;
for(i = 0; i < len; i++) for(i = 0; i < len; i++)
{ {
dst_p[i] = src_p[i]; // if we are on the edge to next chunk
if((target_dbatu0 != 0) && (((unsigned int)dst_p & 0x00F00000) != (target_dbatu0 & 0x00F00000)))
{
target_dbatu0 = ((addr + i) & 0x00F00000) | 0xC0000000 | 0x1F;
target_dbatl0 = ((addr + i) & 0xFFF00000) | 0x32;
dst_p = (unsigned char*)(((addr + i) & 0xFFFFFF) | 0xC0000000);
asm volatile("eieio; isync");
asm volatile("mtdbatu 0, %0" : : "r" (target_dbatu0));
asm volatile("mtdbatl 0, %0" : : "r" (target_dbatl0));
asm volatile("eieio; isync");
}
if((target_dbatu1 != 0) && (((unsigned int)src_p & 0x00F00000) != (target_dbatu1 & 0x00F00000)))
{
target_dbatu1 = ((src + i) & 0x00F00000) | 0xB0000000 | 0x1F;
target_dbatl1 = ((src + i) & 0xFFF00000) | 0x32;
src_p = (unsigned char*)(((src + i) & 0xFFFFFF) | 0xB0000000);
asm volatile("eieio; isync");
asm volatile("mtdbatu 1, %0" : : "r" (target_dbatu1));
asm volatile("mtdbatl 1, %0" : : "r" (target_dbatl1));
asm volatile("eieio; isync");
}
*dst_p = *src_p;
++dst_p;
++src_p;
} }
/* /*
* Restore original DBAT value * Restore original DBAT value
*/ */
asm volatile("eieio; isync");
asm volatile("mtdbatu 0, %0" : : "r" (dbatu0)); asm volatile("mtdbatu 0, %0" : : "r" (dbatu0));
asm volatile("mtdbatl 0, %0" : : "r" (dbatl0)); asm volatile("mtdbatl 0, %0" : : "r" (dbatl0));
asm volatile("mtdbatu 1, %0" : : "r" (dbatu1)); asm volatile("mtdbatu 1, %0" : : "r" (dbatu1));
@ -143,8 +162,35 @@ static void KernelWriteDBATs(bat_table_t * table)
asm volatile("eieio; isync"); asm volatile("eieio; isync");
} }
/* Read a 32-bit word with kernel permissions */
uint32_t __attribute__ ((noinline)) kern_read(const void *addr)
{
uint32_t result;
asm volatile (
"li 3,1\n"
"li 4,0\n"
"li 5,0\n"
"li 6,0\n"
"li 7,0\n"
"lis 8,1\n"
"mr 9,%1\n"
"li 0,0x3400\n"
"mr %0,1\n"
"sc\n"
"nop\n"
"mr 1,%0\n"
"mr %0,3\n"
: "=r"(result)
: "b"(addr)
: "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12"
);
return result;
}
/* Write a 32-bit word with kernel permissions */ /* Write a 32-bit word with kernel permissions */
static void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value) void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value)
{ {
asm volatile ( asm volatile (
"li 3,1\n" "li 3,1\n"
@ -195,9 +241,10 @@ void KernelSetupSyscalls(void)
//! write our hook to the //! write our hook to the
u32 addr_my_PrepareTitle_hook = ((u32)my_PrepareTitle_hook) | 0x48000003; u32 addr_my_PrepareTitle_hook = ((u32)my_PrepareTitle_hook) | 0x48000003;
DCFlushRange(&addr_my_PrepareTitle_hook, sizeof(addr_my_PrepareTitle_hook));
SC0x25_KernelCopyData((u32)&origPrepareTitleInstr, (u32)addr_PrepareTitle_hook, 4); SC0x25_KernelCopyData((u32)&origPrepareTitleInstr, (u32)addr_PrepareTitle_hook, 4);
SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)&addr_my_PrepareTitle_hook, 4); SC0x25_KernelCopyData((u32)addr_PrepareTitle_hook, (u32)OSEffectiveToPhysical(&addr_my_PrepareTitle_hook), 4);
} }

View File

@ -1,3 +1,4 @@
#ifndef __SYSCALLS_H_ #ifndef __SYSCALLS_H_
#define __SYSCALLS_H_ #define __SYSCALLS_H_
@ -15,6 +16,8 @@ void SC0x25_KernelCopyData(unsigned int addr, unsigned int src, unsigned int len
void SC0x36_KernelReadDBATs(bat_table_t * table); void SC0x36_KernelReadDBATs(bat_table_t * table);
void SC0x37_KernelWriteDBATs(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 #ifdef __cplusplus
} }

View File

@ -4,6 +4,8 @@
#include <malloc.h> #include <malloc.h>
#include "main.h" #include "main.h"
#include "version.h" #include "version.h"
#include "common/common.h"
#include "dynamic_libs/os_functions.h" #include "dynamic_libs/os_functions.h"
#include "dynamic_libs/gx2_functions.h" #include "dynamic_libs/gx2_functions.h"
#include "dynamic_libs/syshid_functions.h" #include "dynamic_libs/syshid_functions.h"
@ -13,7 +15,8 @@
#include "controller_patcher/controller_patcher.h" #include "controller_patcher/controller_patcher.h"
#include "controller_patcher/config_reader.h" #include "controller_patcher/config_reader.h"
#include "controller_patcher/cp_retain_vars.h" #include "controller_patcher/cp_retain_vars.h"
#include "patcher/function_hooks.h" #include "utils/function_patcher.h"
#include "patcher/hid_controller_patcher.h"
#include "kernel/kernel_functions.h" #include "kernel/kernel_functions.h"
#include "video/CursorDrawer.h" #include "video/CursorDrawer.h"
#include "utils/logger.h" #include "utils/logger.h"
@ -67,7 +70,7 @@ extern "C" int Menu_Main(void)
//! Patching functions * //! Patching functions *
//!******************************************************************* //!*******************************************************************
log_print("Patching functions\n"); log_print("Patching functions\n");
PatchMethodHooks(); ApplyPatches();
if(strlen(cosAppXmlInfoStruct.rpx_name) > 0 && strcasecmp("ffl_app.rpx", cosAppXmlInfoStruct.rpx_name) != 0) if(strlen(cosAppXmlInfoStruct.rpx_name) > 0 && strcasecmp("ffl_app.rpx", cosAppXmlInfoStruct.rpx_name) != 0)
{ {
@ -83,10 +86,12 @@ extern "C" int Menu_Main(void)
deInit(); deInit();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void ApplyPatches(){
PatchInvidualMethodHooks(method_hooks_hid_controller, method_hooks_size_hid_controller, method_calls_hid_controller);
}
void deInit(){ void deInit(){
CursorDrawer::destroyInstance(); CursorDrawer::destroyInstance();
RestoreInstructions(); RestoreInvidualInstructions(method_hooks_hid_controller,method_hooks_size_hid_controller);
deinit_config_controller(); deinit_config_controller();
log_deinit(); log_deinit();
} }

View File

@ -13,6 +13,7 @@ extern "C" {
int Menu_Main(void); int Menu_Main(void);
void SplashScreen(int time); void SplashScreen(int time);
void deInit(void); void deInit(void);
void ApplyPatches(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -0,0 +1,60 @@
/****************************************************************************
* Copyright (C) 2016 Maschell
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "hid_controller_patcher.h"
#include "video/CursorDrawer.h"
#include "controller_patcher/cp_retain_vars.h"
#include "utils/logger.h"
DECL(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, s32 scan_target){
if(gHIDCurrentDevice & gHID_LIST_MOUSE && gHID_Mouse_Mode == HID_MOUSE_MODE_TOUCH) {
CursorDrawer::draw(gHID_Mouse.pad_data[0].data[0].X, gHID_Mouse.pad_data[0].data[0].Y);
}
real_GX2CopyColorBufferToScanBuffer(colorBuffer,scan_target);
}
DECL(void, _Exit, void){
CursorDrawer::destroyInstance();
real__Exit();
}
DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) {
int result = real_VPADRead(chan, buffer, buffer_size, error);
if(gHIDAttached){
setControllerDataFromHID(buffer,HID_ALL_CONNECTED_DEVICES);
}
if(gButtonRemappingConfigDone){
buttonRemapping(buffer);
if (HID_DEBUG) printButtons(buffer);
}
return result;
}
hooks_magic_t method_hooks_hid_controller[] __attribute__((section(".data"))) = {
MAKE_MAGIC(VPADRead, LIB_VPAD, STATIC_FUNCTION),
MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(_Exit, LIB_CORE_INIT, STATIC_FUNCTION),
};
u32 method_hooks_size_hid_controller __attribute__((section(".data"))) = sizeof(method_hooks_hid_controller) / sizeof(hooks_magic_t);
//! buffer to store our instructions needed for our replacements
volatile unsigned int method_calls_hid_controller[sizeof(method_hooks_hid_controller) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(".data")));

View File

@ -15,20 +15,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/ ****************************************************************************/
#ifndef _FUNCTION_HOOKS_H_ #ifndef _HID_CONTROLLER_FUNCTION_PATCHER_H
#define _FUNCTION_HOOKS_H_ #define _HID_CONTROLLER_FUNCTION_PATCHER_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void PatchMethodHooks(void); #include "utils/function_patcher.h"
void RestoreInstructions(void);
unsigned int GetAddressOfFunction(const char * functionName,unsigned int library); extern hooks_magic_t method_hooks_hid_controller[];
int isDynamicFunction(unsigned int physicalAddress); extern u32 method_hooks_size_hid_controller;
extern volatile unsigned int method_calls_hid_controller[];
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _FS_H */ #endif /* _HID_CONTROLLER_FUNCTION_PATCHER_H */

View File

@ -15,99 +15,33 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/ ****************************************************************************/
#include <vector>
#include <algorithm>
#include <stdio.h> #include <stdio.h>
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
#include <gctypes.h> #include <gctypes.h>
#include "function_hooks.h" #include "function_patcher.h"
#include "controller_patcher/cp_retain_vars.h"
#include "dynamic_libs/aoc_functions.h"
#include "dynamic_libs/ax_functions.h"
#include "dynamic_libs/fs_functions.h"
#include "dynamic_libs/gx2_functions.h"
#include "dynamic_libs/os_functions.h"
#include "dynamic_libs/padscore_functions.h"
#include "dynamic_libs/socket_functions.h"
#include "dynamic_libs/sys_functions.h"
#include "dynamic_libs/vpad_functions.h"
#include "dynamic_libs/acp_functions.h"
#include "dynamic_libs/syshid_functions.h"
#include "kernel/kernel_functions.h"
#include "utils/logger.h" #include "utils/logger.h"
#include "video/CursorDrawer.h" #include "common/kernel_defs.h"
#include "kernel/kernel_functions.h"
#define LIB_CODE_RW_BASE_OFFSET 0xC1000000 #define LIB_CODE_RW_BASE_OFFSET 0xC1000000
#define CODE_RW_BASE_OFFSET 0x00000000 #define CODE_RW_BASE_OFFSET 0x00000000
#define DEBUG_LOG_DYN 0 #define DEBUG_LOG_DYN 0
#define USE_EXTRA_LOG_FUNCTIONS 0
#define DECL(res, name, ...) \
res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".data"))); \
res my_ ## name(__VA_ARGS__)
DECL(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, s32 scan_target){
if(gHIDCurrentDevice & gHID_LIST_MOUSE && gHID_Mouse_Mode == HID_MOUSE_MODE_TOUCH) {
CursorDrawer::draw(gHID_Mouse.pad_data[0].data[0].X, gHID_Mouse.pad_data[0].data[0].Y);
}
real_GX2CopyColorBufferToScanBuffer(colorBuffer,scan_target);
}
DECL(void, _Exit, void){
CursorDrawer::destroyInstance();
real__Exit();
}
DECL(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) {
int result = real_VPADRead(chan, buffer, buffer_size, error);
if(gHIDAttached){
setControllerDataFromHID(buffer,HID_ALL_CONNECTED_DEVICES);
}
if(gButtonRemappingConfigDone){
buttonRemapping(buffer);
if (HID_DEBUG) printButtons(buffer);
}
return result;
}
/* *****************************************************************************
* Creates function pointer array
* ****************************************************************************/
#define MAKE_MAGIC(x, lib,functionType) { (unsigned int) my_ ## x, (unsigned int) &real_ ## x, lib, # x,0,0,functionType,0}
static struct hooks_magic_t {
const unsigned int replaceAddr;
const unsigned int replaceCall;
const unsigned int library;
const char functionName[50];
unsigned int realAddr;
unsigned int restoreInstruction;
unsigned char functionType;
unsigned char alreadyPatched;
} method_hooks[] = {
// Common FS functions
MAKE_MAGIC(VPADRead, LIB_VPAD,STATIC_FUNCTION),
MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2,STATIC_FUNCTION),
MAKE_MAGIC(_Exit, LIB_CORE_INIT,STATIC_FUNCTION),
};
//! buffer to store our 7 instructions needed for our replacements
//! the code will be placed in the address of that buffer - CODE_RW_BASE_OFFSET
//! avoid this buffer to be placed in BSS and reset on start up
volatile unsigned int dynamic_method_calls[sizeof(method_hooks) / sizeof(struct hooks_magic_t) * 7] __attribute__((section(".data")));
/* /*
*Patches a function that is loaded at the start of each application. Its not required to restore, at least when they are really dynamic. * Patches a function that is loaded at the start of each application. Its not required to restore, at least when they are really dynamic.
* "normal" functions should be patch with the normal patcher. Current Code by Maschell with the help of dimok. * "normal" functions should be patch with the normal patcher. Current Code by Maschell with the help of dimok. Orignal code by Chadderz.
*/ */
void PatchMethodHooks(void) void PatchInvidualMethodHooks(hooks_magic_t method_hooks[],int hook_information_size, volatile unsigned int dynamic_method_calls[])
{ {
log_printf("Patching %d given functions\n",hook_information_size);
/* Patch branches to it. */ /* Patch branches to it. */
volatile unsigned int *space = &dynamic_method_calls[0]; volatile unsigned int *space = &dynamic_method_calls[0];
int method_hooks_count = sizeof(method_hooks) / sizeof(struct hooks_magic_t); int method_hooks_count = hook_information_size;
u32 skip_instr = 1; u32 skip_instr = 1;
u32 my_instr_len = 6; u32 my_instr_len = 6;
@ -118,10 +52,10 @@ void PatchMethodHooks(void)
log_printf("Patching %s ...",method_hooks[i].functionName); log_printf("Patching %s ...",method_hooks[i].functionName);
if(method_hooks[i].functionType == STATIC_FUNCTION && method_hooks[i].alreadyPatched == 1){ if(method_hooks[i].functionType == STATIC_FUNCTION && method_hooks[i].alreadyPatched == 1){
if(isDynamicFunction((u32)OSEffectiveToPhysical((void*)method_hooks[i].realAddr))){ if(isDynamicFunction((u32)OSEffectiveToPhysical((void*)method_hooks[i].realAddr))){
log_printf(" The function %s is a dynamic function. Please fix that <3 ... ", method_hooks[i].functionName); log_printf("The function %s is a dynamic function. Please fix that <3\n", method_hooks[i].functionName);
method_hooks[i].functionType = DYNAMIC_FUNCTION; method_hooks[i].functionType = DYNAMIC_FUNCTION;
}else{ }else{
log_printf(" skipped. Its already patched\n", method_hooks[i].functionName); log_printf("Skipping %s, its already patched\n", method_hooks[i].functionName);
space += instr_len; space += instr_len;
continue; continue;
} }
@ -134,7 +68,7 @@ void PatchMethodHooks(void)
unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library); unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);
if(!real_addr){ if(!real_addr){
log_printf("Error. OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName); log_printf("OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName);
space += instr_len; space += instr_len;
continue; continue;
} }
@ -150,27 +84,21 @@ void PatchMethodHooks(void)
if(DEBUG_LOG_DYN)log_printf("%s physical is located at %08X!\n", method_hooks[i].functionName,physical); if(DEBUG_LOG_DYN)log_printf("%s physical is located at %08X!\n", method_hooks[i].functionName,physical);
bat_table_t my_dbat_table;
if(DEBUG_LOG_DYN)log_printf("Setting up DBAT\n");
KernelSetDBATsForDynamicFuction(&my_dbat_table,physical);
//log_printf("Setting call_addr to %08X\n",(unsigned int)(space) - CODE_RW_BASE_OFFSET);
*(volatile unsigned int *)(call_addr) = (unsigned int)(space) - CODE_RW_BASE_OFFSET; *(volatile unsigned int *)(call_addr) = (unsigned int)(space) - CODE_RW_BASE_OFFSET;
// copy instructions from real function.
u32 offset_ptr = 0; SC0x25_KernelCopyData((u32)space, physical, 4);
for(offset_ptr = 0;offset_ptr<skip_instr*4;offset_ptr +=4){
if(DEBUG_LOG_DYN)log_printf("(real_)%08X = %08X\n",space,*(volatile unsigned int*)(physical+offset_ptr));
*space = *(volatile unsigned int*)(physical+offset_ptr);
space++; space++;
}
//Only works if skip_instr == 1 //Only works if skip_instr == 1
if(skip_instr == 1){ if(skip_instr == 1){
// fill the restore instruction section // fill the restore instruction section
method_hooks[i].realAddr = real_addr; method_hooks[i].realAddr = real_addr;
method_hooks[i].restoreInstruction = *(volatile unsigned int*)(physical); method_hooks[i].restoreInstruction = *(space-1);
}else{ if(DEBUG_LOG_DYN)log_printf("method_hooks[i].realAddr = %08X!\n", method_hooks[i].realAddr);
if(DEBUG_LOG_DYN)log_printf("method_hooks[i].restoreInstruction = %08X!\n",method_hooks[i].restoreInstruction) ;
}
else{
log_printf("Error. Can't save %s for restoring!\n", method_hooks[i].functionName); log_printf("Error. Can't save %s for restoring!\n", method_hooks[i].functionName);
} }
@ -199,63 +127,62 @@ void PatchMethodHooks(void)
//setting jump back //setting jump back
unsigned int replace_instr = 0x48000002 | (repl_addr & 0x03fffffc); unsigned int replace_instr = 0x48000002 | (repl_addr & 0x03fffffc);
*(volatile unsigned int *)(physical) = replace_instr; DCFlushRange(&replace_instr, 4);
SC0x25_KernelCopyData(physical, (u32)OSEffectiveToPhysical(&replace_instr), 4);
ICInvalidateRange((void*)(real_addr), 4); ICInvalidateRange((void*)(real_addr), 4);
//restore my dbat stuff
KernelRestoreDBATs(&my_dbat_table);
method_hooks[i].alreadyPatched = 1; method_hooks[i].alreadyPatched = 1;
log_printf("done!\n"); log_printf("done!\n");
} }
log_print("Done with patching all functions!\n"); log_print("Done with patching given functions!\n");
} }
/* ****************************************************************** */ /* ****************************************************************** */
/* RESTORE ORIGINAL INSTRUCTIONS */ /* RESTORE ORIGINAL INSTRUCTIONS */
/* ****************************************************************** */ /* ****************************************************************** */
void RestoreInstructions(void) void RestoreInvidualInstructions(hooks_magic_t method_hooks[],int hook_information_size)
{ {
bat_table_t table; log_printf("Restoring given functions!\n");
log_printf("Restore functions!\n"); int method_hooks_count = hook_information_size;
int method_hooks_count = sizeof(method_hooks) / sizeof(struct hooks_magic_t);
for(int i = 0; i < method_hooks_count; i++) for(int i = 0; i < method_hooks_count; i++)
{ {
log_printf("Restoring %s ...",method_hooks[i].functionName);
if(method_hooks[i].restoreInstruction == 0 || method_hooks[i].realAddr == 0){ if(method_hooks[i].restoreInstruction == 0 || method_hooks[i].realAddr == 0){
log_printf("Error. I dont have the information for the restore =( skip\n"); log_printf("I dont have the information for the restore =( skip\n");
continue; continue;
} }
unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library); unsigned int real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);
if(!real_addr){ if(!real_addr){
//log_printf("Error. OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName); log_printf("OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName);
continue; continue;
} }
u32 physical = (u32)OSEffectiveToPhysical((void*)real_addr); u32 physical = (u32)OSEffectiveToPhysical((void*)real_addr);
if(!physical){ if(!physical){
log_printf("Error. Something is wrong with the physical address\n"); log_printf("Something is wrong with the physical address\n");
continue; continue;
} }
if(isDynamicFunction(physical)){ if(isDynamicFunction(physical))
log_printf("Error. Its a dynamic function. We don't need to restore it! %s\n",method_hooks[i].functionName); {
}else{ log_printf("Its a dynamic function. We don't need to restore it! %s\n",method_hooks[i].functionName);
KernelSetDBATs(&table); }
else
*(volatile unsigned int *)(LIB_CODE_RW_BASE_OFFSET + method_hooks[i].realAddr) = method_hooks[i].restoreInstruction; {
DCFlushRange((void*)(LIB_CODE_RW_BASE_OFFSET + method_hooks[i].realAddr), 4); physical = (u32)OSEffectiveToPhysical((void*)method_hooks[i].realAddr); //When its an static function, we need to use the old location
if(DEBUG_LOG_DYN)log_printf("Restoring %08X to %08X\n",(u32)method_hooks[i].restoreInstruction,physical);
SC0x25_KernelCopyData(physical,(u32)&method_hooks[i].restoreInstruction , 4);
if(DEBUG_LOG_DYN)log_printf("ICInvalidateRange %08X\n",(void*)method_hooks[i].realAddr);
ICInvalidateRange((void*)method_hooks[i].realAddr, 4); ICInvalidateRange((void*)method_hooks[i].realAddr, 4);
log_printf(" done\n");
KernelRestoreDBATs(&table);
} }
method_hooks[i].alreadyPatched = 0; // In case a method_hooks[i].alreadyPatched = 0; // In case a
} }
KernelRestoreInstructions(); KernelRestoreInstructions();
log_print("Done with restoring all functions!\n"); log_print("Done with restoring given functions!\n");
} }
int isDynamicFunction(unsigned int physicalAddress){ int isDynamicFunction(unsigned int physicalAddress){

View File

@ -0,0 +1,70 @@
/****************************************************************************
* Copyright (C) 2016 Maschell
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _FUNCTION_HOOKS_H_
#define _FUNCTION_HOOKS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <gctypes.h>
#include "common/common.h"
#include "dynamic_libs/aoc_functions.h"
#include "dynamic_libs/ax_functions.h"
#include "dynamic_libs/fs_functions.h"
#include "dynamic_libs/gx2_functions.h"
#include "dynamic_libs/os_functions.h"
#include "dynamic_libs/padscore_functions.h"
#include "dynamic_libs/socket_functions.h"
#include "dynamic_libs/sys_functions.h"
#include "dynamic_libs/vpad_functions.h"
#include "dynamic_libs/acp_functions.h"
#include "dynamic_libs/syshid_functions.h"
//Orignal code by Chadderz.
#define DECL(res, name, ...) \
res (* real_ ## name)(__VA_ARGS__) __attribute__((section(".data"))); \
res my_ ## name(__VA_ARGS__)
#define FUNCTION_PATCHER_METHOD_STORE_SIZE 7
typedef struct {
const unsigned int replaceAddr;
const unsigned int replaceCall;
const unsigned int library;
const char functionName[50];
unsigned int realAddr;
unsigned int restoreInstruction;
unsigned char functionType;
unsigned char alreadyPatched;
} hooks_magic_t;
void PatchInvidualMethodHooks(hooks_magic_t hook_information[],int hook_information_size, volatile unsigned int dynamic_method_calls[]);
void RestoreInvidualInstructions(hooks_magic_t hook_information[],int hook_information_size);
unsigned int GetAddressOfFunction(const char * functionName,unsigned int library);
int isDynamicFunction(unsigned int physicalAddress);
//Orignal code by Chadderz.
#define MAKE_MAGIC(x, lib,functionType) { (unsigned int) my_ ## x, (unsigned int) &real_ ## x, lib, # x,0,0,functionType,0}
#ifdef __cplusplus
}
#endif
#endif /* _FS_H */