mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Expose PSPModule (so the debugger can access it later)
This commit is contained in:
parent
ce87560c95
commit
644f5e4e6c
9 changed files with 342 additions and 315 deletions
|
@ -66,6 +66,7 @@ typedef struct HWND__ *HWND;
|
||||||
class SymbolMap {
|
class SymbolMap {
|
||||||
public:
|
public:
|
||||||
SymbolMap() {}
|
SymbolMap() {}
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
void SortSymbols();
|
void SortSymbols();
|
||||||
|
|
||||||
|
|
|
@ -92,9 +92,7 @@ struct NativeFPL
|
||||||
};
|
};
|
||||||
|
|
||||||
//FPL - Fixed Length Dynamic Memory Pool - every item has the same length
|
//FPL - Fixed Length Dynamic Memory Pool - every item has the same length
|
||||||
struct FPL : public KernelObject
|
struct FPL : public KernelObject {
|
||||||
{
|
|
||||||
FPL() : blocks(NULL), nextBlock(0) {}
|
|
||||||
~FPL() {
|
~FPL() {
|
||||||
delete [] blocks;
|
delete [] blocks;
|
||||||
}
|
}
|
||||||
|
@ -148,11 +146,11 @@ struct FPL : public KernelObject
|
||||||
Do(p, pausedWaits);
|
Do(p, pausedWaits);
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeFPL nf;
|
NativeFPL nf{};
|
||||||
bool *blocks;
|
bool *blocks = nullptr;
|
||||||
u32 address;
|
u32 address = 0;
|
||||||
int alignedSize;
|
int alignedSize = 0;
|
||||||
int nextBlock;
|
int nextBlock = 0;
|
||||||
std::vector<FplWaitingThread> waitingThreads;
|
std::vector<FplWaitingThread> waitingThreads;
|
||||||
// Key is the callback id it was for, or if no callback, the thread id.
|
// Key is the callback id it was for, or if no callback, the thread id.
|
||||||
std::map<SceUID, FplWaitingThread> pausedWaits;
|
std::map<SceUID, FplWaitingThread> pausedWaits;
|
||||||
|
@ -379,8 +377,7 @@ struct SceKernelVplHeader {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VPL : public KernelObject
|
struct VPL : public KernelObject {
|
||||||
{
|
|
||||||
const char *GetName() override { return nv.name; }
|
const char *GetName() override { return nv.name; }
|
||||||
const char *GetTypeName() override { return GetStaticTypeName(); }
|
const char *GetTypeName() override { return GetStaticTypeName(); }
|
||||||
static const char *GetStaticTypeName() { return "VPL"; }
|
static const char *GetStaticTypeName() { return "VPL"; }
|
||||||
|
@ -410,8 +407,8 @@ struct VPL : public KernelObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SceKernelVplInfo nv;
|
SceKernelVplInfo nv{};
|
||||||
u32 address;
|
u32 address = 0;
|
||||||
std::vector<VplWaitingThread> waitingThreads;
|
std::vector<VplWaitingThread> waitingThreads;
|
||||||
// Key is the callback id it was for, or if no callback, the thread id.
|
// Key is the callback id it was for, or if no callback, the thread id.
|
||||||
std::map<SceUID, VplWaitingThread> pausedWaits;
|
std::map<SceUID, VplWaitingThread> pausedWaits;
|
||||||
|
|
|
@ -134,93 +134,27 @@ static const char * const blacklistedModules[] = {
|
||||||
"sceMemab",
|
"sceMemab",
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WriteVarSymbolState;
|
const char *NativeModuleStatusToString(NativeModuleStatus status) {
|
||||||
|
switch (status) {
|
||||||
struct VarSymbolImport {
|
case MODULE_STATUS_STARTING: return "STARTING";
|
||||||
char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
|
case MODULE_STATUS_STARTED: return "STARTED";
|
||||||
u32 nid;
|
case MODULE_STATUS_STOPPING: return "STOPPING";
|
||||||
u32 stubAddr;
|
case MODULE_STATUS_STOPPED: return "STOPPED";
|
||||||
u8 type;
|
case MODULE_STATUS_UNLOADING: return "UNLOADING";
|
||||||
};
|
default: return "(err)";
|
||||||
|
|
||||||
struct VarSymbolExport {
|
|
||||||
bool Matches(const VarSymbolImport &other) const {
|
|
||||||
return nid == other.nid && !strncmp(moduleName, other.moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
|
static void ImportVarSymbol(WriteVarSymbolState &state, const VarSymbolImport &var);
|
||||||
u32 nid;
|
static void ExportVarSymbol(const VarSymbolExport &var);
|
||||||
u32 symAddr;
|
static void UnexportVarSymbol(const VarSymbolExport &var);
|
||||||
};
|
|
||||||
|
|
||||||
struct FuncSymbolImport {
|
static void ImportFuncSymbol(const FuncSymbolImport &func, bool reimporting, const char *importingModule);
|
||||||
char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
|
static void ExportFuncSymbol(const FuncSymbolExport &func);
|
||||||
u32 stubAddr;
|
static void UnexportFuncSymbol(const FuncSymbolExport &func);
|
||||||
u32 nid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FuncSymbolExport {
|
|
||||||
bool Matches(const FuncSymbolImport &other) const {
|
|
||||||
return nid == other.nid && !strncmp(moduleName, other.moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
|
|
||||||
u32 symAddr;
|
|
||||||
u32 nid;
|
|
||||||
};
|
|
||||||
|
|
||||||
void ImportVarSymbol(WriteVarSymbolState &state, const VarSymbolImport &var);
|
|
||||||
void ExportVarSymbol(const VarSymbolExport &var);
|
|
||||||
void UnexportVarSymbol(const VarSymbolExport &var);
|
|
||||||
|
|
||||||
void ImportFuncSymbol(const FuncSymbolImport &func, bool reimporting, const char *importingModule);
|
|
||||||
void ExportFuncSymbol(const FuncSymbolExport &func);
|
|
||||||
void UnexportFuncSymbol(const FuncSymbolExport &func);
|
|
||||||
|
|
||||||
class PSPModule;
|
|
||||||
static bool KernelImportModuleFuncs(PSPModule *module, u32 *firstImportStubAddr, bool reimporting = false);
|
static bool KernelImportModuleFuncs(PSPModule *module, u32 *firstImportStubAddr, bool reimporting = false);
|
||||||
|
|
||||||
struct NativeModule {
|
|
||||||
u32_le next;
|
|
||||||
u16_le attribute;
|
|
||||||
u8 version[2];
|
|
||||||
char name[28];
|
|
||||||
u32_le status;
|
|
||||||
u32_le unk1;
|
|
||||||
u32_le modid; // 0x2C
|
|
||||||
u32_le usermod_thid;
|
|
||||||
u32_le memid;
|
|
||||||
u32_le mpidtext;
|
|
||||||
u32_le mpiddata;
|
|
||||||
u32_le ent_top;
|
|
||||||
u32_le ent_size;
|
|
||||||
u32_le stub_top;
|
|
||||||
u32_le stub_size;
|
|
||||||
u32_le module_start_func;
|
|
||||||
u32_le module_stop_func;
|
|
||||||
u32_le module_bootstart_func;
|
|
||||||
u32_le module_reboot_before_func;
|
|
||||||
u32_le module_reboot_phase_func;
|
|
||||||
u32_le entry_addr;
|
|
||||||
u32_le gp_value;
|
|
||||||
u32_le text_addr;
|
|
||||||
u32_le text_size;
|
|
||||||
u32_le data_size;
|
|
||||||
u32_le bss_size;
|
|
||||||
u32_le nsegment;
|
|
||||||
u32_le segmentaddr[4];
|
|
||||||
u32_le segmentsize[4];
|
|
||||||
u32_le module_start_thread_priority;
|
|
||||||
u32_le module_start_thread_stacksize;
|
|
||||||
u32_le module_start_thread_attr;
|
|
||||||
u32_le module_stop_thread_priority;
|
|
||||||
u32_le module_stop_thread_stacksize;
|
|
||||||
u32_le module_stop_thread_attr;
|
|
||||||
u32_le module_reboot_before_thread_priority;
|
|
||||||
u32_le module_reboot_before_thread_stacksize;
|
|
||||||
u32_le module_reboot_before_thread_attr;
|
|
||||||
};
|
|
||||||
|
|
||||||
// by QueryModuleInfo
|
// by QueryModuleInfo
|
||||||
struct ModuleInfo {
|
struct ModuleInfo {
|
||||||
SceSize_le size;
|
SceSize_le size;
|
||||||
|
@ -238,26 +172,7 @@ struct ModuleInfo {
|
||||||
char name[28];
|
char name[28];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModuleWaitingThread {
|
PSPModule::~PSPModule() {
|
||||||
SceUID threadID;
|
|
||||||
u32 statusPtr;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum NativeModuleStatus {
|
|
||||||
MODULE_STATUS_STARTING = 4,
|
|
||||||
MODULE_STATUS_STARTED = 5,
|
|
||||||
MODULE_STATUS_STOPPING = 6,
|
|
||||||
MODULE_STATUS_STOPPED = 7,
|
|
||||||
MODULE_STATUS_UNLOADING = 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
class PSPModule : public KernelObject {
|
|
||||||
public:
|
|
||||||
PSPModule() {
|
|
||||||
modulePtr.ptr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
~PSPModule() {
|
|
||||||
if (memoryBlockAddr) {
|
if (memoryBlockAddr) {
|
||||||
// If it's either below user memory, or using a high kernel bit, it's in kernel.
|
// If it's either below user memory, or using a high kernel bit, it's in kernel.
|
||||||
if (memoryBlockAddr < PSP_GetUserMemoryBase() || memoryBlockAddr > PSP_GetUserMemoryEnd()) {
|
if (memoryBlockAddr < PSP_GetUserMemoryBase() || memoryBlockAddr > PSP_GetUserMemoryEnd()) {
|
||||||
|
@ -272,32 +187,13 @@ public:
|
||||||
//Only alloc at kernel memory.
|
//Only alloc at kernel memory.
|
||||||
kernelMemory.Free(modulePtr.ptr);
|
kernelMemory.Free(modulePtr.ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const char *GetName() override { return nm.name; }
|
|
||||||
const char *GetTypeName() override { return GetStaticTypeName(); }
|
|
||||||
static const char *GetStaticTypeName() { return "Module"; }
|
|
||||||
void GetQuickInfo(char *ptr, int size) override {
|
|
||||||
snprintf(ptr, size, "%d.%d %sname=%s gp=%08x entry=%08x",
|
|
||||||
nm.version[1], nm.version[0],
|
|
||||||
isFake ? "(faked) " : "",
|
|
||||||
nm.name,
|
|
||||||
nm.gp_value,
|
|
||||||
nm.entry_addr);
|
|
||||||
}
|
|
||||||
void GetLongInfo(char *ptr, int bufSize) const override;
|
|
||||||
static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MODULE; }
|
|
||||||
static int GetStaticIDType() { return PPSSPP_KERNEL_TMID_Module; }
|
|
||||||
int GetIDType() const override { return PPSSPP_KERNEL_TMID_Module; }
|
|
||||||
|
|
||||||
u32 GetDataAddr() const {
|
u32 PSPModule::GetMissingErrorCode() {
|
||||||
return nm.text_addr + nm.text_size;
|
return SCE_KERNEL_ERROR_UNKNOWN_MODULE;
|
||||||
}
|
}
|
||||||
u32 GetBSSAddr() const {
|
|
||||||
return nm.text_addr + nm.text_size + nm.data_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoState(PointerWrap &p) override
|
void PSPModule::DoState(PointerWrap &p) {
|
||||||
{
|
|
||||||
auto s = p.Section("Module", 1, 6);
|
auto s = p.Section("Module", 1, 6);
|
||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return;
|
||||||
|
@ -343,15 +239,15 @@ public:
|
||||||
Do(p, modulePtr.ptr);
|
Do(p, modulePtr.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleWaitingThread mwt = {0};
|
ModuleWaitingThread mwt = { 0 };
|
||||||
Do(p, waitingThreads, mwt);
|
Do(p, waitingThreads, mwt);
|
||||||
FuncSymbolExport fsx = {{0}};
|
FuncSymbolExport fsx = { {0} };
|
||||||
Do(p, exportedFuncs, fsx);
|
Do(p, exportedFuncs, fsx);
|
||||||
FuncSymbolImport fsi = {{0}};
|
FuncSymbolImport fsi = { {0} };
|
||||||
Do(p, importedFuncs, fsi);
|
Do(p, importedFuncs, fsi);
|
||||||
VarSymbolExport vsx = {{0}};
|
VarSymbolExport vsx = { {0} };
|
||||||
Do(p, exportedVars, vsx);
|
Do(p, exportedVars, vsx);
|
||||||
VarSymbolImport vsi = {{0}};
|
VarSymbolImport vsi = { {0} };
|
||||||
Do(p, importedVars, vsi);
|
Do(p, importedVars, vsi);
|
||||||
|
|
||||||
if (p.mode == p.MODE_READ) {
|
if (p.mode == p.MODE_READ) {
|
||||||
|
@ -377,7 +273,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char moduleName[29] = {0};
|
char moduleName[29] = { 0 };
|
||||||
truncate_cpy(moduleName, nm.name);
|
truncate_cpy(moduleName, nm.name);
|
||||||
if (memoryBlockAddr != 0) {
|
if (memoryBlockAddr != 0) {
|
||||||
g_symbolMap->AddModule(moduleName, memoryBlockAddr, memoryBlockSize);
|
g_symbolMap->AddModule(moduleName, memoryBlockAddr, memoryBlockSize);
|
||||||
|
@ -387,12 +283,9 @@ public:
|
||||||
HLEPlugins::DoState(p);
|
HLEPlugins::DoState(p);
|
||||||
|
|
||||||
RebuildImpExpModuleNames();
|
RebuildImpExpModuleNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't do this in the destructor to avoid annoying messages on game shutdown.
|
void PSPModule::ImportFunc(const FuncSymbolImport &func, bool reimporting) {
|
||||||
void Cleanup();
|
|
||||||
|
|
||||||
void ImportFunc(const FuncSymbolImport &func, bool reimporting) {
|
|
||||||
if (!Memory::IsValidAddress(func.stubAddr)) {
|
if (!Memory::IsValidAddress(func.stubAddr)) {
|
||||||
WARN_LOG_REPORT(Log::Loader, "Invalid address for syscall stub %s %08x", func.moduleName, func.nid);
|
WARN_LOG_REPORT(Log::Loader, "Invalid address for syscall stub %s %08x", func.moduleName, func.nid);
|
||||||
return;
|
return;
|
||||||
|
@ -403,81 +296,47 @@ public:
|
||||||
// Add the symbol to the symbol map for debugging.
|
// Add the symbol to the symbol map for debugging.
|
||||||
char temp[256];
|
char temp[256];
|
||||||
snprintf(temp, sizeof(temp), "zz_%s", GetFuncName(func.moduleName, func.nid));
|
snprintf(temp, sizeof(temp), "zz_%s", GetFuncName(func.moduleName, func.nid));
|
||||||
g_symbolMap->AddFunction(temp,func.stubAddr,8);
|
g_symbolMap->AddFunction(temp, func.stubAddr, 8);
|
||||||
|
|
||||||
// Keep track and actually hook it up if possible.
|
// Keep track and actually hook it up if possible.
|
||||||
importedFuncs.push_back(func);
|
importedFuncs.push_back(func);
|
||||||
impExpModuleNames.insert(func.moduleName);
|
impExpModuleNames.insert(func.moduleName);
|
||||||
ImportFuncSymbol(func, reimporting, GetName());
|
ImportFuncSymbol(func, reimporting, GetName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImportVar(WriteVarSymbolState &state, const VarSymbolImport &var) {
|
void PSPModule::ImportVar(WriteVarSymbolState &state, const VarSymbolImport &var) {
|
||||||
// Keep track and actually hook it up if possible.
|
// Keep track and actually hook it up if possible.
|
||||||
importedVars.push_back(var);
|
importedVars.push_back(var);
|
||||||
impExpModuleNames.insert(var.moduleName);
|
impExpModuleNames.insert(var.moduleName);
|
||||||
ImportVarSymbol(state, var);
|
ImportVarSymbol(state, var);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportFunc(const FuncSymbolExport &func) {
|
void PSPModule::ExportFunc(const FuncSymbolExport &func) {
|
||||||
if (isFake) {
|
if (isFake) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
exportedFuncs.push_back(func);
|
exportedFuncs.push_back(func);
|
||||||
impExpModuleNames.insert(func.moduleName);
|
impExpModuleNames.insert(func.moduleName);
|
||||||
ExportFuncSymbol(func);
|
ExportFuncSymbol(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportVar(const VarSymbolExport &var) {
|
void PSPModule::ExportVar(const VarSymbolExport &var) {
|
||||||
if (isFake) {
|
if (isFake) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
exportedVars.push_back(var);
|
exportedVars.push_back(var);
|
||||||
impExpModuleNames.insert(var.moduleName);
|
impExpModuleNames.insert(var.moduleName);
|
||||||
ExportVarSymbol(var);
|
ExportVarSymbol(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
void PSPModule::GetQuickInfo(char *ptr, int size) {
|
||||||
void RebuildImpExpList(const std::vector<T> &list) {
|
snprintf(ptr, size, "%d.%d %sname=%s gp=%08x entry=%08x",
|
||||||
for (size_t i = 0; i < list.size(); ++i) {
|
nm.version[1], nm.version[0],
|
||||||
impExpModuleNames.insert(list[i].moduleName);
|
isFake ? "(faked) " : "",
|
||||||
}
|
nm.name,
|
||||||
}
|
nm.gp_value,
|
||||||
|
nm.entry_addr);
|
||||||
void RebuildImpExpModuleNames() {
|
}
|
||||||
impExpModuleNames.clear();
|
|
||||||
RebuildImpExpList(exportedFuncs);
|
|
||||||
RebuildImpExpList(importedFuncs);
|
|
||||||
RebuildImpExpList(exportedVars);
|
|
||||||
RebuildImpExpList(importedVars);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImportsOrExportsModuleName(const std::string &moduleName) {
|
|
||||||
return impExpModuleNames.find(moduleName) != impExpModuleNames.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeModule nm{};
|
|
||||||
std::vector<ModuleWaitingThread> waitingThreads;
|
|
||||||
|
|
||||||
std::vector<FuncSymbolExport> exportedFuncs;
|
|
||||||
std::vector<FuncSymbolImport> importedFuncs;
|
|
||||||
std::vector<VarSymbolExport> exportedVars;
|
|
||||||
std::vector<VarSymbolImport> importedVars;
|
|
||||||
std::set<std::string> impExpModuleNames;
|
|
||||||
// Keep track of the code region so we can throw out analysis results
|
|
||||||
// when unloaded.
|
|
||||||
u32 textStart = 0;
|
|
||||||
u32 textEnd = 0;
|
|
||||||
|
|
||||||
// Keep track of the libstub pointers so we can recheck on load state.
|
|
||||||
u32 libstub = 0;
|
|
||||||
u32 libstubend = 0;
|
|
||||||
|
|
||||||
u32 memoryBlockAddr = 0;
|
|
||||||
u32 memoryBlockSize = 0;
|
|
||||||
u32 crc = 0;
|
|
||||||
PSPPointer<NativeModule> modulePtr;
|
|
||||||
bool isFake = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
void PSPModule::GetLongInfo(char *ptr, int bufSize) const {
|
void PSPModule::GetLongInfo(char *ptr, int bufSize) const {
|
||||||
StringWriter w(ptr, bufSize);
|
StringWriter w(ptr, bufSize);
|
||||||
|
|
|
@ -20,7 +20,13 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "Core/HLE/sceKernel.h"
|
#include "Core/HLE/sceKernel.h"
|
||||||
|
#include "Core/MemMap.h"
|
||||||
|
|
||||||
|
class PointerWrap;
|
||||||
|
struct SceKernelSMOption;
|
||||||
|
|
||||||
struct PspModuleInfo {
|
struct PspModuleInfo {
|
||||||
u16_le moduleAttrs; //0x0000 User Mode, 0x1000 Kernel Mode
|
u16_le moduleAttrs; //0x0000 User Mode, 0x1000 Kernel Mode
|
||||||
|
@ -34,8 +40,169 @@ struct PspModuleInfo {
|
||||||
u32_le libstubend; // ptr to end of .lib.stub section
|
u32_le libstubend; // ptr to end of .lib.stub section
|
||||||
};
|
};
|
||||||
|
|
||||||
class PointerWrap;
|
enum NativeModuleStatus {
|
||||||
struct SceKernelSMOption;
|
MODULE_STATUS_STARTING = 4,
|
||||||
|
MODULE_STATUS_STARTED = 5,
|
||||||
|
MODULE_STATUS_STOPPING = 6,
|
||||||
|
MODULE_STATUS_STOPPED = 7,
|
||||||
|
MODULE_STATUS_UNLOADING = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *NativeModuleStatusToString(NativeModuleStatus status);
|
||||||
|
|
||||||
|
struct NativeModule {
|
||||||
|
u32_le next;
|
||||||
|
u16_le attribute;
|
||||||
|
u8 version[2];
|
||||||
|
char name[28];
|
||||||
|
u32_le status;
|
||||||
|
u32_le unk1;
|
||||||
|
u32_le modid; // 0x2C
|
||||||
|
u32_le usermod_thid;
|
||||||
|
u32_le memid;
|
||||||
|
u32_le mpidtext;
|
||||||
|
u32_le mpiddata;
|
||||||
|
u32_le ent_top;
|
||||||
|
u32_le ent_size;
|
||||||
|
u32_le stub_top;
|
||||||
|
u32_le stub_size;
|
||||||
|
u32_le module_start_func;
|
||||||
|
u32_le module_stop_func;
|
||||||
|
u32_le module_bootstart_func;
|
||||||
|
u32_le module_reboot_before_func;
|
||||||
|
u32_le module_reboot_phase_func;
|
||||||
|
u32_le entry_addr;
|
||||||
|
u32_le gp_value;
|
||||||
|
u32_le text_addr;
|
||||||
|
u32_le text_size;
|
||||||
|
u32_le data_size;
|
||||||
|
u32_le bss_size;
|
||||||
|
u32_le nsegment;
|
||||||
|
u32_le segmentaddr[4];
|
||||||
|
u32_le segmentsize[4];
|
||||||
|
u32_le module_start_thread_priority;
|
||||||
|
u32_le module_start_thread_stacksize;
|
||||||
|
u32_le module_start_thread_attr;
|
||||||
|
u32_le module_stop_thread_priority;
|
||||||
|
u32_le module_stop_thread_stacksize;
|
||||||
|
u32_le module_stop_thread_attr;
|
||||||
|
u32_le module_reboot_before_thread_priority;
|
||||||
|
u32_le module_reboot_before_thread_stacksize;
|
||||||
|
u32_le module_reboot_before_thread_attr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VarSymbolImport {
|
||||||
|
char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
|
||||||
|
u32 nid;
|
||||||
|
u32 stubAddr;
|
||||||
|
u8 type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VarSymbolExport {
|
||||||
|
bool Matches(const VarSymbolImport &other) const {
|
||||||
|
return nid == other.nid && !strncmp(moduleName, other.moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
|
||||||
|
u32 nid;
|
||||||
|
u32 symAddr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FuncSymbolImport {
|
||||||
|
char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
|
||||||
|
u32 stubAddr;
|
||||||
|
u32 nid;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FuncSymbolExport {
|
||||||
|
bool Matches(const FuncSymbolImport &other) const {
|
||||||
|
return nid == other.nid && !strncmp(moduleName, other.moduleName, KERNELOBJECT_MAX_NAME_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
char moduleName[KERNELOBJECT_MAX_NAME_LENGTH + 1];
|
||||||
|
u32 symAddr;
|
||||||
|
u32 nid;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WriteVarSymbolState;
|
||||||
|
|
||||||
|
struct ModuleWaitingThread {
|
||||||
|
SceUID threadID;
|
||||||
|
u32 statusPtr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PSPModule : public KernelObject {
|
||||||
|
public:
|
||||||
|
~PSPModule();
|
||||||
|
const char *GetName() override { return nm.name; }
|
||||||
|
const char *GetTypeName() override { return GetStaticTypeName(); }
|
||||||
|
static const char *GetStaticTypeName() { return "Module"; }
|
||||||
|
void GetQuickInfo(char *ptr, int size) override;
|
||||||
|
void GetLongInfo(char *ptr, int bufSize) const override;
|
||||||
|
static u32 GetMissingErrorCode();
|
||||||
|
static int GetStaticIDType() { return PPSSPP_KERNEL_TMID_Module; }
|
||||||
|
int GetIDType() const override { return PPSSPP_KERNEL_TMID_Module; }
|
||||||
|
|
||||||
|
u32 GetDataAddr() const {
|
||||||
|
return nm.text_addr + nm.text_size;
|
||||||
|
}
|
||||||
|
u32 GetBSSAddr() const {
|
||||||
|
return nm.text_addr + nm.text_size + nm.data_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoState(PointerWrap &p) override;
|
||||||
|
|
||||||
|
// We don't do this in the destructor to avoid annoying messages on game shutdown.
|
||||||
|
void Cleanup();
|
||||||
|
|
||||||
|
void ImportFunc(const FuncSymbolImport &func, bool reimporting);
|
||||||
|
void ImportVar(WriteVarSymbolState &state, const VarSymbolImport &var);
|
||||||
|
void ExportFunc(const FuncSymbolExport &func);
|
||||||
|
void ExportVar(const VarSymbolExport &var);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void RebuildImpExpList(const std::vector<T> &list) {
|
||||||
|
for (size_t i = 0; i < list.size(); ++i) {
|
||||||
|
impExpModuleNames.insert(list[i].moduleName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RebuildImpExpModuleNames() {
|
||||||
|
impExpModuleNames.clear();
|
||||||
|
RebuildImpExpList(exportedFuncs);
|
||||||
|
RebuildImpExpList(importedFuncs);
|
||||||
|
RebuildImpExpList(exportedVars);
|
||||||
|
RebuildImpExpList(importedVars);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImportsOrExportsModuleName(const std::string &moduleName) {
|
||||||
|
return impExpModuleNames.find(moduleName) != impExpModuleNames.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeModule nm{};
|
||||||
|
std::vector<ModuleWaitingThread> waitingThreads;
|
||||||
|
|
||||||
|
std::vector<FuncSymbolExport> exportedFuncs;
|
||||||
|
std::vector<FuncSymbolImport> importedFuncs;
|
||||||
|
std::vector<VarSymbolExport> exportedVars;
|
||||||
|
std::vector<VarSymbolImport> importedVars;
|
||||||
|
std::set<std::string> impExpModuleNames;
|
||||||
|
|
||||||
|
// Keep track of the code region so we can throw out analysis results
|
||||||
|
// when unloaded.
|
||||||
|
u32 textStart = 0;
|
||||||
|
u32 textEnd = 0;
|
||||||
|
|
||||||
|
// Keep track of the libstub pointers so we can recheck on load state.
|
||||||
|
u32 libstub = 0;
|
||||||
|
u32 libstubend = 0;
|
||||||
|
|
||||||
|
u32 memoryBlockAddr = 0;
|
||||||
|
u32 memoryBlockSize = 0;
|
||||||
|
u32 crc = 0;
|
||||||
|
PSPPointer<NativeModule> modulePtr{};
|
||||||
|
bool isFake = false;
|
||||||
|
};
|
||||||
|
|
||||||
KernelObject *__KernelModuleObject();
|
KernelObject *__KernelModuleObject();
|
||||||
void __KernelModuleDoState(PointerWrap &p);
|
void __KernelModuleDoState(PointerWrap &p);
|
||||||
|
|
|
@ -86,7 +86,7 @@ const WaitTypeNames waitTypeNames[] = {
|
||||||
{ WAITTYPE_USB, "USB" },
|
{ WAITTYPE_USB, "USB" },
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *getWaitTypeName(WaitType type) {
|
const char *WaitTypeToString(WaitType type) {
|
||||||
for (WaitTypeNames info : waitTypeNames) {
|
for (WaitTypeNames info : waitTypeNames) {
|
||||||
if (info.type == type)
|
if (info.type == type)
|
||||||
return info.name;
|
return info.name;
|
||||||
|
|
|
@ -115,7 +115,7 @@ enum WaitType : int
|
||||||
NUM_WAITTYPES
|
NUM_WAITTYPES
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *getWaitTypeName(WaitType type);
|
const char *WaitTypeToString(WaitType type);
|
||||||
|
|
||||||
// Suspend wait and timeout while a thread enters a callback.
|
// Suspend wait and timeout while a thread enters a callback.
|
||||||
typedef void (* WaitBeginCallbackFunc)(SceUID threadID, SceUID prevCallbackId);
|
typedef void (* WaitBeginCallbackFunc)(SceUID threadID, SceUID prevCallbackId);
|
||||||
|
|
|
@ -406,6 +406,9 @@ inline const u8* GetPointerOrNull(const u32 address) {
|
||||||
// Avoiding a global include for NotifyMemInfo.
|
// Avoiding a global include for NotifyMemInfo.
|
||||||
void PSPPointerNotifyRW(int rw, uint32_t ptr, uint32_t bytes, const char *tag, size_t tagLen);
|
void PSPPointerNotifyRW(int rw, uint32_t ptr, uint32_t bytes, const char *tag, size_t tagLen);
|
||||||
|
|
||||||
|
// TODO: These are actually quite annoying because they can't be followed in the MSVC debugger...
|
||||||
|
// Need to find a solution for that. Can't just change the internal representation though, because
|
||||||
|
// these can be present in PSP-native structs.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct PSPPointer
|
struct PSPPointer
|
||||||
{
|
{
|
||||||
|
|
|
@ -411,7 +411,7 @@ void DrawThreadView(ImConfig &cfg, ImControl &control) {
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::TextUnformatted(ThreadStatusToString(thread.status));
|
ImGui::TextUnformatted(ThreadStatusToString(thread.status));
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::TextUnformatted(getWaitTypeName(thread.waitType));
|
ImGui::TextUnformatted(WaitTypeToString(thread.waitType));
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
char temp[64];
|
char temp[64];
|
||||||
WaitIDToString(thread.waitType, thread.waitID, temp, sizeof(temp));
|
WaitIDToString(thread.waitType, thread.waitID, temp, sizeof(temp));
|
||||||
|
|
|
@ -217,7 +217,7 @@ void CtrlThreadList::GetColumnText(wchar_t* dest, size_t destSize, int row, int
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TL_WAITTYPE:
|
case TL_WAITTYPE:
|
||||||
wcscpy(dest, ConvertUTF8ToWString(getWaitTypeName(threads[row].waitType)).c_str());
|
wcscpy(dest, ConvertUTF8ToWString(WaitTypeToString(threads[row].waitType)).c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue