// Licensed under AGPL-3.0-or-later. Copyright (C) 2026 StellaOps Contributors.
using System.Collections.Immutable;
namespace StellaOps.BinaryIndex.Analysis;
///
/// Multi-level fingerprint collection for a function.
///
public sealed record FunctionFingerprint
{
///
/// Function name (symbol or demangled).
///
public required string FunctionName { get; init; }
///
/// Function address in binary.
///
public required ulong Address { get; init; }
///
/// Size of the function in bytes.
///
public ulong Size { get; init; }
///
/// BasicBlock-level hashes (per-block instruction hashes).
///
public required ImmutableArray BasicBlockHashes { get; init; }
///
/// CFG structural hash (Weisfeiler-Lehman on block graph).
///
public required string CfgHash { get; init; }
///
/// String reference hashes (sorted, normalized).
///
public ImmutableArray StringRefHashes { get; init; } = [];
///
/// Semantic embedding (KSG + Weisfeiler-Lehman).
///
public SemanticEmbedding? SemanticEmbedding { get; init; }
///
/// Constants extracted from instructions.
///
public ImmutableArray Constants { get; init; } = [];
///
/// Call targets (functions called by this function).
///
public ImmutableArray CallTargets { get; init; } = [];
///
/// Architecture (x86_64, aarch64, etc.).
///
public string? Architecture { get; init; }
}
///
/// Hash of a single basic block.
///
public sealed record BasicBlockHash
{
///
/// Block identifier (e.g., "bb0", "bb1").
///
public required string BlockId { get; init; }
///
/// Address of block start.
///
public required ulong StartAddress { get; init; }
///
/// Address of block end.
///
public ulong EndAddress { get; init; }
///
/// Normalized instruction hash (opcode sequence only).
///
public required string OpcodeHash { get; init; }
///
/// Full instruction hash (with operands).
///
public required string FullHash { get; init; }
///
/// Number of instructions in the block.
///
public int InstructionCount { get; init; }
///
/// Successor blocks (outgoing edges).
///
public ImmutableArray Successors { get; init; } = [];
///
/// Predecessor blocks (incoming edges).
///
public ImmutableArray Predecessors { get; init; } = [];
///
/// Block type (entry, exit, branch, loop, etc.).
///
public BasicBlockType BlockType { get; init; } = BasicBlockType.Normal;
}
///
/// Basic block types.
///
public enum BasicBlockType
{
/// Normal block.
Normal,
/// Function entry block.
Entry,
/// Function exit/return block.
Exit,
/// Conditional branch block.
ConditionalBranch,
/// Unconditional jump block.
UnconditionalJump,
/// Loop header block.
LoopHeader,
/// Loop body block.
LoopBody,
/// Switch/indirect jump block.
Switch,
/// Exception handler block.
ExceptionHandler
}
///
/// Semantic embedding using KSG (Knowledge Semantic Graph).
///
public sealed record SemanticEmbedding
{
///
/// Embedding vector (dimension depends on model).
///
public required float[] Vector { get; init; }
///
/// Model version used for embedding.
///
public required string ModelVersion { get; init; }
///
/// Embedding dimension.
///
public int Dimension => Vector.Length;
///
/// Similarity threshold for matching.
///
public float SimilarityThreshold { get; init; } = 0.85f;
///
/// Computes cosine similarity with another embedding.
///
public float CosineSimilarity(SemanticEmbedding other)
{
ArgumentNullException.ThrowIfNull(other);
if (Vector.Length != other.Vector.Length)
return 0f;
var dotProduct = 0f;
var normA = 0f;
var normB = 0f;
for (var i = 0; i < Vector.Length; i++)
{
dotProduct += Vector[i] * other.Vector[i];
normA += Vector[i] * Vector[i];
normB += other.Vector[i] * other.Vector[i];
}
var denominator = MathF.Sqrt(normA) * MathF.Sqrt(normB);
return denominator > 0 ? dotProduct / denominator : 0f;
}
}
///
/// A constant extracted from binary instructions.
///
public sealed record ExtractedConstant
{
///
/// Value as hex string (e.g., "0x1000").
///
public required string Value { get; init; }
///
/// Numeric value (if parseable).
///
public long? NumericValue { get; init; }
///
/// Address where found.
///
public required ulong Address { get; init; }
///
/// Size in bytes (1, 2, 4, 8).
///
public int Size { get; init; } = 4;
///
/// Context (instruction type or data section).
///
public string? Context { get; init; }
///
/// Whether this is likely a meaningful constant (not a small immediate).
///
public bool IsMeaningful { get; init; } = true;
}
///
/// CFG edge between basic blocks.
///
public sealed record CfgEdge
{
///
/// Source block ID.
///
public required string SourceBlockId { get; init; }
///
/// Target block ID.
///
public required string TargetBlockId { get; init; }
///
/// Edge type (fall-through, conditional-true, conditional-false, jump).
///
public CfgEdgeType EdgeType { get; init; } = CfgEdgeType.FallThrough;
///
/// Condition expression (for conditional edges).
///
public string? Condition { get; init; }
}
///
/// CFG edge types.
///
public enum CfgEdgeType
{
/// Fall-through to next block.
FallThrough,
/// Conditional true branch.
ConditionalTrue,
/// Conditional false branch.
ConditionalFalse,
/// Unconditional jump.
UnconditionalJump,
/// Call edge.
Call,
/// Return edge.
Return,
/// Switch/indirect edge.
Switch
}