Seregon/ShadPKG

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

C++/47.3 KB/No license
core/decompiler/analysis/LoopCorrector.h
ShadPKG / core / decompiler / analysis / LoopCorrector.h
1#pragma once
2 
3#include "../ir/AST.h"
4#include "../ir/IR.h"
5#include <memory>
6#include <set>
7#include <string>
8 
9namespace ShadPKG::Decompiler::Analysis {
10 
11// ╔═══════════════════════════════════════════════════════════════════════════╗
12// ║ LOOP CORRECTOR ║
13// ║ ║
14// ║ Detects and fixes malformed infinite loops in decompiled code: ║
15// ║ - Pattern: (reg_x == reg_x) -> always true ║
16// ║ - Pattern: register walking loops without proper terminators ║
17// ║ - Pattern: NULL/0xFFFFFFFFFFFFFFFF pointer terminators ║
18// ║ ║
19// ║ Common Issues: ║
20// ║ 1. Loop condition is a tautology (e.g., reg_rax == reg_rax) ║
21// ║ 2. Loop has no bounds check before dereference ║
22// ║ 3. Loop should terminate on NULL or sentinel value ║
23// ║ ║
24// ║ Strategies: ║
25// ║ - Replace with bounded pointer walk (check NULL or 0xffffffff) ║
26// ║ - Add safety counter to prevent runaway loops ║
27// ║ - Generate proper termination checks ║
28// ╚═══════════════════════════════════════════════════════════════════════════╝
29 
30class LoopCorrector {
31public:
32 // Analyze and correct a while loop statement
33 static std::shared_ptr<AST::Statement>
34 correctWhileLoop(const std::shared_ptr<AST::WhileStatement> &whileStmt,
35 const std::shared_ptr<IR::BasicBlock> &headerBB);
36 
37 // Analyze and correct a do-while loop statement
38 static std::shared_ptr<AST::Statement>
39 correctDoWhileLoop(const std::shared_ptr<AST::DoWhileStatement> &doWhileStmt,
40 const std::shared_ptr<IR::BasicBlock> &latchBB);
41 
42 // Check if a condition is a tautology (always true/false)
43 static bool isTautologyCondition(const std::shared_ptr<AST::Expression> &cond);
44 
45 // Check if a condition is a pointer walk pattern
46 static bool isPointerWalkPattern(const std::shared_ptr<AST::Expression> &cond,
47 std::string &baseRegister);
48 
49 // Generate a safe bounded loop condition
50 static std::shared_ptr<AST::Expression>
51 generateBoundedCondition(const std::string &ptrReg, int maxIterations = 1000);
52 
53 // Add safety counter variable declaration
54 static std::shared_ptr<AST::VariableDecl>
55 generateSafetyCounter(const std::string &counterName = "safety");
56 
57 // Detect if loop body performs pointer arithmetic (ptr += offset)
58 static bool detectsPointerArithmetic(const std::shared_ptr<AST::Statement> &body,
59 std::string &ptrReg, int64_t &offset);
60 
61private:
62 // Helper: Check if expr is a self-comparison (a == a)
63 static bool isSelfComparison(const std::shared_ptr<AST::Expression> &expr);
64 
65 // Helper: Extract variable names from expressions
66 static std::set<std::string> extractVariables(const std::shared_ptr<AST::Expression> &expr);
67 
68 // Helper: Check for common sentinel values (0, -1, 0xffffffff, etc.)
69 static bool isSentinelValue(int64_t value);
70};
71 
72} // namespace ShadPKG::Decompiler::Analysis
73