mirror of
https://github.com/ran-j/PS2Recomp.git
synced 2026-09-26 08:51:05 -04:00
7562ec14c9
* feat: modularize elf analyzer feat: added experimental sce symbol scanner feat: change analyzer order feat: small optimizations on analyzer * feat: remove example_config.toml because its causing confusion on some people * feat: embed sce symbol but leave optional import path feat: killed skip function on analyzer but leave it so you can skip manual if you want * feat: pin elfio tag * feat: manually create string view with size * feat: update ghidra script
155 lines
6.0 KiB
C++
155 lines
6.0 KiB
C++
#ifndef PS2RECOMP_ELF_ANALYZER_H
|
|
#define PS2RECOMP_ELF_ANALYZER_H
|
|
|
|
#include "ps2recomp/elf_analysis_context.h"
|
|
#include "ps2recomp/function_classifier.h"
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <unordered_set>
|
|
#include <unordered_map>
|
|
#include <memory>
|
|
#include <map>
|
|
#include <set>
|
|
#include <functional>
|
|
#include <cstdint>
|
|
|
|
namespace ps2recomp
|
|
{
|
|
struct CFGNode;
|
|
struct Instruction;
|
|
struct FunctionCall;
|
|
struct JumpTable;
|
|
struct Relocation;
|
|
struct Section;
|
|
struct Symbol;
|
|
struct Function;
|
|
class R5900Decoder;
|
|
class ElfParser;
|
|
|
|
using CFG = std::unordered_map<uint32_t, CFGNode>;
|
|
|
|
class ElfAnalyzer
|
|
{
|
|
public:
|
|
explicit ElfAnalyzer(const std::string &elfPath);
|
|
~ElfAnalyzer();
|
|
|
|
public:
|
|
void setSceSymbolDatabasePath(const std::string &databasePath);
|
|
bool analyze();
|
|
bool generateToml(const std::string &outputPath);
|
|
bool importGhidraMap(const std::string &csvPath);
|
|
|
|
public:
|
|
const std::vector<Function> &getFunctions() const;
|
|
|
|
public:
|
|
bool isLibrarySymbolNameForHeuristics(const std::string &name) const;
|
|
static bool isReliableSymbolNameForHeuristics(const std::string &name);
|
|
|
|
public:
|
|
static int findEntryFunctionIndexForHeuristics(const std::vector<Function> &functions, uint32_t entryAddress);
|
|
static int findFallbackEntryFunctionIndexForHeuristics(const std::vector<Function> &functions);
|
|
|
|
public:
|
|
static bool hasHardwareIOSignalForHeuristics(const std::vector<Instruction> &instructions);
|
|
static bool hasLargeComplexMMISignalForHeuristics(const std::vector<Instruction> &instructions, size_t largeInstructionThreshold = 500);
|
|
static bool hasSelfModifyingSignalForHeuristics(const std::vector<Instruction> &instructions, const std::vector<Section> §ions);
|
|
|
|
public:
|
|
static std::vector<JumpTable> detectJumpTablesForHeuristics(const std::vector<Instruction> &instructions, const std::vector<Section> §ions, const std::function<bool(uint32_t, uint32_t &)> &readWord);
|
|
static std::unordered_set<std::string> findRecursiveFunctionsForHeuristics(const std::unordered_map<std::string, std::vector<std::string>> &callGraph);
|
|
|
|
private:
|
|
std::string m_elfPath;
|
|
std::unique_ptr<ElfParser> m_elfParser;
|
|
std::unique_ptr<R5900Decoder> m_decoder;
|
|
|
|
ElfAnalysisContext m_context;
|
|
|
|
std::unordered_set<std::string> m_libFunctions;
|
|
std::unordered_set<std::string> m_untrackedStubFunctions;
|
|
std::unordered_set<uint32_t> m_forceRecompileStarts;
|
|
std::unordered_set<std::string> m_sceSdkFunctionNames;
|
|
|
|
FunctionClassifier m_classifier;
|
|
|
|
std::unordered_map<std::string, std::set<std::string>> m_functionDataUsage;
|
|
std::unordered_map<uint32_t, std::string> m_commonDataAccess;
|
|
|
|
std::map<uint32_t, uint32_t> m_patches;
|
|
std::map<uint32_t, std::string> m_patchReasons;
|
|
|
|
std::unordered_map<uint32_t, CFG> m_functionCFGs;
|
|
std::vector<JumpTable> m_jumpTables;
|
|
std::unordered_map<uint32_t, std::vector<FunctionCall>> m_functionCalls;
|
|
std::map<uint32_t, std::string> m_performanceCriticalReasons;
|
|
|
|
std::unordered_map<uint32_t, uint32_t> m_mmioByInstructionAddress;
|
|
|
|
std::string m_sceSymbolDatabasePath;
|
|
|
|
bool loadElf();
|
|
void buildFunctionIndex();
|
|
void decodeAllFunctionsOnce();
|
|
void classifyFunctions();
|
|
void runDataUsagePass();
|
|
void runPatchDetectionPass();
|
|
void runControlFlowPass();
|
|
void runJumpTablePass();
|
|
void runPerformancePass();
|
|
void runSignaturePass() const;
|
|
void printAnalysisSummary() const;
|
|
|
|
void discoverSceSdkSymbols();
|
|
void analyzeEntryPoint();
|
|
void analyzeLibraryFunctions();
|
|
void analyzeDataUsage();
|
|
|
|
void identifyPotentialPatches();
|
|
bool tryPatchSelfModifyingStore(const Function &func,
|
|
const std::vector<Instruction> &instructions,
|
|
size_t index);
|
|
bool tryResolveBasePlusOffset(const std::vector<Instruction> &instructions,
|
|
size_t index,
|
|
uint32_t reg,
|
|
int16_t offset,
|
|
uint32_t &baseAddr) const;
|
|
bool tryResolveLuiBase(const std::vector<Instruction> &instructions,
|
|
size_t index,
|
|
uint32_t reg,
|
|
uint32_t &baseAddr) const;
|
|
bool isCodeAddress(uint32_t addr) const;
|
|
|
|
void analyzeControlFlow();
|
|
void detectJumpTables();
|
|
void analyzePerformanceCriticalPaths();
|
|
void identifyRecursiveFunctions();
|
|
void analyzeRegisterUsage() const;
|
|
void analyzeFunctionSignatures() const;
|
|
void optimizePatches();
|
|
|
|
bool identifyMemcpyPattern(const Function &func) const;
|
|
bool identifyMemsetPattern(const Function &func) const;
|
|
bool identifyStringOperationPattern(const Function &func) const;
|
|
bool identifyMathPattern(const Function &func) const;
|
|
|
|
bool isLibraryFunction(const std::string &name) const;
|
|
void clearDecodedInstructionCache();
|
|
const std::vector<Instruction> &getDecodedInstructions(const Function &function) const;
|
|
std::vector<Instruction> decodeFunction(const Function &function) const;
|
|
CFG buildCFG(const Function &function) const;
|
|
std::string formatAddress(uint32_t address) const;
|
|
bool hasMMIInstructions(const Function &function) const;
|
|
bool hasVUInstructions(const Function &function) const;
|
|
void identifyFunctionType(const Function &function) const;
|
|
void categorizeFunction(Function &function);
|
|
uint32_t getSuccessor(const Instruction &inst, uint32_t currentAddr);
|
|
bool isSelfModifyingCode(const Function &function) const;
|
|
bool isLoopHeavyFunction(const Function &function) const;
|
|
};
|
|
}
|
|
|
|
#endif // PS2RECOMP_ELF_ANALYZER_H
|