Seregon/ShadPKG

A tool for deriving PKG packet encryption keys for ps4 written in c++

C++/47.3 KB/No license
core/decompiler/lifter/VariableAnalysis.h
ShadPKG / core / decompiler / lifter / VariableAnalysis.h
1#pragma once
2 
3#include "../ir/AST.h"
4#include "../ir/IR.h"
5#include <map>
6#include <memory>
7#include <set>
8#include <tuple>
9 
10namespace ShadPKG::Decompiler::Lifter {
11 
12// ╔═══════════════════════════════════════════════════════════════════════════╗
13// ║ VARIABLE ANALYSIS ║
14// ║ ║
15// ║ Scans the function for stack frame accesses (RBP/RSP based). ║
16// ║ Creates named LocalVariables (var_4, var_8). ║
17// ║ Replaces low-level Memory Expressions with higher-level Variable
18// Expressions.║
19// ╚═══════════════════════════════════════════════════════════════════════════╝
20 
21class VariableAnalysis {
22public:
23 explicit VariableAnalysis(std::shared_ptr<IR::Function> func);
24 
25 // ═══════════════════════════════════════════════════════════════════════
26 // Main Analysis
27 // ═══════════════════════════════════════════════════════════════════════
28 
29 void analyze();
30 
31 // ═══════════════════════════════════════════════════════════════════════
32 // Lifting
33 // ═══════════════════════════════════════════════════════════════════════
34 
35 // Updates the FunctionAST with detected locals and parameters
36 void applyToAST(std::shared_ptr<AST::FunctionAST> ast);
37 
38 // Inferred Signature
39 const std::vector<AST::LocalVariable> &getDetectedParams() const {
40 return detectedParams_;
41 }
42 std::string getInferredReturnType() const { return inferredReturnType_; }
43 std::string getParamForRegister(uint64_t regId) const;
44 
45 // ═══════════════════════════════════════════════════════════════════════
46 // SSA Register Tracking - converts registers to temp variables
47 // ═══════════════════════════════════════════════════════════════════════
48 
49 // Get temp name for a register at a given instruction address
50 // Returns empty if not tracked (use register name as fallback)
51 std::string getTempForRegister(uint64_t regId, uint64_t instrAddr) const;
52 
53 // Track a new definition of a register at an instruction address
54 void trackRegisterDef(uint64_t regId, uint64_t instrAddr);
55 
56 // Resolves a memory operand to a variable name if possible
57 // Returns empty string if not a known variable
58 std::string resolveVariable(const IR::Operand &op);
59 
60private:
61 std::shared_ptr<IR::Function> func_;
62 
63 // Stack Offset -> LocalVariable
64 // Offset is usually negative for locals (rbp - x) and positive for args (rbp
65 // + x)
66 std::map<int, AST::LocalVariable> stackVariables_;
67 std::vector<AST::LocalVariable> detectedParams_;
68 std::string inferredReturnType_ = "void";
69 
70 // Registers used for passing arguments (System V AMD64 ABI)
71 // RDI, RSI, RDX, RCX, R8, R9
72 std::map<uint64_t, int> registerParams_; // RegID -> ParamIndex
73 std::set<uint64_t> assignedRegisters_; // To detect use-before-def
74 std::map<uint64_t, std::string> regToParam_;
75 
76 // ═══════════════════════════════════════════════════════════════════════
77 // SSA Tracking: {register, def_addr} -> temp_N
78 // ═══════════════════════════════════════════════════════════════════════
79 struct RegDef {
80 uint64_t regId;
81 uint64_t defAddr;
82 bool operator<(const RegDef &o) const {
83 return std::tie(regId, defAddr) < std::tie(o.regId, o.defAddr);
84 }
85 };
86 std::map<RegDef, std::string> ssaTemps_;
87 int nextTempId_ = 0;
88 
89 void scanInstruction(const IR::Instruction &instr);
90 void createVariable(int offset, int size, bool isParam);
91};
92 
93} // namespace ShadPKG::Decompiler::Lifter
94