Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ps2xAnalyzer/include/ps2recomp/elf_analyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace ps2recomp
static bool isReliableSymbolNameForHeuristics(const std::string &name);
static bool isSystemSymbolNameForHeuristics(const std::string &name);
static bool shouldAutoSkipNameForHeuristics(const std::string &name);
static bool shouldSkipSystemSymbolForHeuristics(const std::string &name, const std::unordered_set<std::string> &forcedRecompileNames);
static int findEntryFunctionIndexForHeuristics(const std::vector<Function> &functions, uint32_t entryAddress);
static int findFallbackEntryFunctionIndexForHeuristics(const std::vector<Function> &functions);
static bool hasHardwareIOSignalForHeuristics(const std::vector<Instruction> &instructions);
Expand Down
56 changes: 53 additions & 3 deletions ps2xAnalyzer/src/elf_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace ps2recomp
static bool hasPs2ApiPrefix(const std::string &name);
static bool hasReliableSymbolName(const std::string &name);
static bool isDoNotSkipOrStub(const std::string &name);
static bool matchesKernelRuntimeName(const std::string &name);
static uint32_t decodeAbsoluteJumpTarget(uint32_t instructionAddress, uint32_t targetField);
static bool tryReadWord(const ElfParser *parser, uint32_t address, uint32_t &outWord);

Expand Down Expand Up @@ -444,6 +445,16 @@ namespace ps2recomp

void ElfAnalyzer::analyzeLibraryFunctions()
{
std::unordered_set<std::string> forcedRecompileNames;
forcedRecompileNames.reserve(m_forceRecompileStarts.size());
for (const auto &func : m_functions)
{
if (m_forceRecompileStarts.contains(func.start))
{
forcedRecompileNames.insert(func.name);
}
}

for (const auto &symbol : m_symbols)
{
if (symbol.isFunction)
Expand All @@ -457,7 +468,7 @@ namespace ps2recomp
{
m_libFunctions.insert(symbol.name);
}
else if (isSystemFunction(symbol.name))
else if (shouldSkipSystemSymbolForHeuristics(symbol.name, forcedRecompileNames))
{
m_skipFunctions.insert(symbol.name);
}
Expand All @@ -475,7 +486,7 @@ namespace ps2recomp
{
m_libFunctions.insert(func.name);
}
else if (isSystemFunction(func.name))
else if (shouldSkipSystemSymbolForHeuristics(func.name, forcedRecompileNames))
{
m_skipFunctions.insert(func.name);
}
Expand Down Expand Up @@ -1606,6 +1617,10 @@ namespace ps2recomp
if (funcIt != m_functions.end())
{
const Function &func = *funcIt;
if (m_forceRecompileStarts.contains(func.start))
{
continue;
}

if (patchAddrs.size() > 3)
{
Expand Down Expand Up @@ -2032,6 +2047,18 @@ namespace ps2recomp
return false;
}

static bool matchesKernelRuntimeName(const std::string &name)
{
if (name.empty())
{
return false;
}

static const std::regex kernelRuntimePattern(
"^(?:(?:Create|Delete|Start|ExitDelete|Exit|Terminate|Suspend|Resume|Sleep|Wakeup|CancelWakeup|Change|Rotate|Release|Setup|Register|Query|Get|Set|Refer|Poll|Wait|Signal|Enable|Disable|Flush|Reset|Add|Init)(?:Thread|Sema|EventFlag|Alarm|Intc|IntcHandler2|Dmac|DmacHandler2|OsdConfigParam|MemorySize|VSyncFlag|Heap|TLS|Status|Cache|Syscall|TLB|TLBEntry|GsCrt)|EndOfHeap|GsGetIMR|GsPutIMR|Deci2Call|Sif[A-Za-z0-9_]+|i(?:SignalSema|PollSema|ReferSemaStatus|SetEventFlag|ClearEventFlag|PollEventFlag|ReferEventFlagStatus|WakeupThread|CancelWakeupThread|ReleaseWaitThread|SetAlarm|CancelAlarm|FlushCache|sceSifSetDma|sceSifSetDChain))$");
return std::regex_match(name, kernelRuntimePattern);
}

static bool isDoNotSkipOrStub(const std::string &name)
{
static const std::unordered_set<std::string> kDoNotSkipOrStub = {
Expand Down Expand Up @@ -2131,6 +2158,17 @@ namespace ps2recomp
return isSystemSymbolNameForHeuristics(name);
}

bool ElfAnalyzer::shouldSkipSystemSymbolForHeuristics(
const std::string &name,
const std::unordered_set<std::string> &forcedRecompileNames)
{
if (forcedRecompileNames.contains(name))
{
return false;
}
return isSystemSymbolNameForHeuristics(name);
}

bool ElfAnalyzer::isSystemFunction(const std::string &name) const
{
return isSystemSymbolNameForHeuristics(name);
Expand All @@ -2144,15 +2182,27 @@ namespace ps2recomp
if (!hasReliableSymbolName(name))
return false;

std::string normalizedName = name;
if (normalizedName[0] == '_' && normalizedName.size() > 1)
{
normalizedName = normalizedName.substr(1);
}

if (matchesKernelRuntimeName(normalizedName))
return true;

if (m_knownLibNames.find(name) != m_knownLibNames.end())
return true;

if (m_knownLibNames.find(normalizedName) != m_knownLibNames.end())
return true;

if (hasPs2ApiPrefix(name))
return true;

// Check for common C/C++ library function names
static const std::regex cLibPattern("^_*(mem|str|time|f?printf|f?scanf|malloc|free|calloc|realloc|atoi|itoa|rand|srand|abort|exit|atexit|getenv|system|bsearch|qsort|abs|labs|div|ldiv|mblen|mbtowc|wctomb|mbstowcs|wcstombs).*");
if (std::regex_match(name, cLibPattern))
if (std::regex_match(normalizedName, cLibPattern))
{
return true;
}
Expand Down
3 changes: 3 additions & 0 deletions ps2xRecomp/include/ps2recomp/code_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
namespace ps2recomp
{
struct JumpTableEntry;
struct JumpTable;
struct Instruction;
struct Function;
struct Symbol;
Expand Down Expand Up @@ -47,6 +48,7 @@ namespace ps2recomp
void setRenamedFunctions(const std::unordered_map<uint32_t, std::string> &renames);
void setBootstrapInfo(const BootstrapInfo &info);
void setRelocationCallNames(const std::unordered_map<uint32_t, std::string> &callNames);
void setConfiguredJumpTables(const std::vector<JumpTable> &jumpTables);

AnalysisResult collectInternalBranchTargets(const Function &function,
const std::vector<Instruction> &instructions);
Expand All @@ -55,6 +57,7 @@ namespace ps2recomp
std::unordered_map<uint32_t, Symbol> m_symbols;
std::unordered_map<uint32_t, std::string> m_renamedFunctions;
std::unordered_map<uint32_t, std::string> m_relocationCallNames;
std::unordered_map<uint32_t, std::vector<uint32_t>> m_configJumpTableTargetsByAddress;
const std::vector<Section>& m_sections;
BootstrapInfo m_bootstrapInfo;

Expand Down
3 changes: 3 additions & 0 deletions ps2xRecomp/include/ps2recomp/ps2_recompiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ namespace ps2recomp
std::vector<Function> &functions,
std::unordered_map<uint32_t, std::vector<Instruction>> &decodedFunctions);

static std::string ClampFilenameLength(const std::string& baseName, const std::string& extension, std::size_t maxLength);

private:
ConfigManager m_configManager;
std::unique_ptr<ElfParser> m_elfParser;
Expand Down Expand Up @@ -70,6 +72,7 @@ namespace ps2recomp
bool generateStubHeader();
bool writeToFile(const std::string &path, const std::string &content);
std::filesystem::path getOutputPath(const Function &function) const;
static std::string clampFilenameLength(const std::string& baseName, const std::string& extension, std::size_t maxLength);
std::string sanitizeFunctionName(const std::string &name) const;
};

Expand Down
1 change: 1 addition & 0 deletions ps2xRecomp/include/ps2recomp/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ namespace ps2recomp
std::unordered_map<uint32_t, std::string> patches;
std::vector<std::string> stubImplementations;
std::unordered_map<uint32_t, uint32_t> mmioByInstructionAddress;
std::vector<JumpTable> jumpTables;
};

} // namespace ps2recomp
Expand Down
Loading