// 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 }