2025-04-18 21:34:35 +03:00
|
|
|
namespace X86Disassembler.Analysers;
|
2025-04-18 16:29:53 +03:00
|
|
|
|
2025-04-18 21:34:35 +03:00
|
|
|
/// <summary>
|
|
|
|
/// Represents a disassembled function with its control flow graph
|
|
|
|
/// </summary>
|
2025-04-18 16:29:53 +03:00
|
|
|
public class AsmFunction
|
|
|
|
{
|
2025-04-18 21:34:35 +03:00
|
|
|
/// <summary>
|
|
|
|
/// The starting address of the function
|
|
|
|
/// </summary>
|
2025-04-18 16:29:53 +03:00
|
|
|
public ulong Address { get; set; }
|
|
|
|
|
2025-04-18 21:34:35 +03:00
|
|
|
/// <summary>
|
|
|
|
/// The list of basic blocks that make up the function
|
|
|
|
/// </summary>
|
|
|
|
public List<InstructionBlock> Blocks { get; set; } = [];
|
2025-04-18 16:29:53 +03:00
|
|
|
|
2025-04-18 21:34:35 +03:00
|
|
|
/// <summary>
|
|
|
|
/// The entry block of the function
|
|
|
|
/// </summary>
|
|
|
|
public InstructionBlock? EntryBlock => Blocks.FirstOrDefault(b => b.Address == Address);
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The exit blocks of the function (blocks that end with a return instruction)
|
|
|
|
/// </summary>
|
|
|
|
public List<InstructionBlock> ExitBlocks => Blocks.Where(b =>
|
|
|
|
b.Instructions.Count > 0 &&
|
|
|
|
b.Instructions[^1].Type.IsRet()).ToList();
|
2025-04-18 23:46:51 +03:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The analyzer context for this function
|
|
|
|
/// </summary>
|
|
|
|
public AnalyzerContext Context { get; private set; }
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Creates a new AsmFunction instance
|
|
|
|
/// </summary>
|
|
|
|
public AsmFunction()
|
|
|
|
{
|
|
|
|
Context = new AnalyzerContext(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Analyzes the function using various analyzers
|
|
|
|
/// </summary>
|
|
|
|
public void Analyze()
|
|
|
|
{
|
|
|
|
// Analyze loops
|
|
|
|
var loopAnalyzer = new LoopAnalyzer();
|
|
|
|
loopAnalyzer.AnalyzeLoops(Context);
|
|
|
|
|
|
|
|
// Analyze data flow
|
|
|
|
var dataFlowAnalyzer = new DataFlowAnalyzer();
|
|
|
|
dataFlowAnalyzer.AnalyzeDataFlow(Context);
|
|
|
|
}
|
2025-04-18 21:34:35 +03:00
|
|
|
|
|
|
|
/// <summary>
|
2025-04-18 23:46:51 +03:00
|
|
|
/// Returns a string representation of the function, including its address, blocks, and analysis results
|
2025-04-18 21:34:35 +03:00
|
|
|
/// </summary>
|
2025-04-18 16:29:53 +03:00
|
|
|
public override string ToString()
|
|
|
|
{
|
2025-04-18 23:46:51 +03:00
|
|
|
string loopsInfo = "";
|
|
|
|
if (Context.LoopsByHeaderAddress.Count > 0)
|
|
|
|
{
|
|
|
|
loopsInfo = $"Loops: {Context.LoopsByHeaderAddress.Count}\n";
|
|
|
|
int i = 0;
|
|
|
|
foreach (var loop in Context.LoopsByHeaderAddress.Values)
|
|
|
|
{
|
|
|
|
loopsInfo += $" Loop {i++}: Header=0x{loop.Header.Address:X8}, " +
|
|
|
|
$"Blocks={loop.Blocks.Count}, " +
|
|
|
|
$"Back Edge=(0x{loop.BackEdge.From.Address:X8} -> 0x{loop.BackEdge.To.Address:X8}), " +
|
|
|
|
$"Exits={loop.ExitBlocks.Count}\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
loopsInfo = "Loops: None\n";
|
|
|
|
}
|
|
|
|
|
2025-04-18 21:34:35 +03:00
|
|
|
return $"Function at 0x{Address:X8}\n" +
|
|
|
|
$"Entry Block: 0x{EntryBlock?.Address.ToString("X8") ?? "None"}\n" +
|
|
|
|
$"Exit Blocks: {(ExitBlocks.Count > 0 ? string.Join(", ", ExitBlocks.Select(b => $"0x{b.Address:X8}")) : "None")}\n" +
|
|
|
|
$"Total Blocks: {Blocks.Count}\n" +
|
2025-04-18 23:46:51 +03:00
|
|
|
loopsInfo +
|
2025-04-18 21:34:35 +03:00
|
|
|
$"{string.Join("\n", Blocks.Select(x => $"\t{x}"))}";
|
2025-04-18 16:29:53 +03:00
|
|
|
}
|
|
|
|
}
|