Files
git.stella-ops.org/src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Ghidra/Abstractions/IGhidriffBridge.cs
StellaOps Bot 37e11918e0 save progress
2026-01-06 09:42:20 +02:00

208 lines
7.3 KiB
C#

// Copyright (c) StellaOps. All rights reserved.
// Licensed under AGPL-3.0-or-later. See LICENSE in the project root.
using System.Collections.Immutable;
namespace StellaOps.BinaryIndex.Ghidra;
/// <summary>
/// Bridge interface for ghidriff Python tool integration.
/// ghidriff provides automated binary diff reports using Ghidra.
/// </summary>
public interface IGhidriffBridge
{
/// <summary>
/// Run ghidriff to compare two binaries.
/// </summary>
/// <param name="oldBinaryPath">Path to the older binary version.</param>
/// <param name="newBinaryPath">Path to the newer binary version.</param>
/// <param name="options">ghidriff configuration options.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>Diff result with added, removed, and modified functions.</returns>
Task<GhidriffResult> DiffAsync(
string oldBinaryPath,
string newBinaryPath,
GhidriffDiffOptions? options = null,
CancellationToken ct = default);
/// <summary>
/// Run ghidriff to compare two binaries from streams.
/// </summary>
/// <param name="oldBinary">Stream of the older binary version.</param>
/// <param name="newBinary">Stream of the newer binary version.</param>
/// <param name="options">ghidriff configuration options.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>Diff result with added, removed, and modified functions.</returns>
Task<GhidriffResult> DiffAsync(
Stream oldBinary,
Stream newBinary,
GhidriffDiffOptions? options = null,
CancellationToken ct = default);
/// <summary>
/// Generate a formatted report from ghidriff results.
/// </summary>
/// <param name="result">The diff result to format.</param>
/// <param name="format">Output format.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>Formatted report string.</returns>
Task<string> GenerateReportAsync(
GhidriffResult result,
GhidriffReportFormat format,
CancellationToken ct = default);
/// <summary>
/// Check if ghidriff is available (Python + ghidriff installed).
/// </summary>
/// <param name="ct">Cancellation token.</param>
/// <returns>True if ghidriff is available.</returns>
Task<bool> IsAvailableAsync(CancellationToken ct = default);
/// <summary>
/// Get ghidriff version information.
/// </summary>
/// <param name="ct">Cancellation token.</param>
/// <returns>Version string.</returns>
Task<string> GetVersionAsync(CancellationToken ct = default);
}
/// <summary>
/// Options for ghidriff diff operation.
/// </summary>
public sealed record GhidriffDiffOptions
{
/// <summary>
/// Path to Ghidra installation (auto-detected if not set).
/// </summary>
public string? GhidraPath { get; init; }
/// <summary>
/// Path for Ghidra project files (temp dir if not set).
/// </summary>
public string? ProjectPath { get; init; }
/// <summary>
/// Whether to include decompiled code in results.
/// </summary>
public bool IncludeDecompilation { get; init; } = true;
/// <summary>
/// Whether to include disassembly listing in results.
/// </summary>
public bool IncludeDisassembly { get; init; } = true;
/// <summary>
/// Functions to exclude from comparison (by name pattern).
/// </summary>
public ImmutableArray<string> ExcludeFunctions { get; init; } = [];
/// <summary>
/// Maximum number of concurrent Ghidra instances.
/// </summary>
public int MaxParallelism { get; init; } = 1;
/// <summary>
/// Maximum analysis time in seconds.
/// </summary>
public int TimeoutSeconds { get; init; } = 600;
}
/// <summary>
/// Result of a ghidriff comparison.
/// </summary>
/// <param name="OldBinaryHash">SHA256 hash of the old binary.</param>
/// <param name="NewBinaryHash">SHA256 hash of the new binary.</param>
/// <param name="OldBinaryName">Name/path of the old binary.</param>
/// <param name="NewBinaryName">Name/path of the new binary.</param>
/// <param name="AddedFunctions">Functions added in new binary.</param>
/// <param name="RemovedFunctions">Functions removed from old binary.</param>
/// <param name="ModifiedFunctions">Functions modified between versions.</param>
/// <param name="Statistics">Comparison statistics.</param>
/// <param name="RawJsonOutput">Raw JSON output from ghidriff.</param>
public sealed record GhidriffResult(
string OldBinaryHash,
string NewBinaryHash,
string OldBinaryName,
string NewBinaryName,
ImmutableArray<GhidriffFunction> AddedFunctions,
ImmutableArray<GhidriffFunction> RemovedFunctions,
ImmutableArray<GhidriffDiff> ModifiedFunctions,
GhidriffStats Statistics,
string RawJsonOutput);
/// <summary>
/// A function from ghidriff output.
/// </summary>
/// <param name="Name">Function name.</param>
/// <param name="Address">Function address.</param>
/// <param name="Size">Function size in bytes.</param>
/// <param name="Signature">Decompiled signature.</param>
/// <param name="DecompiledCode">Decompiled C code (if requested).</param>
public sealed record GhidriffFunction(
string Name,
ulong Address,
int Size,
string? Signature,
string? DecompiledCode);
/// <summary>
/// A function diff from ghidriff output.
/// </summary>
/// <param name="FunctionName">Function name.</param>
/// <param name="OldAddress">Address in old binary.</param>
/// <param name="NewAddress">Address in new binary.</param>
/// <param name="OldSize">Size in old binary.</param>
/// <param name="NewSize">Size in new binary.</param>
/// <param name="OldSignature">Signature in old binary.</param>
/// <param name="NewSignature">Signature in new binary.</param>
/// <param name="Similarity">Similarity score.</param>
/// <param name="OldDecompiled">Decompiled code from old binary.</param>
/// <param name="NewDecompiled">Decompiled code from new binary.</param>
/// <param name="InstructionChanges">List of instruction-level changes.</param>
public sealed record GhidriffDiff(
string FunctionName,
ulong OldAddress,
ulong NewAddress,
int OldSize,
int NewSize,
string? OldSignature,
string? NewSignature,
decimal Similarity,
string? OldDecompiled,
string? NewDecompiled,
ImmutableArray<string> InstructionChanges);
/// <summary>
/// Statistics from ghidriff comparison.
/// </summary>
/// <param name="TotalOldFunctions">Total functions in old binary.</param>
/// <param name="TotalNewFunctions">Total functions in new binary.</param>
/// <param name="AddedCount">Number of added functions.</param>
/// <param name="RemovedCount">Number of removed functions.</param>
/// <param name="ModifiedCount">Number of modified functions.</param>
/// <param name="UnchangedCount">Number of unchanged functions.</param>
/// <param name="AnalysisDuration">Time taken for analysis.</param>
public sealed record GhidriffStats(
int TotalOldFunctions,
int TotalNewFunctions,
int AddedCount,
int RemovedCount,
int ModifiedCount,
int UnchangedCount,
TimeSpan AnalysisDuration);
/// <summary>
/// Report output format for ghidriff.
/// </summary>
public enum GhidriffReportFormat
{
/// <summary>JSON format.</summary>
Json,
/// <summary>Markdown format.</summary>
Markdown,
/// <summary>HTML format.</summary>
Html
}