From 9be8be6b7f3d8e5c0fa5e95ffd179b55ae270acf Mon Sep 17 00:00:00 2001 From: Arthur Blot Date: Sun, 4 Nov 2012 19:01:20 +0100 Subject: [PATCH] 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. --- Core/ELF/ElfReader.cpp | 16 +++- Core/ELF/ElfReader.h | 9 ++ Core/HLE/FunctionWrappers.h | 4 + Core/HLE/HLE.cpp | 59 ++++++------ Core/HLE/HLE.h | 8 ++ Core/HLE/sceKernelModule.cpp | 181 +++++++++++++++++++++-------------- 6 files changed, 177 insertions(+), 100 deletions(-) diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index 74b45224fe..f5577aa553 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -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; ie_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) { diff --git a/Core/ELF/ElfReader.h b/Core/ELF/ElfReader.h index 722fd95ab3..1480cb06b9 100644 --- a/Core/ELF/ElfReader.h +++ b/Core/ELF/ElfReader.h @@ -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; } diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 8c56c9c085..c87d6c1a54 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -72,6 +72,10 @@ template void Wrap() { RETURN(retval); } +template void Wrap() { + int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); + RETURN((u32)retval); +} template void Wrap() { int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); RETURN((u32)retval); diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index d8620d805d..0fee6ba38e 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -28,6 +28,7 @@ #include "../MIPS/MIPSCodeUtils.h" static std::vector moduleDB; +static std::vector 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) diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index f76e4a7c4a..cfa8fc58d7 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -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(); diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 9402f2a24a..66b79cf71f 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -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; mentry_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; msize == 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"}, {0xb7f46618,0,"sceKernelLoadModuleByID"}, - {0x50F0C1EC,sceKernelStartModule,"sceKernelStartModule"}, - {0xD675EBB8,sceKernelExitGame,"sceKernelSelfStopUnloadModule"}, //HACK - {0xd1ff982a,sceKernelStopModule,"sceKernelStopModule"}, - {0x2e0911aa,sceKernelUnloadModule,"sceKernelUnloadModule"}, + {0x50F0C1EC,&Wrap,"sceKernelStartModule"}, + {0xD675EBB8,&Wrap,"sceKernelSelfStopUnloadModule"}, //HACK + {0xd1ff982a,&Wrap,"sceKernelStopModule"}, + {0x2e0911aa,&Wrap,"sceKernelUnloadModule"}, {0x710F61B5,0,"sceKernelLoadModuleMs"}, {0xF9275D98,0,"sceKernelLoadModuleBufferUsbWlan"}, ///??? {0xCC1D3699,0,"sceKernelStopUnloadSelfModule"}, {0x748CBED9,0,"sceKernelQueryModuleInfo"}, - {0xd8b73127,sceKernelGetModuleIdByAddress, "sceKernelGetModuleIdByAddress"}, - {0xf0a26395,sceKernelGetModuleId, "sceKernelGetModuleId"}, + {0xd8b73127,&Wrap, "sceKernelGetModuleIdByAddress"}, + {0xf0a26395,&Wrap, "sceKernelGetModuleId"}, {0x8f2df740,0,"sceKernel_ModuleMgr_8f2df740"}, };