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 d95e43eeef..7ee169ef91 100644 --- a/Core/ELF/ElfReader.h +++ b/Core/ELF/ElfReader.h @@ -77,15 +77,13 @@ 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) - { + 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,48 +91,48 @@ 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; } + u32 GetTotalTextSize() const; + u32 GetTotalDataSize() const; + // More indepth stuff:) int LoadInto(u32 vaddr); bool LoadSymbols(); 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) { diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 4eca17b3cf..1651be159e 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" @@ -275,7 +276,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); + } } } @@ -731,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) { @@ -812,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()); @@ -864,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); @@ -890,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 @@ -902,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(); @@ -934,6 +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) { + 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; @@ -952,7 +970,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); } @@ -964,10 +982,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) @@ -980,8 +995,19 @@ 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); + } else { + 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); struct PspLibStubEntry { @@ -1226,6 +1252,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); } } @@ -1280,6 +1309,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; } @@ -1309,6 +1341,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro } } + error = 0; return module; } @@ -1330,7 +1363,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; @@ -1369,7 +1403,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; @@ -1377,8 +1412,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; @@ -1440,6 +1476,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 @@ -1612,28 +1654,36 @@ 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") { 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 + 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) { @@ -1668,6 +1718,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) { @@ -1972,7 +2023,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); } } } @@ -1993,7 +2044,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; @@ -2057,7 +2108,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) { @@ -2065,14 +2116,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) { @@ -2105,21 +2163,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) { 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)