mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-25 09:09:49 +00:00
Implemented sceKernelLoadModule()
Note that it wasn't tested because all the games I tested had other problems (already implemented modules, encrypted modules, using different functions etc). But code looks good so it'd probably need few (no?) fixes.
This commit is contained in:
parent
6f391515a6
commit
9be8be6b7f
@ -77,6 +77,20 @@ bool ElfReader::LoadInto(u32 vaddr)
|
||||
bRelocate = (header->e_type != ET_EXEC);
|
||||
|
||||
entryPoint = header->e_entry;
|
||||
u32 totalSize = 0;
|
||||
for (int i=0; i<header->e_phnum; i++)
|
||||
{
|
||||
Elf32_Phdr *p = segments + i;
|
||||
if (p->p_type == PT_LOAD && p->p_vaddr + p->p_memsz > totalSize)
|
||||
{
|
||||
totalSize = p->p_vaddr + p->p_memsz;
|
||||
}
|
||||
}
|
||||
if (vaddr)
|
||||
vaddr = userMemory.AllocAt(vaddr, totalSize, "ELF");
|
||||
else
|
||||
vaddr = userMemory.Alloc(totalSize, false, "ELF");
|
||||
|
||||
if (bRelocate)
|
||||
{
|
||||
DEBUG_LOG(LOADER,"Relocatable module");
|
||||
@ -109,8 +123,6 @@ bool ElfReader::LoadInto(u32 vaddr)
|
||||
u32 srcSize = p->p_filesz;
|
||||
u32 dstSize = p->p_memsz;
|
||||
|
||||
userMemory.AllocAt(writeAddr, dstSize, "ELF");
|
||||
|
||||
memcpy(dst, src, srcSize);
|
||||
if (srcSize < dstSize)
|
||||
{
|
||||
|
@ -95,6 +95,15 @@ public:
|
||||
}
|
||||
SectionID GetSectionByName(const char *name, int firstSection=0); //-1 for not found
|
||||
|
||||
u32 GetSegmentPaddr(int segment)
|
||||
{
|
||||
return segments[segment].p_paddr;
|
||||
}
|
||||
u32 GetSegmentOffset(int segment)
|
||||
{
|
||||
return segments[segment].p_offset;
|
||||
}
|
||||
|
||||
bool DidRelocate() {
|
||||
return bRelocate;
|
||||
}
|
||||
|
@ -72,6 +72,10 @@ template<u32 func(int, u32)> void Wrap() {
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
template<u32 func(const char *, u32)> void Wrap() {
|
||||
int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1));
|
||||
RETURN((u32)retval);
|
||||
}
|
||||
template<int func(const char *, u32)> void Wrap() {
|
||||
int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1));
|
||||
RETURN((u32)retval);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "../MIPS/MIPSCodeUtils.h"
|
||||
|
||||
static std::vector<HLEModule> moduleDB;
|
||||
static std::vector<Syscall> unresolvedSyscalls;
|
||||
|
||||
void HLEInit()
|
||||
{
|
||||
@ -39,32 +40,6 @@ void HLEShutdown()
|
||||
moduleDB.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
//unused
|
||||
struct PSPHeader
|
||||
{
|
||||
char psp[4];
|
||||
u32 version; //00080000
|
||||
short whatever; //0101
|
||||
char sometext[28];
|
||||
short whatever2; //0102
|
||||
u32 filesizedecrypted;
|
||||
u32 filesize;
|
||||
u32 unknownoffsets[3];
|
||||
short whatever3[2]; //0x40 0x40
|
||||
u32 whatever4[2]; //00
|
||||
u32 whatever5; //1067008
|
||||
u32 whatever6[2]; //00
|
||||
u32 whatever7; //1067008
|
||||
u32 whatever8; //2553296
|
||||
u32 whatever9[8]; //0
|
||||
u32 whatever10; //12
|
||||
u32 encryptedStuff[12];
|
||||
u32 filesizedecrypted2;
|
||||
u32 whatever11;//0x80
|
||||
u32 whatever12[6];
|
||||
};*/
|
||||
|
||||
void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable)
|
||||
{
|
||||
HLEModule module = {name, numFunctions, funcTable};
|
||||
@ -157,8 +132,36 @@ void WriteSyscall(const char *moduleName, u32 nib, u32 address)
|
||||
Memory::Write_U32(MIPS_MAKE_NOP(), address+4); //patched out?
|
||||
return;
|
||||
}
|
||||
Memory::Write_U32(MIPS_MAKE_JR_RA(), address); // jr ra
|
||||
Memory::Write_U32(GetSyscallOp(moduleName, nib), address + 4);
|
||||
int modindex = GetModuleIndex(moduleName);
|
||||
if (modindex != -1)
|
||||
{
|
||||
Memory::Write_U32(MIPS_MAKE_JR_RA(), address); // jr ra
|
||||
Memory::Write_U32(GetSyscallOp(moduleName, nib), address + 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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';
|
||||
unresolvedSyscalls.push_back(sysc);
|
||||
}
|
||||
}
|
||||
|
||||
void ResolveSyscall(const char *moduleName, u32 nib, u32 address)
|
||||
{
|
||||
for (size_t i = 0; i < unresolvedSyscalls.size(); i++)
|
||||
{
|
||||
Syscall *sysc = &unresolvedSyscalls[i];
|
||||
if (strncmp(sysc->moduleName, moduleName, 32) == 0 && sysc->nid == nib)
|
||||
{
|
||||
INFO_LOG(HLE,"Resolving %s/%08x",moduleName,nib);
|
||||
// Note: doing that, we can't trace external module calls, so maybe something else should be done to debug more efficiently
|
||||
Memory::Write_U32(MIPS_MAKE_JAL(address), sysc->symAddr);
|
||||
Memory::Write_U32(MIPS_MAKE_NOP(), sysc->symAddr + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *GetFuncName(int moduleIndex, int func)
|
||||
|
@ -40,6 +40,13 @@ struct HLEModule
|
||||
const HLEFunction *funcTable;
|
||||
};
|
||||
|
||||
struct Syscall
|
||||
{
|
||||
char moduleName[32];
|
||||
u32 symAddr;
|
||||
u32 nid;
|
||||
};
|
||||
|
||||
#define PARAM(n) currentMIPS->r[4+n]
|
||||
#define RETURN(n) currentMIPS->r[2]=n
|
||||
#define RETURN2(n) currentMIPS->r[3]=n
|
||||
@ -69,6 +76,7 @@ u32 GetNibByName(const char *module, const char *function);
|
||||
u32 GetSyscallOp(const char *module, u32 nib);
|
||||
void WriteSyscall(const char *module, u32 nib, u32 address);
|
||||
void CallSyscall(u32 op);
|
||||
void ResolveSyscall(const char *moduleName, u32 nib, u32 address);
|
||||
|
||||
// Need to be able to save entire kernel state
|
||||
int GetStateSize();
|
||||
|
@ -105,15 +105,14 @@ struct SceKernelSMOption {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// STATE BEGIN
|
||||
static int numLoadedModules;
|
||||
static SceUID mainModuleID; // hack
|
||||
// STATE END
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, SceUID &id, std::string *error_string)
|
||||
Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *error_string)
|
||||
{
|
||||
Module *m = new Module;
|
||||
kernelObjects.Create(m);
|
||||
Module *module = new Module;
|
||||
kernelObjects.Create(module);
|
||||
|
||||
u32 magic = *((u32*)ptr);
|
||||
|
||||
@ -158,17 +157,11 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, SceUID &id, std::
|
||||
u32 __entrytableAddr;
|
||||
};
|
||||
|
||||
SectionID entSection = reader.GetSectionByName(".lib.ent");
|
||||
SectionID textSection = reader.GetSectionByName(".text");
|
||||
|
||||
u32 sceResidentAddr = 0;
|
||||
u32 moduleInfoAddr = 0;
|
||||
u32 textStart = reader.GetSectionAddr(textSection);
|
||||
u32 textSize = reader.GetSectionSize(textSection);
|
||||
|
||||
SectionID sceResidentSection = reader.GetSectionByName(".rodata.sceResident");
|
||||
SectionID sceModuleInfoSection = reader.GetSectionByName(".rodata.sceModuleInfo");
|
||||
|
||||
bool hasSymbols = false;
|
||||
bool dontadd = false;
|
||||
|
||||
@ -186,28 +179,6 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, SceUID &id, std::
|
||||
dontadd = true;
|
||||
}
|
||||
|
||||
if (entSection != -1)
|
||||
{
|
||||
//libent *lib = (libent *)(Memory::GetPointer(reader.GetSectionAddr(entSection)));
|
||||
//what's this for?
|
||||
//lib->l1+=0;
|
||||
}
|
||||
|
||||
sceResidentAddr = reader.GetSectionAddr(sceResidentSection);
|
||||
moduleInfoAddr = reader.GetSectionAddr(sceModuleInfoSection);
|
||||
|
||||
struct PspResidentData
|
||||
{
|
||||
u32 l1; // unknown 0xd632acdb
|
||||
u32 l2; // unknown 0xf01d73a7
|
||||
u32 startAddress; // address of _start
|
||||
u32 moduleInfoAddr; // address of sceModuleInfo struct
|
||||
};
|
||||
|
||||
DEBUG_LOG(LOADER,"Resident data addr: %08x", sceResidentAddr);
|
||||
|
||||
//PspResidentData *resdata = (PspResidentData *)Memory::GetPointer(sceResidentAddr);
|
||||
|
||||
struct PspModuleInfo
|
||||
{
|
||||
// 0, 0, 1, 1 ?
|
||||
@ -222,23 +193,25 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, SceUID &id, std::
|
||||
u32 libstubend; // ptr to end of .lib.stub section
|
||||
};
|
||||
|
||||
PspModuleInfo *modinfo = (PspModuleInfo *)Memory::GetPointer(moduleInfoAddr);
|
||||
m->gp_value = modinfo->gp;
|
||||
strncpy(m->name, modinfo->name, 28); // TODO
|
||||
SectionID sceModuleInfoSection = reader.GetSectionByName(".rodata.sceModuleInfo");
|
||||
PspModuleInfo *modinfo;
|
||||
if (sceModuleInfoSection != -1)
|
||||
modinfo = (PspModuleInfo *)Memory::GetPointer(reader.GetSectionAddr(sceModuleInfoSection));
|
||||
else
|
||||
modinfo = (PspModuleInfo *)reader.GetPtr(reader.GetSegmentPaddr(0) + reader.GetSegmentOffset(0));
|
||||
|
||||
module->gp_value = modinfo->gp;
|
||||
strncpy(module->name, modinfo->name, 28);
|
||||
|
||||
DEBUG_LOG(LOADER,"Module %s: %08x %08x %08x", modinfo->name, modinfo->gp, modinfo->libent,modinfo->libstub);
|
||||
|
||||
struct PspLibStubEntry
|
||||
{
|
||||
// pointer to module name (will be in .rodata.sceResident section)
|
||||
u32 moduleNameSymbol;
|
||||
// mod version??
|
||||
unsigned short version;
|
||||
unsigned short val1;
|
||||
unsigned char val2; // 0x5
|
||||
unsigned char val3;
|
||||
// number of function symbols
|
||||
unsigned short numFuncs;
|
||||
u32 name;
|
||||
u16 version;
|
||||
u16 flags;
|
||||
u16 size;
|
||||
u16 numFuncs;
|
||||
// each symbol has an associated nid; nidData is a pointer
|
||||
// (in .rodata.sceNid section) to an array of longs, one
|
||||
// for each function, which identifies the function whose
|
||||
@ -252,8 +225,6 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, SceUID &id, std::
|
||||
// should be filled in
|
||||
u32 firstSymAddr;
|
||||
};
|
||||
//sceDisplay at 5968-
|
||||
|
||||
|
||||
int numModules = (modinfo->libstubend - modinfo->libstub)/sizeof(PspLibStubEntry);
|
||||
|
||||
@ -265,9 +236,8 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, SceUID &id, std::
|
||||
int numSyms=0;
|
||||
for (int m=0; m<numModules; m++)
|
||||
{
|
||||
const char *modulename = (const char*)Memory::GetPointer(entry[m].moduleNameSymbol);
|
||||
const char *modulename = (const char*)Memory::GetPointer(entry[m].name);
|
||||
u32 *nidDataPtr = (u32*)Memory::GetPointer(entry[m].nidData);
|
||||
//u32 *stubs = (u32*)Memory::GetPointer(entry[m].firstSymAddr);
|
||||
|
||||
DEBUG_LOG(LOADER,"Importing Module %s, stubs at %08x",modulename,entry[m].firstSymAddr);
|
||||
|
||||
@ -288,9 +258,58 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, SceUID &id, std::
|
||||
DEBUG_LOG(LOADER,"-------------------------------------------------------------");
|
||||
}
|
||||
|
||||
m->entry_addr = reader.GetEntryPoint();
|
||||
struct PspLibEntEntry
|
||||
{
|
||||
u32 name; /* ent's name (module name) address */
|
||||
u16 version;
|
||||
u16 flags;
|
||||
u8 size;
|
||||
u8 vcount;
|
||||
u16 fcount;
|
||||
u32 resident;
|
||||
};
|
||||
|
||||
return m;
|
||||
int numEnts = (modinfo->libentend - modinfo->libent)/sizeof(PspLibEntEntry);
|
||||
PspLibEntEntry *ent = (PspLibEntEntry *)Memory::GetPointer(modinfo->libent);
|
||||
for (int m=0; m<numEnts; m++)
|
||||
{
|
||||
const char *name;
|
||||
if (ent->size == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ent->name == 0)
|
||||
{
|
||||
// ?
|
||||
name = module->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = (const char*)Memory::GetPointer(ent->name);
|
||||
}
|
||||
|
||||
INFO_LOG(HLE,"Exporting ent %d named %s, %d funcs, %d vars, resident %08x", m, name, ent->fcount, ent->vcount, ent->resident);
|
||||
u32 *residentPtr = (u32*)Memory::GetPointer(ent[m].resident);
|
||||
for (u32 j = 0; j < ent[m].fcount; j++)
|
||||
{
|
||||
u32 nid = residentPtr[j];
|
||||
u32 exportAddr = residentPtr[ent->fcount + ent->vcount + j];
|
||||
ResolveSyscall(name, nid, exportAddr);
|
||||
}
|
||||
if (ent->size > 4)
|
||||
{
|
||||
ent = (PspLibEntEntry*)((u8*)ent + ent->size * 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
ent++;
|
||||
}
|
||||
}
|
||||
|
||||
module->entry_addr = reader.GetEntryPoint();
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
bool __KernelLoadPBP(const char *filename, std::string *error_string)
|
||||
@ -331,8 +350,7 @@ bool __KernelLoadPBP(const char *filename, std::string *error_string)
|
||||
{
|
||||
u8 *temp = new u8[1024*1024*8];
|
||||
in.read((char*)temp, 1024*1024*8);
|
||||
SceUID id;
|
||||
Module *m = __KernelLoadELFFromPtr(temp, PSP_GetDefaultLoadAddress(), id, error_string);
|
||||
Module *m = __KernelLoadELFFromPtr(temp, PSP_GetDefaultLoadAddress(), error_string);
|
||||
if (!m)
|
||||
return false;
|
||||
mipsr4k.pc = m->entry_addr;
|
||||
@ -343,7 +361,7 @@ bool __KernelLoadPBP(const char *filename, std::string *error_string)
|
||||
}
|
||||
|
||||
|
||||
Module *__KernelLoadModule(u8 *fileptr, SceUID &id, SceKernelLMOption *options, std::string *error_string)
|
||||
Module *__KernelLoadModule(u8 *fileptr, SceKernelLMOption *options, std::string *error_string)
|
||||
{
|
||||
Module *m = 0;
|
||||
// Check for PBP
|
||||
@ -360,11 +378,11 @@ Module *__KernelLoadModule(u8 *fileptr, SceUID &id, SceKernelLMOption *options,
|
||||
offsets[0] = offset0;
|
||||
for (int i = 1; i < numfiles; i++)
|
||||
memcpy(&offsets[i], fileptr + 12 + 4*i, 4);
|
||||
m = __KernelLoadELFFromPtr(fileptr + offsets[5], PSP_GetDefaultLoadAddress(), id, error_string);
|
||||
m = __KernelLoadELFFromPtr(fileptr + offsets[5], PSP_GetDefaultLoadAddress(), error_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
m = __KernelLoadELFFromPtr(fileptr, PSP_GetDefaultLoadAddress(), id, error_string);
|
||||
m = __KernelLoadELFFromPtr(fileptr, PSP_GetDefaultLoadAddress(), error_string);
|
||||
}
|
||||
|
||||
return m;
|
||||
@ -410,8 +428,7 @@ bool __KernelLoadExec(const char *filename, SceKernelLoadExecParam *param, std::
|
||||
|
||||
pspFileSystem.ReadFile(handle, temp, (size_t)size);
|
||||
|
||||
SceUID moduleID;
|
||||
Module *m = __KernelLoadModule(temp, moduleID, 0, error_string);
|
||||
Module *m = __KernelLoadModule(temp, 0, error_string);
|
||||
|
||||
if (!m) {
|
||||
ERROR_LOG(LOADER, "Failed to load module %s", filename);
|
||||
@ -454,10 +471,33 @@ void sceKernelLoadExec()
|
||||
ERROR_LOG(HLE, "sceKernelLoadExec failed: %s", error_string.c_str());
|
||||
}
|
||||
|
||||
void sceKernelLoadModule()
|
||||
u32 sceKernelLoadModule(const char *name, u32 flags)
|
||||
{
|
||||
const char *name = Memory::GetCharPointer(PARAM(0));
|
||||
u32 flags = PARAM(1);
|
||||
PSPFileInfo info = pspFileSystem.GetFileInfo(name);
|
||||
std::string error_string;
|
||||
s64 size = (s64)info.size;
|
||||
if (!size)
|
||||
{
|
||||
ERROR_LOG(LOADER, "Module file is size 0: %s", name);
|
||||
return false;
|
||||
}
|
||||
u32 handle = pspFileSystem.OpenFile(name, FILEACCESS_READ);
|
||||
|
||||
u8 *temp = new u8[(int)size];
|
||||
|
||||
pspFileSystem.ReadFile(handle, temp, (size_t)size);
|
||||
|
||||
Module *m = __KernelLoadELFFromPtr(temp, 0, &error_string);
|
||||
|
||||
if (!m) {
|
||||
ERROR_LOG(LOADER, "Failed to load module %s", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
delete [] temp;
|
||||
|
||||
pspFileSystem.CloseFile(handle);
|
||||
|
||||
if (PARAM(2))
|
||||
{
|
||||
SceKernelLMOption *lmoption= (SceKernelLMOption *)Memory::GetPointer(PARAM(2));
|
||||
@ -467,14 +507,15 @@ void sceKernelLoadModule()
|
||||
//Else, actually do load it and resolve pointers!
|
||||
|
||||
INFO_LOG(HLE,"%i=sceKernelLoadModule(name=%s,flag=%08x,%08x,%08x,%08x,%08x(...))",
|
||||
numLoadedModules+1,name,flags,
|
||||
m->GetUID(),name,flags,
|
||||
lmoption->size,lmoption->mpidtext,lmoption->mpiddata,lmoption->position);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE,"%i=sceKernelLoadModule(name=%s,flag=%08x,(...))", numLoadedModules+1, name, flags);
|
||||
INFO_LOG(HLE,"%i=sceKernelLoadModule(name=%s,flag=%08x,(...))", m->GetUID(), name, flags);
|
||||
}
|
||||
RETURN(++numLoadedModules);
|
||||
|
||||
return m->GetUID();
|
||||
}
|
||||
|
||||
void sceKernelStartModule()
|
||||
@ -528,18 +569,18 @@ u32 sceKernelFindModuleByName(u32)
|
||||
|
||||
const HLEFunction ModuleMgrForUser[] =
|
||||
{
|
||||
{0x977DE386,sceKernelLoadModule,"sceKernelLoadModule"},
|
||||
{0x977DE386,&Wrap<sceKernelLoadModule>,"sceKernelLoadModule"},
|
||||
{0xb7f46618,0,"sceKernelLoadModuleByID"},
|
||||
{0x50F0C1EC,sceKernelStartModule,"sceKernelStartModule"},
|
||||
{0xD675EBB8,sceKernelExitGame,"sceKernelSelfStopUnloadModule"}, //HACK
|
||||
{0xd1ff982a,sceKernelStopModule,"sceKernelStopModule"},
|
||||
{0x2e0911aa,sceKernelUnloadModule,"sceKernelUnloadModule"},
|
||||
{0x50F0C1EC,&Wrap<sceKernelStartModule>,"sceKernelStartModule"},
|
||||
{0xD675EBB8,&Wrap<sceKernelExitGame>,"sceKernelSelfStopUnloadModule"}, //HACK
|
||||
{0xd1ff982a,&Wrap<sceKernelStopModule>,"sceKernelStopModule"},
|
||||
{0x2e0911aa,&Wrap<sceKernelUnloadModule>,"sceKernelUnloadModule"},
|
||||
{0x710F61B5,0,"sceKernelLoadModuleMs"},
|
||||
{0xF9275D98,0,"sceKernelLoadModuleBufferUsbWlan"}, ///???
|
||||
{0xCC1D3699,0,"sceKernelStopUnloadSelfModule"},
|
||||
{0x748CBED9,0,"sceKernelQueryModuleInfo"},
|
||||
{0xd8b73127,sceKernelGetModuleIdByAddress, "sceKernelGetModuleIdByAddress"},
|
||||
{0xf0a26395,sceKernelGetModuleId, "sceKernelGetModuleId"},
|
||||
{0xd8b73127,&Wrap<sceKernelGetModuleIdByAddress>, "sceKernelGetModuleIdByAddress"},
|
||||
{0xf0a26395,&Wrap<sceKernelGetModuleId>, "sceKernelGetModuleId"},
|
||||
{0x8f2df740,0,"sceKernel_ModuleMgr_8f2df740"},
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user