From 399d4d1ba99d9e33a77c59dd8868ccd12b410d9c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Jul 2014 12:35:32 -0700 Subject: [PATCH 01/10] Correct sceKernelModuleStart() return value. --- Core/HLE/sceKernelModule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index aab621b6aa..7722eaba29 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1972,7 +1972,7 @@ void __KernelReturnFromModuleFunc() } else { if (it->statusPtr != 0) Memory::Write_U32(exitStatus, it->statusPtr); - __KernelResumeThreadFromWait(it->threadID, 0); + __KernelResumeThreadFromWait(it->threadID, module->nm.status == MODULE_STATUS_STARTED ? leftModuleID : 0); } } } From 1c7873e2f52c70a36e7b24517f894035b08056fd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Jul 2014 18:23:30 -0700 Subject: [PATCH 02/10] Fill the module info segment addresses and sizes. --- Core/ELF/ElfReader.h | 39 ++++++++++++++++-------------------- Core/HLE/sceKernelModule.cpp | 3 +++ 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/Core/ELF/ElfReader.h b/Core/ELF/ElfReader.h index d95e43eeef..d9052638d1 100644 --- a/Core/ELF/ElfReader.h +++ b/Core/ELF/ElfReader.h @@ -80,12 +80,10 @@ public: int GetNumSegments() { return (int)(header->e_phnum); } int GetNumSections() { return (int)(header->e_shnum); } const char *GetSectionName(int section); - u8 *GetPtr(u32 offset) - { + u8 *GetPtr(u32 offset) const { return (u8*)base + offset; } - u8 *GetSectionDataPtr(int section) - { + u8 *GetSectionDataPtr(int section) const { if (section < 0 || section >= header->e_shnum) return 0; if (sections[section].sh_type != SHT_NOBITS) @@ -93,45 +91,42 @@ public: else return 0; } - u8 *GetSegmentPtr(int segment) - { + u8 *GetSegmentPtr(int segment) const { return GetPtr(segments[segment].p_offset); } - u32 GetSectionAddr(SectionID section) {return sectionAddrs[section];} - int GetSectionSize(SectionID section) - { + u32 GetSectionAddr(SectionID section) const { + return sectionAddrs[section]; + } + int GetSectionSize(SectionID section) const { return sections[section].sh_size; } SectionID GetSectionByName(const char *name, int firstSection=0); //-1 for not found - u32 GetSegmentPaddr(int segment) - { + u32 GetSegmentPaddr(int segment) const { return segments[segment].p_paddr; } - u32 GetSegmentOffset(int segment) - { + u32 GetSegmentOffset(int segment) const { return segments[segment].p_offset; } - u32 GetSegmentVaddr(int segment) - { + u32 GetSegmentVaddr(int segment) const { return segmentVAddr[segment]; } - u32 GetSegmentDataSize(int segment) - { + u32 GetSegmentDataSize(int segment) const { return segments[segment].p_filesz; } + u32 GetSegmentMemSize(int segment) const { + return segments[segment].p_memsz; + } - bool DidRelocate() { + bool DidRelocate() const { return bRelocate; } - u32 GetVaddr() - { + u32 GetVaddr() const { return vaddr; } - u32 GetTotalSize() - { + u32 GetTotalSize() const { return totalSize; } diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 7722eaba29..2590390b3d 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -934,6 +934,8 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro module->nm.data_size = 0; // TODO: Is summing them up correct? Must not be since the numbers aren't exactly right. for (int i = 0; i < reader.GetNumSegments(); ++i) { + module->nm.segmentaddr[i] = reader.GetSegmentVaddr(i); + module->nm.segmentsize[i] = reader.GetSegmentMemSize(i); module->nm.data_size += reader.GetSegmentDataSize(i); } module->nm.gp_value = modinfo->gp; @@ -1668,6 +1670,7 @@ void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValu u32 error; Module *module = kernelObjects.Get(moduleId, error); if (!module) { + INFO_LOG(SCEMODULE, "sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x): error %08x", moduleId, argsize, argAddr, returnValueAddr, optionAddr, error); RETURN(error); return; } else if (module->isFake) { From 4a94a30ba6c794a1581a287586ab87065c98a050 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Jul 2014 19:53:00 -0700 Subject: [PATCH 03/10] Calculate the module info data/text/bss size. --- Core/ELF/ElfReader.cpp | 20 ++++++++++++++++++++ Core/ELF/ElfReader.h | 7 +++++-- Core/HLE/sceKernelModule.cpp | 13 +++++++++---- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index e1fe1c6aaa..25357479ac 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -570,6 +570,26 @@ SectionID ElfReader::GetSectionByName(const char *name, int firstSection) return -1; } +u32 ElfReader::GetTotalTextSize() const { + u32 total = 0; + for (int i = 0; i < GetNumSections(); ++i) { + if (!(sections[i].sh_flags & SHF_WRITE) && (sections[i].sh_flags & SHF_ALLOC)) { + total += sections[i].sh_size; + } + } + return total; +} + +u32 ElfReader::GetTotalDataSize() const { + u32 total = 0; + for (int i = 0; i < GetNumSections(); ++i) { + if ((sections[i].sh_flags & SHF_WRITE) && (sections[i].sh_flags & SHF_ALLOC) && !(sections[i].sh_flags & SHF_MASKPROC)) { + total += sections[i].sh_size; + } + } + return total; +} + bool ElfReader::LoadSymbols() { bool hasSymbols = false; diff --git a/Core/ELF/ElfReader.h b/Core/ELF/ElfReader.h index d9052638d1..7ee169ef91 100644 --- a/Core/ELF/ElfReader.h +++ b/Core/ELF/ElfReader.h @@ -77,8 +77,8 @@ public: u32 GetEntryPoint() { return entryPoint; } u32 GetFlags() { return (u32)(header->e_flags); } - int GetNumSegments() { return (int)(header->e_phnum); } - int GetNumSections() { return (int)(header->e_shnum); } + int GetNumSegments() const { return (int)(header->e_phnum); } + int GetNumSections() const { return (int)(header->e_shnum); } const char *GetSectionName(int section); u8 *GetPtr(u32 offset) const { return (u8*)base + offset; @@ -130,6 +130,9 @@ public: return totalSize; } + u32 GetTotalTextSize() const; + u32 GetTotalDataSize() const; + // More indepth stuff:) int LoadInto(u32 vaddr); bool LoadSymbols(); diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 2590390b3d..e9b816aaf6 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -966,10 +966,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro module->textEnd = module->textStart + textSize; module->nm.text_addr = module->textStart; - // TODO: This value appears to be wrong. In one example, the PSP has a value > 0x1000 bigger. - module->nm.text_size = textSize; - // TODO: It seems like the data size excludes the text size, which kinda makes sense? - module->nm.data_size -= textSize; + module->nm.text_size = reader.GetTotalTextSize(); if (!module->isFake) { #if !defined(MOBILE_DEVICE) @@ -984,6 +981,14 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro } } + SectionID bssSection = reader.GetSectionByName(".bss"); + if (bssSection != -1) { + module->nm.bss_size = reader.GetSectionSize(bssSection); + module->nm.data_size = reader.GetTotalDataSize() - module->nm.bss_size; + } else { + module->nm.data_size = reader.GetTotalDataSize(); + } + INFO_LOG(LOADER, "Module %s: %08x %08x %08x", modinfo->name, modinfo->gp, modinfo->libent, modinfo->libstub); struct PspLibStubEntry { From 729377881c50f402eccdf260343828b3027a215c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Jul 2014 19:58:30 -0700 Subject: [PATCH 04/10] Protect against modules with no start address. Generally, fake ones. --- Core/HLE/sceKernelModule.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index e9b816aaf6..cda4d79870 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -275,7 +275,9 @@ public: if (p.mode == p.MODE_READ) { char moduleName[29] = {0}; strncpy(moduleName, nm.name, ARRAY_SIZE(nm.name)); - symbolMap.AddModule(moduleName, memoryBlockAddr, memoryBlockSize); + if (memoryBlockAddr != 0) { + symbolMap.AddModule(moduleName, memoryBlockAddr, memoryBlockSize); + } } } @@ -954,7 +956,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro } } - if (!module->isFake) { + if (!module->isFake && module->memoryBlockAddr != 0) { symbolMap.AddModule(moduleName, module->memoryBlockAddr, module->memoryBlockSize); } @@ -2001,7 +2003,7 @@ struct GetModuleIdByAddressArg bool __GetModuleIdByAddressIterator(Module *module, GetModuleIdByAddressArg *state) { const u32 start = module->memoryBlockAddr, size = module->memoryBlockSize; - if (start <= state->addr && start + size > state->addr) + if (start != 0 && start <= state->addr && start + size > state->addr) { state->result = module->GetUID(); return false; From ede29179c6ca2467420a9ae996f65fd58c7e512f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Jul 2014 20:04:27 -0700 Subject: [PATCH 05/10] Cleanup remaining modules on loadexec. --- Core/HLE/sceKernelModule.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index cda4d79870..8159b41be1 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1449,6 +1449,12 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str // Wipe kernel here, loadexec should reset the entire system if (__KernelIsRunning()) { + u32 error; + while (!loadedModules.empty()) { + Module *module = kernelObjects.Get(*loadedModules.begin(), error); + module->Cleanup(); + } + Replacement_Shutdown(); __KernelShutdown(); //HLE needs to be reset here @@ -1634,7 +1640,9 @@ u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) if (info.name == "BOOT.BIN") { NOTICE_LOG(LOADER, "Module %s is blacklisted or undecryptable - we try __KernelLoadExec", name); - return __KernelLoadExec(name, 0, &error_string); + // Name might get deleted. + const std::string safeName = name; + return __KernelLoadExec(safeName.c_str(), 0, &error_string); } else { From 292a9ea567992bd781fc6f259ae16067db414827 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Jul 2014 20:25:50 -0700 Subject: [PATCH 06/10] Clear module text and bss on unload. Text is set to break instructions, data/bss to -1. Matches results on a PSP. --- Core/HLE/sceKernelModule.cpp | 16 ++++++++++++++-- Core/HLE/sceKernelThread.cpp | 2 +- Core/MIPS/MIPSCodeUtils.h | 2 +- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 8159b41be1..8b15f2ef93 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -31,6 +31,7 @@ #include "Core/Host.h" #include "Core/MIPS/MIPS.h" #include "Core/MIPS/MIPSAnalyst.h" +#include "Core/MIPS/MIPSCodeUtils.h" #include "Core/ELF/ElfReader.h" #include "Core/ELF/PBPReader.h" #include "Core/ELF/PrxDecrypter.h" @@ -733,6 +734,14 @@ void Module::Cleanup() { for (auto it = exportedFuncs.begin(), end = exportedFuncs.end(); it != end; ++it) { UnexportFuncSymbol(*it); } + + if (memoryBlockAddr != 0 && nm.text_addr != 0 && memoryBlockSize >= nm.data_size + nm.bss_size + nm.text_size) { + DEBUG_LOG(HLE, "Zeroing out module %s memory: %08x - %08x", nm.name, memoryBlockAddr, memoryBlockAddr + memoryBlockSize); + for (u32 i = 0; i < (u32)(nm.text_size + 3); i += 4) { + Memory::Write_U32(MIPS_MAKE_BREAK(1), nm.text_addr + i); + } + Memory::Memset(nm.text_addr + nm.text_size, -1, nm.data_size + nm.bss_size); + } } void __SaveDecryptedEbootToStorageMedia(const u8 *decryptedEbootDataPtr, const u32 length) { @@ -981,15 +990,18 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro } #endif } + } else { + module->nm.text_addr = 0; + module->nm.text_size = 0; } SectionID bssSection = reader.GetSectionByName(".bss"); if (bssSection != -1) { module->nm.bss_size = reader.GetSectionSize(bssSection); - module->nm.data_size = reader.GetTotalDataSize() - module->nm.bss_size; } else { - module->nm.data_size = reader.GetTotalDataSize(); + module->nm.bss_size = 0; } + module->nm.data_size = reader.GetTotalDataSize() - module->nm.bss_size; INFO_LOG(LOADER, "Module %s: %08x %08x %08x", modinfo->name, modinfo->gp, modinfo->libent, modinfo->libstub); diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 4b4e09a8b6..c2cb8c0258 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1153,7 +1153,7 @@ void __KernelThreadingInit() MIPS_MAKE_JR_RA(), //MIPS_MAKE_SYSCALL("ThreadManForUser", "sceKernelDelayThread"), MIPS_MAKE_SYSCALL("FakeSysCalls", "_sceKernelIdle"), - MIPS_MAKE_BREAK(), + MIPS_MAKE_BREAK(0), }; // If you add another func here, don't forget __KernelThreadingDoState() below. diff --git a/Core/MIPS/MIPSCodeUtils.h b/Core/MIPS/MIPSCodeUtils.h index 2ad6309984..06445a615a 100644 --- a/Core/MIPS/MIPSCodeUtils.h +++ b/Core/MIPS/MIPSCodeUtils.h @@ -32,7 +32,7 @@ #define MIPS_MAKE_LUI(reg, immval) (0x3c000000 | ((reg) << 16) | (immval)) #define MIPS_MAKE_LW(rt, rs, immval) (0x8c000000 | ((rs) << 21) | ((rt) << 16) | (immval)) #define MIPS_MAKE_SYSCALL(module, function) GetSyscallOp(module, GetNibByName(module, function)) -#define MIPS_MAKE_BREAK() (13) // ! :) +#define MIPS_MAKE_BREAK(n) (((n) << 6) | 13) // ! :) #define MIPS_GET_OP(op) ((op>>26) & 0x3F) #define MIPS_GET_FUNC(op) (op & 0x3F) From 50402a3d49b336d27d2b6643679faedcbb3e9167 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Jul 2014 20:34:10 -0700 Subject: [PATCH 07/10] Return NOT_YET_LINKED for unlinked module funcs. --- Core/HLE/HLE.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 7ff3ff92f8..17a360de53 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -518,8 +518,10 @@ void CallSyscall(MIPSOpcode op) start = time_now_d(); } const HLEFunction *info = GetSyscallInfo(op); - if (!info) + if (!info) { + RETURN(SCE_KERNEL_ERROR_LIBRARY_NOT_YET_LINKED); return; + } if (info->func) { @@ -530,8 +532,10 @@ void CallSyscall(MIPSOpcode op) else CallSyscallWithoutFlags(info); } - else + else { + RETURN(SCE_KERNEL_ERROR_LIBRARY_NOT_YET_LINKED); ERROR_LOG_REPORT(HLE, "Unimplemented HLE function %s", info->name ? info->name : "(\?\?\?)"); + } if (g_Config.bShowDebugStats) { From 7c4aab3cc22a731f6c5b5f0fa58d316287c9a003 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Jul 2014 21:55:15 -0700 Subject: [PATCH 08/10] Warn on exports from syslib. They don't seem to hook up properly on hardware by the module name. --- Core/HLE/sceKernelModule.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 8b15f2ef93..d265722f4b 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1247,6 +1247,9 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro default: func.nid = nid; func.symAddr = exportAddr; + if (ent->name == NULL) { + WARN_LOG_REPORT(HLE, "Exporting func from syslib export: %08x", nid); + } module->ExportFunc(func); } } @@ -1301,6 +1304,9 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro default: var.nid = nid; var.symAddr = exportAddr; + if (ent->name == NULL) { + WARN_LOG_REPORT(HLE, "Exporting var from syslib export: %08x", nid); + } module->ExportVar(var); break; } From 4ced0e86b1cc6531bd30ee2d5452f68bb8e99d89 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 30 Jun 2014 07:49:15 -0700 Subject: [PATCH 09/10] Return an error code when module load fails. If we're out of memory, we need to tell the game, of course. --- Core/HLE/sceKernelModule.cpp | 70 +++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index d265722f4b..2ee547b68e 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -823,7 +823,7 @@ static bool IsHLEVersionedModule(const char *name) { return false; } -Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *error_string, u32 *magic) { +Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *error_string, u32 *magic, u32 &error) { Module *module = new Module; kernelObjects.Create(module); loadedModules.insert(module->GetUID()); @@ -875,6 +875,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro strncpy(module->nm.name, head->modname, ARRAY_SIZE(module->nm.name)); module->nm.entry_addr = -1; module->nm.gp_value = -1; + error = 0; return module; } else if (ret <= 0) { ERROR_LOG(SCEMODULE, "Failed decrypting PRX! That's not normal! ret = %i\n", ret); @@ -901,6 +902,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro delete [] newptr; module->Cleanup(); kernelObjects.Destroy(module->GetUID()); + error = -1; return 0; } // Open ELF reader @@ -913,6 +915,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro delete [] newptr; module->Cleanup(); kernelObjects.Destroy(module->GetUID()); + error = result; return 0; } module->memoryBlockAddr = reader.GetVaddr(); @@ -1336,6 +1339,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro } } + error = 0; return module; } @@ -1357,7 +1361,8 @@ bool __KernelLoadPBP(const char *filename, std::string *error_string) size_t elfSize; u8 *elfData = pbp.GetSubFile(PBP_EXECUTABLE_PSP, &elfSize); u32 magic; - Module *module = __KernelLoadELFFromPtr(elfData, PSP_GetDefaultLoadAddress(), error_string, &magic); + u32 error; + Module *module = __KernelLoadELFFromPtr(elfData, PSP_GetDefaultLoadAddress(), error_string, &magic, error); if (!module) { delete [] elfData; return false; @@ -1396,7 +1401,8 @@ Module *__KernelLoadModule(u8 *fileptr, SceKernelLMOption *options, std::string INFO_LOG(LOADER, "Elf unaligned, aligning!"); } - module = __KernelLoadELFFromPtr(temp ? temp : fileptr + offsets[5], PSP_GetDefaultLoadAddress(), error_string, &magic); + u32 error; + module = __KernelLoadELFFromPtr(temp ? temp : fileptr + offsets[5], PSP_GetDefaultLoadAddress(), error_string, &magic, error); if (temp) { delete [] temp; @@ -1404,8 +1410,9 @@ Module *__KernelLoadModule(u8 *fileptr, SceKernelLMOption *options, std::string } else { + u32 error; u32 magic = 0; - module = __KernelLoadELFFromPtr(fileptr, PSP_GetDefaultLoadAddress(), error_string, &magic); + module = __KernelLoadELFFromPtr(fileptr, PSP_GetDefaultLoadAddress(), error_string, &magic, error); } return module; @@ -1645,14 +1652,15 @@ u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) u32 handle = pspFileSystem.OpenFile(name, FILEACCESS_READ); pspFileSystem.ReadFile(handle, temp, (size_t)size); u32 magic; - module = __KernelLoadELFFromPtr(temp, 0, &error_string, &magic); + u32 error; + module = __KernelLoadELFFromPtr(temp, 0, &error_string, &magic, error); delete [] temp; pspFileSystem.CloseFile(handle); if (!module) { if (magic == 0x46535000) { ERROR_LOG(LOADER, "Game tried to load an SFO as a module. Go figure? Magic = %08x", magic); - return -1; + return error; } if (info.name == "BOOT.BIN") @@ -1662,13 +1670,18 @@ u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) const std::string safeName = name; return __KernelLoadExec(safeName.c_str(), 0, &error_string); } - else + else if ((int)error >= 0) { // Module was blacklisted or couldn't be decrypted, which means it's a kernel module we don't want to run.. // Let's just act as if it worked. NOTICE_LOG(LOADER, "Module %s is blacklisted or undecryptable - we lie about success", name); return 1; } + else + { + NOTICE_LOG(LOADER, "Module %s failed to load: %08x", name, error); + return error; + } } if (lmoption) { @@ -2093,7 +2106,7 @@ u32 sceKernelLoadModuleByID(u32 id, u32 flags, u32 lmoptionPtr) u8 *temp = new u8[size]; pspFileSystem.ReadFile(handle, temp, size); u32 magic; - module = __KernelLoadELFFromPtr(temp, 0, &error_string, &magic); + module = __KernelLoadELFFromPtr(temp, 0, &error_string, &magic, error); delete [] temp; if (!module) { @@ -2101,14 +2114,21 @@ u32 sceKernelLoadModuleByID(u32 id, u32 flags, u32 lmoptionPtr) // This checks for the SFO magic number. if (magic == 0x46535000) { ERROR_LOG(LOADER, "Game tried to load an SFO as a module. Go figure? Magic = %08x", magic); - return -1; + return error; } - // Module was blacklisted or couldn't be decrypted, which means it's a kernel module we don't want to run. - // Let's just act as if it worked. - - NOTICE_LOG(LOADER, "Module %d is blacklisted or undecryptable - we lie about success", id); - return 1; + if ((int)error >= 0) + { + // Module was blacklisted or couldn't be decrypted, which means it's a kernel module we don't want to run.. + // Let's just act as if it worked. + NOTICE_LOG(LOADER, "Module %d is blacklisted or undecryptable - we lie about success", id); + return 1; + } + else + { + NOTICE_LOG(LOADER, "Module %d failed to load: %08x", id, error); + return error; + } } if (lmoption) { @@ -2141,21 +2161,29 @@ SceUID sceKernelLoadModuleBufferUsbWlan(u32 size, u32 bufPtr, u32 flags, u32 lmo std::string error_string; Module *module = 0; u32 magic; - module = __KernelLoadELFFromPtr(Memory::GetPointer(bufPtr), 0, &error_string, &magic); + u32 error; + module = __KernelLoadELFFromPtr(Memory::GetPointer(bufPtr), 0, &error_string, &magic, error); if (!module) { // Some games try to load strange stuff as PARAM.SFO as modules and expect it to fail. // This checks for the SFO magic number. if (magic == 0x46535000) { ERROR_LOG(LOADER, "Game tried to load an SFO as a module. Go figure? Magic = %08x", magic); - return -1; + return error; } - // Module was blacklisted or couldn't be decrypted, which means it's a kernel module we don't want to run. - // Let's just act as if it worked. - - NOTICE_LOG(LOADER, "Module is blacklisted or undecryptable - we lie about success"); - return 1; + if ((int)error >= 0) + { + // Module was blacklisted or couldn't be decrypted, which means it's a kernel module we don't want to run.. + // Let's just act as if it worked. + NOTICE_LOG(LOADER, "Module is blacklisted or undecryptable - we lie about success"); + return 1; + } + else + { + NOTICE_LOG(LOADER, "Module failed to load: %08x", error); + return error; + } } if (lmoption) { From bddeba59012918da6a05b485f733cc4cb7837d05 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Jul 2014 23:26:47 -0700 Subject: [PATCH 10/10] Add a safety check for lots of segments. --- Core/HLE/sceKernelModule.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 2ee547b68e..89785bdf2d 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -948,8 +948,10 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro module->nm.data_size = 0; // TODO: Is summing them up correct? Must not be since the numbers aren't exactly right. for (int i = 0; i < reader.GetNumSegments(); ++i) { - module->nm.segmentaddr[i] = reader.GetSegmentVaddr(i); - module->nm.segmentsize[i] = reader.GetSegmentMemSize(i); + if (i < (int)ARRAY_SIZE(module->nm.segmentaddr)) { + module->nm.segmentaddr[i] = reader.GetSegmentVaddr(i); + module->nm.segmentsize[i] = reader.GetSegmentMemSize(i); + } module->nm.data_size += reader.GetSegmentDataSize(i); } module->nm.gp_value = modinfo->gp; @@ -968,7 +970,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro } } - if (!module->isFake && module->memoryBlockAddr != 0) { + if (!module->isFake && module->memoryBlockAddr != 0) { symbolMap.AddModule(moduleName, module->memoryBlockAddr, module->memoryBlockSize); }