// -----------------------------------------------------------------------------
// SymbolTableDiff.cs
// Sprint: SPRINT_20260106_001_003_BINDEX_symbol_table_diff
// Tasks: SYM-001, SYM-002, SYM-003, SYM-004, SYM-005
// Description: Symbol table diff model for comparing exports/imports between binaries
// -----------------------------------------------------------------------------
using System.Text.Json.Serialization;
namespace StellaOps.BinaryIndex.Builders.SymbolDiff;
///
/// Complete symbol table diff between two binaries.
///
public sealed record SymbolTableDiff
{
/// Content-addressed diff ID (sha256 of canonical JSON).
[JsonPropertyName("diff_id")]
public required string DiffId { get; init; }
/// Base binary identity.
[JsonPropertyName("base")]
public required BinaryRef Base { get; init; }
/// Target binary identity.
[JsonPropertyName("target")]
public required BinaryRef Target { get; init; }
/// Exported symbol changes.
[JsonPropertyName("exports")]
public required SymbolChangeSummary Exports { get; init; }
/// Imported symbol changes.
[JsonPropertyName("imports")]
public required SymbolChangeSummary Imports { get; init; }
/// Version map changes.
[JsonPropertyName("versions")]
public required VersionMapDiff Versions { get; init; }
/// GOT/PLT changes (dynamic linking).
[JsonPropertyName("dynamic")]
public DynamicLinkingDiff? Dynamic { get; init; }
/// Overall ABI compatibility assessment.
[JsonPropertyName("abi_compatibility")]
public required AbiCompatibility AbiCompatibility { get; init; }
/// When this diff was computed (UTC).
[JsonPropertyName("computed_at")]
public required DateTimeOffset ComputedAt { get; init; }
/// Schema version for forward compatibility.
[JsonPropertyName("schema_version")]
public string SchemaVersion { get; init; } = "1.0";
}
/// Reference to a binary.
public sealed record BinaryRef
{
[JsonPropertyName("path")]
public required string Path { get; init; }
[JsonPropertyName("sha256")]
public required string Sha256 { get; init; }
[JsonPropertyName("build_id")]
public string? BuildId { get; init; }
[JsonPropertyName("architecture")]
public required string Architecture { get; init; }
[JsonPropertyName("format")]
public required BinaryFormat Format { get; init; }
[JsonPropertyName("file_size")]
public long FileSize { get; init; }
}
/// Binary format.
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum BinaryFormat
{
Elf,
Pe,
MachO,
Unknown
}
/// Summary of symbol changes.
public sealed record SymbolChangeSummary
{
[JsonPropertyName("added")]
public required IReadOnlyList Added { get; init; }
[JsonPropertyName("removed")]
public required IReadOnlyList Removed { get; init; }
[JsonPropertyName("modified")]
public required IReadOnlyList Modified { get; init; }
[JsonPropertyName("renamed")]
public required IReadOnlyList Renamed { get; init; }
/// Count summaries.
[JsonPropertyName("counts")]
public required SymbolChangeCounts Counts { get; init; }
}
/// Count summary for symbol changes.
public sealed record SymbolChangeCounts
{
[JsonPropertyName("added")]
public int Added { get; init; }
[JsonPropertyName("removed")]
public int Removed { get; init; }
[JsonPropertyName("modified")]
public int Modified { get; init; }
[JsonPropertyName("renamed")]
public int Renamed { get; init; }
[JsonPropertyName("unchanged")]
public int Unchanged { get; init; }
[JsonPropertyName("total_base")]
public int TotalBase { get; init; }
[JsonPropertyName("total_target")]
public int TotalTarget { get; init; }
}
/// A symbol that was added or removed.
public sealed record SymbolChange
{
[JsonPropertyName("name")]
public required string Name { get; init; }
[JsonPropertyName("demangled_name")]
public string? DemangledName { get; init; }
[JsonPropertyName("type")]
public required SymbolType Type { get; init; }
[JsonPropertyName("binding")]
public required SymbolBinding Binding { get; init; }
[JsonPropertyName("visibility")]
public required SymbolVisibility Visibility { get; init; }
[JsonPropertyName("section")]
public string? Section { get; init; }
[JsonPropertyName("address")]
public ulong Address { get; init; }
[JsonPropertyName("size")]
public ulong Size { get; init; }
[JsonPropertyName("version")]
public string? Version { get; init; }
[JsonPropertyName("fingerprint")]
public string? Fingerprint { get; init; }
}
/// A symbol that was modified (same name, different attributes).
public sealed record SymbolModification
{
[JsonPropertyName("name")]
public required string Name { get; init; }
[JsonPropertyName("demangled_name")]
public string? DemangledName { get; init; }
[JsonPropertyName("base")]
public required SymbolAttributes Base { get; init; }
[JsonPropertyName("target")]
public required SymbolAttributes Target { get; init; }
[JsonPropertyName("changes")]
public required IReadOnlyList Changes { get; init; }
[JsonPropertyName("is_abi_breaking")]
public bool IsAbiBreaking { get; init; }
}
/// Symbol attributes for comparison.
public sealed record SymbolAttributes
{
[JsonPropertyName("type")]
public required SymbolType Type { get; init; }
[JsonPropertyName("binding")]
public required SymbolBinding Binding { get; init; }
[JsonPropertyName("visibility")]
public required SymbolVisibility Visibility { get; init; }
[JsonPropertyName("section")]
public string? Section { get; init; }
[JsonPropertyName("address")]
public ulong Address { get; init; }
[JsonPropertyName("size")]
public ulong Size { get; init; }
[JsonPropertyName("version")]
public string? Version { get; init; }
[JsonPropertyName("fingerprint")]
public string? Fingerprint { get; init; }
}
/// A specific attribute change.
public sealed record AttributeChange
{
[JsonPropertyName("attribute")]
public required string Attribute { get; init; }
[JsonPropertyName("base_value")]
public string? BaseValue { get; init; }
[JsonPropertyName("target_value")]
public string? TargetValue { get; init; }
[JsonPropertyName("severity")]
public required ChangeSeverity Severity { get; init; }
}
/// A symbol that was renamed (detected via fingerprint matching).
public sealed record SymbolRename
{
[JsonPropertyName("base_name")]
public required string BaseName { get; init; }
[JsonPropertyName("target_name")]
public required string TargetName { get; init; }
[JsonPropertyName("base_demangled")]
public string? BaseDemangled { get; init; }
[JsonPropertyName("target_demangled")]
public string? TargetDemangled { get; init; }
[JsonPropertyName("fingerprint")]
public required string Fingerprint { get; init; }
[JsonPropertyName("similarity")]
public double Similarity { get; init; }
[JsonPropertyName("confidence")]
public required RenameConfidence Confidence { get; init; }
}
/// Symbol type classification.
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum SymbolType
{
NoType,
Object,
Function,
Section,
File,
Common,
Tls,
Unknown
}
/// Symbol binding.
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum SymbolBinding
{
Local,
Global,
Weak,
Unknown
}
/// Symbol visibility.
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum SymbolVisibility
{
Default,
Internal,
Hidden,
Protected,
Unknown
}
/// Severity of a change.
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum ChangeSeverity
{
Info,
Low,
Medium,
High,
Critical
}
/// Confidence level for rename detection.
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum RenameConfidence
{
VeryHigh,
High,
Medium,
Low,
VeryLow
}