316 lines
8.5 KiB
C#
316 lines
8.5 KiB
C#
// -----------------------------------------------------------------------------
|
|
// 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;
|
|
|
|
/// <summary>
|
|
/// Complete symbol table diff between two binaries.
|
|
/// </summary>
|
|
public sealed record SymbolTableDiff
|
|
{
|
|
/// <summary>Content-addressed diff ID (sha256 of canonical JSON).</summary>
|
|
[JsonPropertyName("diff_id")]
|
|
public required string DiffId { get; init; }
|
|
|
|
/// <summary>Base binary identity.</summary>
|
|
[JsonPropertyName("base")]
|
|
public required BinaryRef Base { get; init; }
|
|
|
|
/// <summary>Target binary identity.</summary>
|
|
[JsonPropertyName("target")]
|
|
public required BinaryRef Target { get; init; }
|
|
|
|
/// <summary>Exported symbol changes.</summary>
|
|
[JsonPropertyName("exports")]
|
|
public required SymbolChangeSummary Exports { get; init; }
|
|
|
|
/// <summary>Imported symbol changes.</summary>
|
|
[JsonPropertyName("imports")]
|
|
public required SymbolChangeSummary Imports { get; init; }
|
|
|
|
/// <summary>Version map changes.</summary>
|
|
[JsonPropertyName("versions")]
|
|
public required VersionMapDiff Versions { get; init; }
|
|
|
|
/// <summary>GOT/PLT changes (dynamic linking).</summary>
|
|
[JsonPropertyName("dynamic")]
|
|
public DynamicLinkingDiff? Dynamic { get; init; }
|
|
|
|
/// <summary>Overall ABI compatibility assessment.</summary>
|
|
[JsonPropertyName("abi_compatibility")]
|
|
public required AbiCompatibility AbiCompatibility { get; init; }
|
|
|
|
/// <summary>When this diff was computed (UTC).</summary>
|
|
[JsonPropertyName("computed_at")]
|
|
public required DateTimeOffset ComputedAt { get; init; }
|
|
|
|
/// <summary>Schema version for forward compatibility.</summary>
|
|
[JsonPropertyName("schema_version")]
|
|
public string SchemaVersion { get; init; } = "1.0";
|
|
}
|
|
|
|
/// <summary>Reference to a binary.</summary>
|
|
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; }
|
|
}
|
|
|
|
/// <summary>Binary format.</summary>
|
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
|
public enum BinaryFormat
|
|
{
|
|
Elf,
|
|
Pe,
|
|
MachO,
|
|
Unknown
|
|
}
|
|
|
|
/// <summary>Summary of symbol changes.</summary>
|
|
public sealed record SymbolChangeSummary
|
|
{
|
|
[JsonPropertyName("added")]
|
|
public required IReadOnlyList<SymbolChange> Added { get; init; }
|
|
|
|
[JsonPropertyName("removed")]
|
|
public required IReadOnlyList<SymbolChange> Removed { get; init; }
|
|
|
|
[JsonPropertyName("modified")]
|
|
public required IReadOnlyList<SymbolModification> Modified { get; init; }
|
|
|
|
[JsonPropertyName("renamed")]
|
|
public required IReadOnlyList<SymbolRename> Renamed { get; init; }
|
|
|
|
/// <summary>Count summaries.</summary>
|
|
[JsonPropertyName("counts")]
|
|
public required SymbolChangeCounts Counts { get; init; }
|
|
}
|
|
|
|
/// <summary>Count summary for symbol changes.</summary>
|
|
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; }
|
|
}
|
|
|
|
/// <summary>A symbol that was added or removed.</summary>
|
|
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; }
|
|
}
|
|
|
|
/// <summary>A symbol that was modified (same name, different attributes).</summary>
|
|
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<AttributeChange> Changes { get; init; }
|
|
|
|
[JsonPropertyName("is_abi_breaking")]
|
|
public bool IsAbiBreaking { get; init; }
|
|
}
|
|
|
|
/// <summary>Symbol attributes for comparison.</summary>
|
|
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; }
|
|
}
|
|
|
|
/// <summary>A specific attribute change.</summary>
|
|
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; }
|
|
}
|
|
|
|
/// <summary>A symbol that was renamed (detected via fingerprint matching).</summary>
|
|
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; }
|
|
}
|
|
|
|
/// <summary>Symbol type classification.</summary>
|
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
|
public enum SymbolType
|
|
{
|
|
NoType,
|
|
Object,
|
|
Function,
|
|
Section,
|
|
File,
|
|
Common,
|
|
Tls,
|
|
Unknown
|
|
}
|
|
|
|
/// <summary>Symbol binding.</summary>
|
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
|
public enum SymbolBinding
|
|
{
|
|
Local,
|
|
Global,
|
|
Weak,
|
|
Unknown
|
|
}
|
|
|
|
/// <summary>Symbol visibility.</summary>
|
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
|
public enum SymbolVisibility
|
|
{
|
|
Default,
|
|
Internal,
|
|
Hidden,
|
|
Protected,
|
|
Unknown
|
|
}
|
|
|
|
/// <summary>Severity of a change.</summary>
|
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
|
public enum ChangeSeverity
|
|
{
|
|
Info,
|
|
Low,
|
|
Medium,
|
|
High,
|
|
Critical
|
|
}
|
|
|
|
/// <summary>Confidence level for rename detection.</summary>
|
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
|
public enum RenameConfidence
|
|
{
|
|
VeryHigh,
|
|
High,
|
|
Medium,
|
|
Low,
|
|
VeryLow
|
|
}
|