diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index 942236c68a..93863d7c6d 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -410,8 +410,10 @@ int ElfReader::LoadInto(u32 loadAddress, bool fromTop) for (int i = 0; i < header->e_phnum; i++) { const Elf32_Phdr *p = &segments[i]; if (p->p_type == PT_LOAD) { - if (p->p_vaddr < totalStart) + if (p->p_vaddr < totalStart) { totalStart = p->p_vaddr; + firstSegAlign = p->p_align; + } if (p->p_vaddr + p->p_memsz > totalEnd) totalEnd = p->p_vaddr + p->p_memsz; } @@ -612,6 +614,16 @@ u32 ElfReader::GetTotalTextSize() const { return total; } +u32 ElfReader::GetTotalTextSizeFromSeg() const { + u32 total = 0; + for (int i = 0; i < GetNumSegments(); ++i) { + if ((segments[i].p_flags & PF_X) != 0) { + total += segments[i].p_filesz; + } + } + return total; +} + u32 ElfReader::GetTotalDataSize() const { u32 total = 0; for (int i = 0; i < GetNumSections(); ++i) { diff --git a/Core/ELF/ElfReader.h b/Core/ELF/ElfReader.h index 44d33a8e8e..0284b56bd4 100644 --- a/Core/ELF/ElfReader.h +++ b/Core/ELF/ElfReader.h @@ -114,6 +114,10 @@ public: return segments[segment].p_memsz; } + u32 GetFirstSegmentAlign() const { + return firstSegAlign; + } + bool DidRelocate() const { return bRelocate; } @@ -127,6 +131,7 @@ public: } u32 GetTotalTextSize() const; + u32 GetTotalTextSizeFromSeg() const; u32 GetTotalDataSize() const; u32 GetTotalSectionSizeByPrefix(const std::string &prefix) const; @@ -151,4 +156,5 @@ private: u32 vaddr = 0; u32 segmentVAddr[32]; size_t size_ = 0; + u32 firstSegAlign = 0; }; diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 4952f9be31..be48124fd8 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -168,6 +168,7 @@ struct NativeModule { char name[28]; u32_le status; u32_le unk1; + u32_le modid; // 0x2C u32_le usermod_thid; u32_le memid; u32_le mpidtext; @@ -233,7 +234,7 @@ enum NativeModuleStatus { class PSPModule : public KernelObject { public: - PSPModule() : textStart(0), textEnd(0), libstub(0), libstubend(0), memoryBlockAddr(0), isFake(false) {} + PSPModule() : textStart(0), textEnd(0), libstub(0), libstubend(0), memoryBlockAddr(0), isFake(false), modulePtr(0) {} ~PSPModule() { if (memoryBlockAddr) { // If it's either below user memory, or using a high kernel bit, it's in kernel. @@ -244,6 +245,11 @@ public: } g_symbolMap->UnloadModule(memoryBlockAddr, memoryBlockSize); } + + if (modulePtr) { + //Only alloc at kernel memory. + kernelMemory.Free(modulePtr); + } } const char *GetName() override { return nm.name; } const char *GetTypeName() override { return GetStaticTypeName(); } @@ -263,11 +269,23 @@ public: void DoState(PointerWrap &p) override { - auto s = p.Section("Module", 1, 4); + auto s = p.Section("Module", 1, 5); if (!s) return; - Do(p, nm); + if (s >= 5) { + Do(p, nm); + } else { + char temp[192]; + NativeModule *pnm = &nm; + char *ptemp = temp; + DoArray(p, ptemp, 0xC0); + memcpy(pnm, ptemp, 0x2C); + pnm->modid = GetUID(); + pnm += 0x30; + ptemp += 0x30; + memcpy(pnm, ptemp, 0xC0 - 0x2C); + } Do(p, memoryBlockAddr); Do(p, memoryBlockSize); Do(p, isFake); @@ -290,6 +308,10 @@ public: Do(p, libstubend); } + if (s >= 5) { + Do(p, modulePtr); + } + ModuleWaitingThread mwt = {0}; Do(p, waitingThreads, mwt); FuncSymbolExport fsx = {{0}}; @@ -422,6 +444,7 @@ public: u32 memoryBlockAddr; u32 memoryBlockSize; + u32 modulePtr; bool isFake; }; @@ -1104,6 +1127,8 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load loadedModules.insert(module->GetUID()); memset(&module->nm, 0, sizeof(module->nm)); + module->nm.modid = module->GetUID(); + bool reportedModule = false; u32 devkitVersion = 0; u8 *newptr = 0; @@ -1310,6 +1335,12 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load if (textSection == -1) { module->textStart = reader.GetVaddr(); module->textEnd = firstImportStubAddr - 4; + // Reference Jpcsp. + if (reader.GetFirstSegmentAlign() > 0) + module->textStart &= ~(reader.GetFirstSegmentAlign() - 1); + // PSP set these values even if no section. + module->nm.text_addr = module->textStart; + module->nm.text_size = reader.GetTotalTextSizeFromSeg(); } if (!module->isFake) { @@ -1540,6 +1571,15 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load } } + u32 moduleSize = sizeof(module->nm); + char tag[32]; + snprintf(tag, sizeof(tag), "SceModule-%d", module->nm.modid); + module->modulePtr = kernelMemory.Alloc(moduleSize, true, tag); + + // Fill the struct. + if (Memory::IsValidAddress(module->modulePtr)) + Memory::WriteStruct(module->modulePtr, &module->nm); + error = 0; return module; } @@ -1896,6 +1936,15 @@ u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) { module->nm.entry_addr = -1; module->nm.gp_value = -1; + u32 moduleSize = sizeof(module->nm); + char tag[32]; + snprintf(tag, sizeof(tag), "SceModule-%d", module->nm.modid); + module->modulePtr = kernelMemory.Alloc(moduleSize, true, tag); + + // Fill the struct. + if(Memory::IsValidAddress(module->modulePtr)) + Memory::WriteStruct(module->modulePtr, &module->nm); + // TODO: It would be more ideal to allocate memory for this module. return hleLogSuccessInfoI(LOADER, module->GetUID(), "created fake module"); @@ -2367,16 +2416,30 @@ static u32 sceKernelGetModuleId() u32 sceKernelFindModuleByUID(u32 uid) { - ERROR_LOG(SCEMODULE, "UNIMPL sceKernelFindModuleByUID(%d)", uid); - return 0; + u32 error; + PSPModule *module = kernelObjects.Get(uid, error); + if (!module || module->isFake) { + ERROR_LOG(SCEMODULE, "0 = sceKernelFindModuleByUID(%d): Module Not Found or Fake", uid); + return 0; + } + INFO_LOG(SCEMODULE, "sceKernelFindModuleByUID(%d)", uid); + return module->modulePtr; } u32 sceKernelFindModuleByName(const char *name) { - int index = GetModuleIndex(name); - u32 temp = index + 1; - INFO_LOG(SCEMODULE, "%d = sceKernelFindModuleByName(%s)", temp, name); - return temp; + u32 error; + for (SceUID moduleId : loadedModules) { + PSPModule *module = kernelObjects.Get(moduleId, error); + if (!module) + continue; + if (!module->isFake && strcmp(name, module->nm.name) == 0) { + INFO_LOG(SCEMODULE, "%d = sceKernelFindModuleByName(%s)", module->modulePtr, name); + return module->modulePtr; + } + } + WARN_LOG(SCEMODULE, "0 = sceKernelFindModuleByName(%s): Module Not Found or Fake", name); + return 0; } static u32 sceKernelLoadModuleByID(u32 id, u32 flags, u32 lmoptionPtr)