Merge pull request #362 from unknownbrackets/module-exports

Process module exports and listen to them
This commit is contained in:
Henrik Rydgård 2013-01-08 00:50:03 -08:00
commit 27cfde291d
2 changed files with 134 additions and 7 deletions

View file

@ -51,6 +51,7 @@ enum
static std::vector<HLEModule> moduleDB;
static std::vector<Syscall> unresolvedSyscalls;
static std::vector<Syscall> exportedCalls;
static int hleAfterSyscall = HLE_AFTER_NOTHING;
static char hleAfterSyscallReschedReason[512];
@ -63,6 +64,7 @@ void HLEDoState(PointerWrap &p)
{
Syscall sc = {0};
p.Do(unresolvedSyscalls, sc);
p.Do(exportedCalls, sc);
p.DoMarker("HLE");
}
@ -71,6 +73,7 @@ void HLEShutdown()
hleAfterSyscall = HLE_AFTER_NOTHING;
moduleDB.clear();
unresolvedSyscalls.clear();
exportedCalls.clear();
}
void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable)
@ -124,15 +127,26 @@ const HLEFunction *GetFunc(const char *moduleName, u32 nib)
const char *GetFuncName(const char *moduleName, u32 nib)
{
_dbg_assert_msg_(HLE, moduleName != NULL, "Invalid module name.");
const HLEFunction *func = GetFunc(moduleName,nib);
if (func)
return func->name;
else
// Was this function exported previously?
static char temp[256];
for (auto it = exportedCalls.begin(), end = exportedCalls.end(); it != end; ++it)
{
static char temp[256];
sprintf(temp,"[UNK: 0x%08x ]",nib);
return temp;
if (!strcmp(it->moduleName, moduleName) && it->nid == nib)
{
sprintf(temp, "[EXP: 0x%08x]", nib);
return temp;
}
}
// No good, we can't find it.
sprintf(temp,"[UNK: 0x%08x]", nib);
return temp;
}
u32 GetSyscallOp(const char *moduleName, u32 nib)
@ -173,17 +187,34 @@ void WriteSyscall(const char *moduleName, u32 nib, u32 address)
}
else
{
// Did another module export this already?
for (auto it = exportedCalls.begin(), end = exportedCalls.end(); it != end; ++it)
{
if (!strcmp(it->moduleName, moduleName) && it->nid == nib)
{
Memory::Write_U32(MIPS_MAKE_J(it->symAddr), address); // j symAddr
Memory::Write_U32(MIPS_MAKE_NOP(), address + 4); // nop (delay slot)
return;
}
}
// Module inexistent.. for now; let's store the syscall for it to be resolved later
INFO_LOG(HLE,"Syscall (%s,%08x) unresolved, storing for later resolving", moduleName, nib);
Syscall sysc = {"", address, nib};
strncpy(sysc.moduleName, moduleName, 32);
sysc.moduleName[31] = '\0';
strncpy(sysc.moduleName, moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
sysc.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
unresolvedSyscalls.push_back(sysc);
// Write a trap so we notice this func if it's called before resolving.
Memory::Write_U32(MIPS_MAKE_JR_RA(), address); // jr ra
Memory::Write_U32(GetSyscallOp("(invalid syscall)", nib), address + 4);
}
}
void ResolveSyscall(const char *moduleName, u32 nib, u32 address)
{
_dbg_assert_msg_(HLE, moduleName != NULL, "Invalid module name.");
for (size_t i = 0; i < unresolvedSyscalls.size(); i++)
{
Syscall *sysc = &unresolvedSyscalls[i];
@ -196,6 +227,11 @@ void ResolveSyscall(const char *moduleName, u32 nib, u32 address)
Memory::Write_U32(MIPS_MAKE_NOP(), sysc->symAddr + 4);
}
}
Syscall ex = {"", address, nib};
strncpy(ex.moduleName, moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
ex.moduleName[KERNELOBJECT_MAX_NAME_LENGTH] = '\0';
exportedCalls.push_back(ex);
}
const char *GetFuncName(int moduleIndex, int func)

View file

@ -44,6 +44,22 @@ enum {
PSP_THREAD_ATTR_USER = 0x80000000
};
enum {
// Function exports.
NID_MODULE_START = 0xD632ACDB,
NID_MODULE_STOP = 0xCEE8593C,
NID_MODULE_REBOOT_BEFORE = 0x2F064FA6,
NID_MODULE_REBOOT_PHASE = 0xADF12745,
NID_MODULE_BOOTSTART = 0xD3744BE0,
// Variable exports.
NID_MODULE_INFO = 0xF01D73A7,
NID_MODULE_START_THREAD_PARAMETER = 0x0F7C276C,
NID_MODULE_STOP_THREAD_PARAMETER = 0xCF0CC697,
NID_MODULE_REBOOT_BEFORE_THREAD_PARAMETER = 0xF4F4299D,
NID_MODULE_SDK_VERSION = 0x11B97506,
};
static const char *blacklistedModules[] = {
"sceATRAC3plus_Library",
"sceFont_Library",
@ -229,6 +245,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
{
Module *module = new Module;
kernelObjects.Create(module);
memset(&module->nm, 0, sizeof(module->nm));
u8 *newptr = 0;
if (*(u32*)ptr == 0x4543537e) { // "~SCE"
@ -464,8 +481,68 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
{
u32 nid = residentPtr[j];
u32 exportAddr = residentPtr[ent->fcount + ent->vcount + j];
ResolveSyscall(name, nid, exportAddr);
switch (nid)
{
case NID_MODULE_START:
module->nm.module_start_func = exportAddr;
break;
case NID_MODULE_STOP:
module->nm.module_stop_func = exportAddr;
break;
case NID_MODULE_REBOOT_BEFORE:
module->nm.module_reboot_before_func = exportAddr;
break;
case NID_MODULE_REBOOT_PHASE:
module->nm.module_reboot_phase_func = exportAddr;
break;
case NID_MODULE_BOOTSTART:
module->nm.module_bootstart_func = exportAddr;
break;
default:
ResolveSyscall(name, nid, exportAddr);
}
}
for (u32 j = 0; j < ent->vcount; j++)
{
u32 nid = residentPtr[ent->fcount + j];
u32 exportAddr = residentPtr[ent->fcount + ent->vcount + ent->fcount + j];
switch (nid)
{
case NID_MODULE_INFO:
break;
case NID_MODULE_START_THREAD_PARAMETER:
if (Memory::Read_U32(exportAddr) != 3)
WARN_LOG(LOADER, "Strange value at module_start_thread_parameter export: %08x", Memory::Read_U32(exportAddr));
module->nm.module_start_thread_priority = Memory::Read_U32(exportAddr + 4);
module->nm.module_start_thread_stacksize = Memory::Read_U32(exportAddr + 8);
module->nm.module_start_thread_attr = Memory::Read_U32(exportAddr + 12);
break;
case NID_MODULE_STOP_THREAD_PARAMETER:
if (Memory::Read_U32(exportAddr) != 3)
WARN_LOG(LOADER, "Strange value at module_stop_thread_parameter export: %08x", Memory::Read_U32(exportAddr));
module->nm.module_stop_thread_priority = Memory::Read_U32(exportAddr + 4);
module->nm.module_stop_thread_stacksize = Memory::Read_U32(exportAddr + 8);
module->nm.module_stop_thread_attr = Memory::Read_U32(exportAddr + 12);
break;
case NID_MODULE_REBOOT_BEFORE_THREAD_PARAMETER:
if (Memory::Read_U32(exportAddr) != 3)
WARN_LOG(LOADER, "Strange value at module_reboot_before_thread_parameter export: %08x", Memory::Read_U32(exportAddr));
module->nm.module_reboot_before_thread_priority = Memory::Read_U32(exportAddr + 4);
module->nm.module_reboot_before_thread_stacksize = Memory::Read_U32(exportAddr + 8);
module->nm.module_reboot_before_thread_attr = Memory::Read_U32(exportAddr + 12);
break;
case NID_MODULE_SDK_VERSION:
DEBUG_LOG(LOADER, "Module SDK: %08x", Memory::Read_U32(exportAddr));
break;
default:
DEBUG_LOG(LOADER, "Unexpected variable with nid: %08x", nid);
break;
}
}
if (ent->size > 4)
{
ent = (PspLibEntEntry*)((u8*)ent + ent->size * 4);
@ -562,6 +639,12 @@ Module *__KernelLoadModule(u8 *fileptr, SceKernelLMOption *options, std::string
void __KernelStartModule(Module *m, int args, const char *argp, SceKernelSMOption *options)
{
if (m->nm.module_start_func != 0 || m->nm.module_start_func != -1)
{
if (m->nm.module_start_func != m->nm.entry_addr)
WARN_LOG(LOADER, "Main module has start func (%08x) different from entry (%08x)?", m->nm.module_start_func, m->nm.entry_addr);
}
__KernelSetupRootThread(m->GetUID(), args, argp, options->priority, options->stacksize, options->attribute);
mainModuleID = m->GetUID();
//TODO: if current thread, put it in wait state, waiting for the new thread
@ -621,6 +704,14 @@ bool __KernelLoadExec(const char *filename, SceKernelLoadExecParam *param, std::
option.priority = 0x20;
option.stacksize = 0x40000; // crazy? but seems to be the truth
// Replace start options with module-specified values if they exist.
if (module->nm.module_start_thread_attr != 0)
option.attribute = module->nm.module_start_thread_attr;
if (module->nm.module_start_thread_priority != 0)
option.priority = module->nm.module_start_thread_priority;
if (module->nm.module_start_thread_stacksize != 0)
option.stacksize = module->nm.module_start_thread_stacksize;
__KernelStartModule(module, (u32)strlen(filename) + 1, filename, &option);
__KernelStartIdleThreads();