mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-03 03:05:18 +02:00
Merge pull request #6549 from unknownbrackets/modules
Correct some module func return values, info values, and clear on unload
This commit is contained in:
@@ -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>(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>(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<Module>(*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<Module>(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) {
|
||||
|
||||
Reference in New Issue
Block a user