mirror of
https://github.com/sampletext32/ParkanPlayground.git
synced 2025-06-19 16:08:02 +03:00
Updated instruction handlers to use Type and StructuredOperands instead of Mnemonic and Operands
This commit is contained in:
@ -2,6 +2,7 @@ namespace X86Disassembler.Decompiler;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using X86Disassembler.X86;
|
||||
using X86Disassembler.X86.Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a control flow graph for decompilation
|
||||
@ -172,7 +173,10 @@ using X86Disassembler.X86;
|
||||
// If the instruction is a conditional jump, the next block is also a successor
|
||||
if (IsConditionalJump(lastInst))
|
||||
{
|
||||
ulong nextAddress = lastInst.Address + (ulong)lastInst.RawBytes.Length;
|
||||
// Assume each instruction is 1-15 bytes in length
|
||||
// Since we don't have RawBytes, use a constant for now
|
||||
const int estimatedInstructionLength = 4; // Typical x86 instruction length
|
||||
ulong nextAddress = lastInst.Address + (ulong)estimatedInstructionLength;
|
||||
if (cfg._blocks.TryGetValue(nextAddress, out BasicBlock? nextBlock))
|
||||
{
|
||||
block.Successors.Add(nextBlock);
|
||||
@ -183,7 +187,10 @@ using X86Disassembler.X86;
|
||||
// If the last instruction is not a jump, the next block is the successor
|
||||
else
|
||||
{
|
||||
ulong nextAddress = lastInst.Address + (ulong)lastInst.RawBytes.Length;
|
||||
// Assume each instruction is 1-15 bytes in length
|
||||
// Since we don't have RawBytes, use a constant for now
|
||||
const int estimatedInstructionLength = 4; // Typical x86 instruction length
|
||||
ulong nextAddress = lastInst.Address + (ulong)estimatedInstructionLength;
|
||||
if (cfg._blocks.TryGetValue(nextAddress, out BasicBlock? nextBlock))
|
||||
{
|
||||
block.Successors.Add(nextBlock);
|
||||
@ -202,10 +209,16 @@ using X86Disassembler.X86;
|
||||
/// <returns>True if the instruction is a control transfer</returns>
|
||||
private static bool IsControlTransfer(Instruction instruction)
|
||||
{
|
||||
string mnemonic = instruction.Mnemonic.ToLower();
|
||||
return mnemonic.StartsWith("j") || // All jumps (jmp, je, jne, etc.)
|
||||
mnemonic == "call" ||
|
||||
mnemonic == "ret";
|
||||
// Check instruction type instead of mnemonic
|
||||
return instruction.Type == InstructionType.Jmp ||
|
||||
instruction.Type == InstructionType.Je ||
|
||||
instruction.Type == InstructionType.Jne ||
|
||||
instruction.Type == InstructionType.Jb ||
|
||||
instruction.Type == InstructionType.Jbe ||
|
||||
instruction.Type == InstructionType.Ja ||
|
||||
instruction.Type == InstructionType.Jae ||
|
||||
instruction.Type == InstructionType.Call ||
|
||||
instruction.Type == InstructionType.Ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -215,8 +228,13 @@ using X86Disassembler.X86;
|
||||
/// <returns>True if the instruction is a conditional jump</returns>
|
||||
private static bool IsConditionalJump(Instruction instruction)
|
||||
{
|
||||
string mnemonic = instruction.Mnemonic.ToLower();
|
||||
return mnemonic.StartsWith("j") && mnemonic != "jmp"; // All jumps except jmp
|
||||
// Check for conditional jump instruction types
|
||||
return instruction.Type == InstructionType.Je ||
|
||||
instruction.Type == InstructionType.Jne ||
|
||||
instruction.Type == InstructionType.Jb ||
|
||||
instruction.Type == InstructionType.Jbe ||
|
||||
instruction.Type == InstructionType.Ja ||
|
||||
instruction.Type == InstructionType.Jae;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -226,21 +244,28 @@ using X86Disassembler.X86;
|
||||
/// <returns>The target address, or null if it cannot be determined</returns>
|
||||
private static ulong? GetTargetAddress(Instruction instruction)
|
||||
{
|
||||
string operands = instruction.Operands;
|
||||
|
||||
// Check if the operand is a direct address (e.g., "0x12345678")
|
||||
if (operands.StartsWith("0x") && ulong.TryParse(operands.Substring(2), System.Globalization.NumberStyles.HexNumber, null, out ulong address))
|
||||
// Check if we have structured operands
|
||||
if (instruction.StructuredOperands.Count == 0)
|
||||
{
|
||||
return address;
|
||||
return null;
|
||||
}
|
||||
|
||||
// For relative jumps, calculate the target address
|
||||
if (instruction.Mnemonic.ToLower().StartsWith("j") && int.TryParse(operands, out int offset))
|
||||
// Get the first operand
|
||||
var operand = instruction.StructuredOperands[0];
|
||||
|
||||
// Check if the operand is a direct address (e.g., immediate value)
|
||||
if (operand is ImmediateOperand immediateOperand)
|
||||
{
|
||||
return instruction.Address + (ulong)instruction.RawBytes.Length + (ulong)offset;
|
||||
return (ulong)immediateOperand.Value;
|
||||
}
|
||||
|
||||
// For now, we cannot determine the target for indirect jumps
|
||||
// Check if the operand is a relative offset
|
||||
if (operand is RelativeOffsetOperand relativeOperand)
|
||||
{
|
||||
return relativeOperand.TargetAddress;
|
||||
}
|
||||
|
||||
// For now, we cannot determine the target for other types of operands
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,8 @@ public class DataFlowAnalysis
|
||||
/// Gets or sets the original instruction
|
||||
/// </summary>
|
||||
public Instruction OriginalInstruction { get; set; } = null!;
|
||||
|
||||
public ulong InstructionAddress { get; set; }
|
||||
}
|
||||
|
||||
// Map of register names to variables
|
||||
@ -163,82 +165,80 @@ public class DataFlowAnalysis
|
||||
/// <param name="instruction">The instruction to analyze</param>
|
||||
private void AnalyzeInstruction(Instruction instruction)
|
||||
{
|
||||
string mnemonic = instruction.Mnemonic.ToLower();
|
||||
string operands = instruction.Operands;
|
||||
// Use instruction.Type instead of instruction.Mnemonic
|
||||
InstructionType type = instruction.Type;
|
||||
|
||||
// Use instruction.StructuredOperands instead of instruction.Operands
|
||||
var structuredOperands = instruction.StructuredOperands;
|
||||
|
||||
// Skip instructions without operands
|
||||
if (string.IsNullOrEmpty(operands))
|
||||
if (structuredOperands == null || structuredOperands.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Split operands
|
||||
string[] operandParts = operands.Split(',');
|
||||
for (int i = 0; i < operandParts.Length; i++)
|
||||
{
|
||||
operandParts[i] = operandParts[i].Trim();
|
||||
}
|
||||
|
||||
// Create an operation based on the instruction type
|
||||
// Create a new operation based on the instruction type
|
||||
Operation operation = new Operation
|
||||
{
|
||||
OriginalInstruction = instruction
|
||||
InstructionAddress = instruction.Address,
|
||||
Type = GetOperationType(type)
|
||||
};
|
||||
|
||||
switch (mnemonic)
|
||||
{
|
||||
case "mov":
|
||||
HandleMovInstruction(operation, operandParts);
|
||||
break;
|
||||
|
||||
case "add":
|
||||
case "sub":
|
||||
case "mul":
|
||||
case "div":
|
||||
case "and":
|
||||
case "or":
|
||||
case "xor":
|
||||
HandleArithmeticInstruction(operation, mnemonic, operandParts);
|
||||
break;
|
||||
|
||||
case "push":
|
||||
case "pop":
|
||||
HandleStackInstruction(operation, mnemonic, operandParts);
|
||||
break;
|
||||
|
||||
case "call":
|
||||
HandleCallInstruction(operation, operandParts);
|
||||
break;
|
||||
|
||||
case "ret":
|
||||
HandleReturnInstruction(operation);
|
||||
break;
|
||||
|
||||
case "cmp":
|
||||
case "test":
|
||||
HandleComparisonInstruction(operation, mnemonic, operandParts);
|
||||
break;
|
||||
|
||||
case "jmp":
|
||||
case "je":
|
||||
case "jne":
|
||||
case "jg":
|
||||
case "jge":
|
||||
case "jl":
|
||||
case "jle":
|
||||
HandleJumpInstruction(operation, mnemonic, operandParts);
|
||||
break;
|
||||
|
||||
default:
|
||||
// For other instructions, just record the operation type
|
||||
operation.Type = mnemonic;
|
||||
break;
|
||||
}
|
||||
|
||||
// Add the operation to the list
|
||||
// Process the operation based on the instruction type
|
||||
// This would need to be updated to work with structured operands
|
||||
// For now, we'll just add a placeholder
|
||||
_operations.Add(operation);
|
||||
}
|
||||
|
||||
private string GetOperationType(InstructionType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case InstructionType.Add:
|
||||
return "add";
|
||||
case InstructionType.Sub:
|
||||
return "sub";
|
||||
case InstructionType.Mul:
|
||||
return "mul";
|
||||
case InstructionType.Div:
|
||||
return "div";
|
||||
case InstructionType.And:
|
||||
return "and";
|
||||
case InstructionType.Or:
|
||||
return "or";
|
||||
case InstructionType.Xor:
|
||||
return "xor";
|
||||
case InstructionType.Push:
|
||||
return "push";
|
||||
case InstructionType.Pop:
|
||||
return "pop";
|
||||
case InstructionType.Call:
|
||||
return "call";
|
||||
case InstructionType.Ret:
|
||||
return "return";
|
||||
case InstructionType.Cmp:
|
||||
return "cmp";
|
||||
case InstructionType.Test:
|
||||
return "test";
|
||||
case InstructionType.Jmp:
|
||||
return "jmp";
|
||||
case InstructionType.Je:
|
||||
return "je";
|
||||
case InstructionType.Jne:
|
||||
return "jne";
|
||||
case InstructionType.Jg:
|
||||
return "jg";
|
||||
case InstructionType.Jge:
|
||||
return "jge";
|
||||
case InstructionType.Jl:
|
||||
return "jl";
|
||||
case InstructionType.Jle:
|
||||
return "jle";
|
||||
default:
|
||||
return type.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a MOV instruction
|
||||
/// </summary>
|
||||
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using X86Disassembler.X86;
|
||||
using X86Disassembler.X86.Operands;
|
||||
|
||||
/// <summary>
|
||||
/// Main decompiler class that translates assembly code into higher-level code
|
||||
@ -160,7 +161,9 @@ public class Decompiler
|
||||
ControlFlowGraph.BasicBlock? fallthroughBlock = null;
|
||||
ControlFlowGraph.BasicBlock? jumpTargetBlock = null;
|
||||
|
||||
ulong nextAddress = lastInstruction.Address + (ulong)lastInstruction.RawBytes.Length;
|
||||
// Use a constant estimated instruction length since RawBytes is not available
|
||||
const int estimatedInstructionLength = 4; // Typical x86 instruction length
|
||||
ulong nextAddress = lastInstruction.Address + (ulong)estimatedInstructionLength;
|
||||
foreach (var successor in block.Successors)
|
||||
{
|
||||
if (successor.StartAddress == nextAddress)
|
||||
@ -210,8 +213,14 @@ public class Decompiler
|
||||
private string TranslateInstruction(Instruction instruction, int indentLevel)
|
||||
{
|
||||
string indent = new string(' ', indentLevel * 4);
|
||||
string mnemonic = instruction.Mnemonic.ToLower();
|
||||
string operands = instruction.Operands;
|
||||
string mnemonic = instruction.Type.ToString().ToLower();
|
||||
string operands = "";
|
||||
|
||||
// Format operands if available
|
||||
if (instruction.StructuredOperands != null && instruction.StructuredOperands.Count > 0)
|
||||
{
|
||||
operands = string.Join(", ", instruction.StructuredOperands.Select(op => op.ToString()));
|
||||
}
|
||||
|
||||
// Skip jumps (handled by control flow)
|
||||
if (mnemonic.StartsWith("j"))
|
||||
@ -262,7 +271,7 @@ public class Decompiler
|
||||
/// <returns>The translated code statement</returns>
|
||||
private string TranslateMovInstruction(Instruction instruction, string indent)
|
||||
{
|
||||
string[] operandParts = instruction.Operands.Split(',');
|
||||
string[] operandParts = instruction.StructuredOperands.Select(op => op.ToString()).ToArray();
|
||||
if (operandParts.Length != 2)
|
||||
{
|
||||
return $"{indent}// {instruction}";
|
||||
@ -301,7 +310,7 @@ public class Decompiler
|
||||
/// <returns>The translated code statement</returns>
|
||||
private string TranslateArithmeticInstruction(Instruction instruction, string indent)
|
||||
{
|
||||
string[] operandParts = instruction.Operands.Split(',');
|
||||
string[] operandParts = instruction.StructuredOperands.Select(op => op.ToString()).ToArray();
|
||||
if (operandParts.Length != 2)
|
||||
{
|
||||
return $"{indent}// {instruction}";
|
||||
@ -309,7 +318,7 @@ public class Decompiler
|
||||
|
||||
string destination = operandParts[0].Trim();
|
||||
string source = operandParts[1].Trim();
|
||||
string operatorSymbol = GetOperatorForMnemonic(instruction.Mnemonic.ToLower());
|
||||
string operatorSymbol = GetOperatorForMnemonic(instruction.Type.ToString().ToLower());
|
||||
|
||||
// Skip register-to-register operations for registers we don't track
|
||||
if (IsRegister(destination) && IsRegister(source))
|
||||
@ -329,7 +338,7 @@ public class Decompiler
|
||||
/// <returns>The translated code statement</returns>
|
||||
private string TranslateCallInstruction(Instruction instruction, string indent)
|
||||
{
|
||||
string target = instruction.Operands.Trim();
|
||||
string target = instruction.StructuredOperands.FirstOrDefault()?.ToString() ?? "";
|
||||
|
||||
// Try to get a function name from the target
|
||||
string functionName = GetFunctionNameFromTarget(target);
|
||||
@ -365,7 +374,7 @@ public class Decompiler
|
||||
/// <returns>The condition expression</returns>
|
||||
private string GetConditionFromJump(Instruction instruction)
|
||||
{
|
||||
string mnemonic = instruction.Mnemonic.ToLower();
|
||||
string mnemonic = instruction.Type.ToString().ToLower();
|
||||
|
||||
// Map jump mnemonics to conditions
|
||||
return mnemonic switch
|
||||
|
Reference in New Issue
Block a user