namespace StellaOps.Signals.Services; /// /// Symbol canonicalization service interface. /// Sprint: SPRINT_20251226_010_SIGNALS_runtime_stack /// Task: STACK-06 /// /// Resolves program counter addresses to canonical (Build-ID, function, offset) tuples. /// public interface ISymbolCanonicalizationService { /// /// Resolves a program counter address to a canonical symbol. /// /// The program counter address. /// The ELF Build-ID of the binary. /// Optional path to the binary for symbol lookup. /// Cancellation token. /// The resolved symbol, or null if resolution failed. Task ResolveAsync( ulong address, string? buildId, string? binaryPath = null, CancellationToken cancellationToken = default); /// /// Resolves multiple addresses in batch for efficiency. /// Task> ResolveBatchAsync( IReadOnlyList requests, CancellationToken cancellationToken = default); /// /// Resolves a Java frame using JVMTI metadata. /// Task ResolveJavaFrameAsync( ulong address, JavaFrameMetadata metadata, CancellationToken cancellationToken = default); /// /// Resolves a .NET frame using DAC (Data Access Component). /// Task ResolveDotNetFrameAsync( ulong address, DotNetFrameMetadata metadata, CancellationToken cancellationToken = default); /// /// Resolves a Python frame using interpreter symbols. /// Task ResolvePythonFrameAsync( ulong address, PythonFrameMetadata metadata, CancellationToken cancellationToken = default); /// /// Checks if a Build-ID is in the local symbol cache. /// Task IsInCacheAsync(string buildId, CancellationToken cancellationToken = default); /// /// Adds symbols for a Build-ID to the cache. /// Task CacheSymbolsAsync( string buildId, IReadOnlyList symbols, CancellationToken cancellationToken = default); } /// /// Request for symbol resolution. /// public sealed record SymbolResolutionRequest { /// /// Program counter address. /// public required ulong Address { get; init; } /// /// ELF Build-ID of the binary. /// public string? BuildId { get; init; } /// /// Path to the binary file. /// public string? BinaryPath { get; init; } /// /// Runtime type hint for managed runtimes. /// public RuntimeType RuntimeType { get; init; } = RuntimeType.Native; } /// /// Runtime type for symbol resolution hints. /// public enum RuntimeType { /// /// Native code (C, C++, Rust, Go, etc.). /// Native, /// /// Java Virtual Machine. /// Java, /// /// .NET Common Language Runtime. /// DotNet, /// /// Python interpreter. /// Python, /// /// Node.js / V8. /// NodeJs, /// /// Ruby interpreter. /// Ruby, } /// /// Canonical symbol representation. /// public sealed record CanonicalSymbol { /// /// Original address that was resolved. /// public required ulong Address { get; init; } /// /// ELF Build-ID of the containing binary. /// public required string BuildId { get; init; } /// /// Demangled function name. /// public required string FunctionName { get; init; } /// /// Offset within the function. /// public required ulong Offset { get; init; } /// /// Module or binary name. /// public string? ModuleName { get; init; } /// /// Source file path (if debug info available). /// public string? SourceFile { get; init; } /// /// Source line number. /// public int? SourceLine { get; init; } /// /// Whether this symbol is from a trusted source. /// public bool IsTrusted { get; init; } /// /// Resolution method used. /// public SymbolResolutionMethod ResolutionMethod { get; init; } /// /// Returns the canonical string format. /// public string ToCanonicalString() { return $"{BuildId[..Math.Min(16, BuildId.Length)]}:{FunctionName}+0x{Offset:x}"; } /// /// Parses a canonical string format. /// public static CanonicalSymbol? Parse(string canonical) { if (string.IsNullOrWhiteSpace(canonical)) return null; // Format: "buildid:function+0xoffset" var colonIdx = canonical.IndexOf(':'); if (colonIdx < 0) return null; var buildId = canonical[..colonIdx]; var rest = canonical[(colonIdx + 1)..]; var plusIdx = rest.LastIndexOf('+'); if (plusIdx < 0) return null; var functionName = rest[..plusIdx]; var offsetStr = rest[(plusIdx + 1)..]; if (!offsetStr.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) return null; if (!ulong.TryParse(offsetStr[2..], System.Globalization.NumberStyles.HexNumber, null, out var offset)) return null; return new CanonicalSymbol { Address = 0, // Not recoverable from canonical string BuildId = buildId, FunctionName = functionName, Offset = offset, ResolutionMethod = SymbolResolutionMethod.Parsed, }; } } /// /// Method used to resolve the symbol. /// public enum SymbolResolutionMethod { /// /// Resolved from ELF symbol table. /// ElfSymtab, /// /// Resolved from DWARF debug info. /// DwarfDebugInfo, /// /// Resolved from local symbol cache. /// LocalCache, /// /// Resolved from debuginfod server. /// Debuginfod, /// /// Resolved from JIT metadata (Java/V8/etc). /// JitMetadata, /// /// Resolved from runtime-specific mechanism. /// RuntimeSpecific, /// /// Parsed from canonical string format. /// Parsed, /// /// Could not resolve, using address only. /// Unresolved, } /// /// Symbol entry for cache storage. /// public sealed record SymbolEntry { /// /// Start address of the symbol. /// public required ulong StartAddress { get; init; } /// /// Size of the symbol in bytes. /// public required ulong Size { get; init; } /// /// Symbol name (demangled). /// public required string Name { get; init; } /// /// Symbol type. /// public SymbolType Type { get; init; } = SymbolType.Function; } /// /// Type of symbol. /// public enum SymbolType { Function, Object, Unknown, } /// /// Metadata for Java frame resolution. /// public sealed record JavaFrameMetadata { /// /// Class name. /// public string? ClassName { get; init; } /// /// Method name. /// public string? MethodName { get; init; } /// /// Method signature. /// public string? Signature { get; init; } /// /// Bytecode index. /// public int? BytecodeIndex { get; init; } /// /// Whether this is a JIT-compiled frame. /// public bool IsJit { get; init; } } /// /// Metadata for .NET frame resolution. /// public sealed record DotNetFrameMetadata { /// /// Type name. /// public string? TypeName { get; init; } /// /// Method name. /// public string? MethodName { get; init; } /// /// Method token. /// public uint? MethodToken { get; init; } /// /// IL offset. /// public int? IlOffset { get; init; } /// /// Assembly name. /// public string? AssemblyName { get; init; } } /// /// Metadata for Python frame resolution. /// public sealed record PythonFrameMetadata { /// /// Module name. /// public string? ModuleName { get; init; } /// /// Function name. /// public string? FunctionName { get; init; } /// /// Source file path. /// public string? SourceFile { get; init; } /// /// Line number. /// public int? LineNumber { get; init; } /// /// Python version. /// public string? PythonVersion { get; init; } }