Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@CTurt
Last active August 8, 2020 16:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CTurt/6eecc155e2b545a58bad9a65e866b4ab to your computer and use it in GitHub Desktop.
Save CTurt/6eecc155e2b545a58bad9a65e866b4ab to your computer and use it in GitHub Desktop.
Find location of exported function in an IOP RAM dump (FlushDCache and FlushICache)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef u32 pointer;
typedef struct _smod_mod_info {
//struct _smod_mod_info *next;
pointer next;
/** A pointer to the name in IOP RAM, this must be smem_read(). */
//char *name;
pointer name;
u16 version;
/** For MODLOAD shipped with games. The old MODLOAD module from boot ROMs do not use a flags field. */
u16 newflags;
u16 id;
u16 unused;
/** _start */
u32 entry;
u32 gp;
u32 text_start;
u32 text_size;
u32 data_size;
u32 bss_size;
u32 unused1;
u32 unused2;
} smod_mod_info_t;
typedef struct _slib_imp_list {
u8 magic;
//struct _slib_imp_list *next;
pointer next;
u16 version;
u16 flags;
u8 name[8];
//void *imports[0];
pointer imports[0];
} slib_imp_list_t;
typedef struct _slib_exp_lib {
//struct _slib_exp_lib *prev;
pointer prev;
//struct _slib_imp_list *caller;
pointer caller;
u16 version;
u16 flags;
u8 name[8];
//void *exports[0];
pointer exports[0];
} slib_exp_lib_t;
typedef struct _slib_exp_lib_list {
//struct _slib_exp_lib *tail;
pointer tail;
//struct _slib_exp_lib *head;
pointer head;
} slib_exp_lib_list_t;
#define SMEM_BUF_SIZE 0x300 //Must be large enough to accommodate all operations.
struct smem_buf {
union {
u8 bytes[SMEM_BUF_SIZE / sizeof(u8)];
u32 words[SMEM_BUF_SIZE / sizeof(u32)];
smod_mod_info_t mod_info;
slib_exp_lib_t exp_lib;
};
};
slib_exp_lib_list_t _slib_cur_exp_lib_list = {NULL, NULL};
/* from common.c */
struct smem_buf smem_buf;
typedef unsigned int SifRpcReceiveData_t;
#define SyncDCache(a, b)
unsigned char *p;
size_t SifRpcGetOtherData(void *a, pointer x, void *dest, size_t s, int z) {
memcpy(dest, p + x, s);
return s;
}
slib_exp_lib_list_t *slib_exp_lib_list(void)
{
SifRpcReceiveData_t RData;
slib_exp_lib_t *core_exps;
slib_exp_lib_list_t *exp_lib_list = NULL;
u32 i, addr, core_end, NextMod, *exp_func;
void *pGetLoadcoreInternalData;
smod_mod_info_t *ModInfo;
/* Read the start of the global module table - this is where we will search. */
SyncDCache(&smem_buf, smem_buf.bytes+sizeof(smod_mod_info_t));
if(SifRpcGetOtherData(&RData, (void*)0x800, &smem_buf, sizeof(smod_mod_info_t), 0)>=0){
/* The first entry points to LOADCORE's module info. We then use the
module info to determine the end of LOADCORE's .text segment (just
past the export library we're trying to find. */
NextMod = *smem_buf.words;
SyncDCache(&smem_buf, smem_buf.bytes+sizeof(smod_mod_info_t));
if(SifRpcGetOtherData(&RData, (void*)NextMod, &smem_buf, sizeof(smod_mod_info_t), 0)>=0){
ModInfo = &smem_buf.mod_info;
core_end = ModInfo->text_start+ModInfo->text_size;
/* Back up so we position ourselves infront of where the export
library will be. */
SyncDCache(&smem_buf, smem_buf.bytes+512);
if(SifRpcGetOtherData(&RData, (void*)(core_end - 512), &smem_buf, 512, 0)>=0){
/* Search for LOADCORE's export library. */
for (i = 0; i < 512; i += 4) {
/* SYSMEM's export library sits at 0x830, so it should appear in
LOADCORE's prev pointer. */
if (smem_buf.words[i / sizeof(u32)] == 0x830) {
if (!memcmp(smem_buf.bytes + i + 12, "loadcore", 8))
break;
}
}
if (i >= 512)
return NULL;
/* Get to the start of the export table, and find the address of the
routine that will get us the export library list info. */
core_exps = (slib_exp_lib_t *)(smem_buf.bytes + i);
pGetLoadcoreInternalData = core_exps->exports[3];
SyncDCache(&smem_buf, smem_buf.bytes+8);
if(SifRpcGetOtherData(&RData, pGetLoadcoreInternalData, &smem_buf, 8, 0)>=0){
exp_func = smem_buf.words;
/* Parse the two instructions that hold the address of the table. */
if ((exp_func[0] & 0xffff0000) != 0x3c020000) /* lui v0, XXXX */
return NULL;
if ((exp_func[1] & 0xffff0000) != 0x24420000) /* addiu v0, v0, XXXX */
return NULL;
addr = ((exp_func[0] & 0xffff) << 16) | (exp_func[1] & 0xffff);
SyncDCache(&smem_buf, smem_buf.bytes+8);
if(SifRpcGetOtherData(&RData, (void*)addr, &smem_buf, 8, 0)>=0){
_slib_cur_exp_lib_list.tail = (slib_exp_lib_t *)(smem_buf.words[0]);
_slib_cur_exp_lib_list.head = (slib_exp_lib_t *)(smem_buf.words[1]);
exp_lib_list = &_slib_cur_exp_lib_list;
}
}
}
}
}
return exp_lib_list;
}
#define EXP_LIB_MAX SMEM_BUF_SIZE /* We can even handle CDVDMAN's bloat! */
int slib_get_exp_lib(const char *name, slib_exp_lib_t *library)
{
SifRpcReceiveData_t RData;
slib_exp_lib_list_t *exp_lib_list = &_slib_cur_exp_lib_list;
slib_exp_lib_t *exp_lib = &smem_buf.exp_lib;
void *cur_lib;
int len = strlen(name), count = 0;
if (!exp_lib_list->head && !(exp_lib_list = slib_exp_lib_list()))
return 0;
/* Read the tail export library to initiate the search. */
cur_lib = exp_lib_list->tail;
while (cur_lib) {
SyncDCache(&smem_buf, smem_buf.bytes+EXP_LIB_MAX);
if(SifRpcGetOtherData(&RData, cur_lib, exp_lib, EXP_LIB_MAX, 0)>=0){
if (!memcmp(exp_lib->name, name, len)) {
while (exp_lib->exports[count] != 0)
count++;
if (library)
memcpy(library, exp_lib, sizeof(slib_exp_lib_t) + count * 4);
return count;
}
cur_lib = exp_lib->prev;
}
}
return 0;
}
int main(int argc, char **argv) {
FILE *f = fopen(argv[1], "rb");
fseek(f, 0, SEEK_END);
size_t s = ftell(f);
p = malloc(s);
rewind(f);
fread(p, s, 1, f);
union {
u8 buf[256];
slib_exp_lib_t exp_lib;
} buf;
slib_exp_lib_t *modload_lib = &buf.exp_lib;
memset(&_slib_cur_exp_lib_list, 0, sizeof(slib_exp_lib_list_t));
//if (!slib_get_exp_lib("modload", modload_lib)) {
if (!slib_get_exp_lib("loadcore", modload_lib)) {
printf("not found\n");
return -1;
}
printf("flush i cache location: %08x\n", modload_lib->exports[4]);
printf("flush d cache location: %08x\n", modload_lib->exports[5]);
free(p);
fclose(f);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment