sprints work.

This commit is contained in:
master
2026-01-20 00:45:38 +02:00
parent b34bde89fa
commit 4903395618
275 changed files with 52785 additions and 79 deletions

View File

@@ -0,0 +1,90 @@
using System.Diagnostics;
using System.Diagnostics.Metrics;
namespace StellaOps.BinaryIndex.GroundTruth.Debuginfod.Internal;
/// <summary>
/// Diagnostics and metrics for the debuginfod connector.
/// </summary>
public sealed class DebuginfodDiagnostics
{
private readonly Counter<long> _fetchSuccessCounter;
private readonly Counter<long> _fetchNotFoundCounter;
private readonly Counter<long> _fetchErrorCounter;
private readonly Counter<long> _parseSuccessCounter;
private readonly Counter<long> _parseErrorCounter;
private readonly Counter<long> _mapSuccessCounter;
private readonly Counter<long> _mapErrorCounter;
private readonly Counter<long> _mapAocViolationCounter;
private readonly Histogram<long> _symbolCountHistogram;
public DebuginfodDiagnostics(IMeterFactory meterFactory)
{
var meter = meterFactory.Create("StellaOps.BinaryIndex.GroundTruth.Debuginfod");
_fetchSuccessCounter = meter.CreateCounter<long>(
"groundtruth.debuginfod.fetch.success",
unit: "{documents}",
description: "Number of successful debuginfod fetches");
_fetchNotFoundCounter = meter.CreateCounter<long>(
"groundtruth.debuginfod.fetch.not_found",
unit: "{documents}",
description: "Number of debuginfod fetches that returned 404");
_fetchErrorCounter = meter.CreateCounter<long>(
"groundtruth.debuginfod.fetch.error",
unit: "{documents}",
description: "Number of failed debuginfod fetches");
_parseSuccessCounter = meter.CreateCounter<long>(
"groundtruth.debuginfod.parse.success",
unit: "{documents}",
description: "Number of successful DWARF parses");
_parseErrorCounter = meter.CreateCounter<long>(
"groundtruth.debuginfod.parse.error",
unit: "{documents}",
description: "Number of failed DWARF parses");
_mapSuccessCounter = meter.CreateCounter<long>(
"groundtruth.debuginfod.map.success",
unit: "{observations}",
description: "Number of successful observation mappings");
_mapErrorCounter = meter.CreateCounter<long>(
"groundtruth.debuginfod.map.error",
unit: "{observations}",
description: "Number of failed observation mappings");
_mapAocViolationCounter = meter.CreateCounter<long>(
"groundtruth.debuginfod.map.aoc_violation",
unit: "{observations}",
description: "Number of AOC violations during mapping");
_symbolCountHistogram = meter.CreateHistogram<long>(
"groundtruth.debuginfod.symbols_per_binary",
unit: "{symbols}",
description: "Distribution of symbol counts per binary");
}
public void RecordFetchSuccess() => _fetchSuccessCounter.Add(1);
public void RecordFetchNotFound() => _fetchNotFoundCounter.Add(1);
public void RecordFetchError() => _fetchErrorCounter.Add(1);
public void RecordParseSuccess(int symbolCount)
{
_parseSuccessCounter.Add(1);
_symbolCountHistogram.Record(symbolCount);
}
public void RecordParseError() => _parseErrorCounter.Add(1);
public void RecordMapSuccess(int symbolCount)
{
_mapSuccessCounter.Add(1);
}
public void RecordMapError() => _mapErrorCounter.Add(1);
public void RecordMapAocViolation() => _mapAocViolationCounter.Add(1);
}

View File

@@ -0,0 +1,87 @@
using Microsoft.Extensions.Logging;
using StellaOps.BinaryIndex.GroundTruth.Abstractions;
namespace StellaOps.BinaryIndex.GroundTruth.Debuginfod.Internal;
/// <summary>
/// ELF/DWARF parser implementation.
///
/// NOTE: LibObjectFile 1.0.0 has significant API changes from 0.x.
/// This is a stub implementation pending API migration.
/// See: https://github.com/xoofx/LibObjectFile/releases/tag/1.0.0
/// </summary>
public sealed class ElfDwarfParser : IDwarfParser
{
private readonly ILogger<ElfDwarfParser> _logger;
public ElfDwarfParser(ILogger<ElfDwarfParser> logger)
{
_logger = logger;
}
/// <inheritdoc/>
public Task<IReadOnlyList<ObservedSymbol>> ParseSymbolsAsync(Guid payloadId, CancellationToken ct = default)
{
throw new NotImplementedException(
"Parsing from payload ID requires blob storage integration. Use stream overload instead.");
}
/// <inheritdoc/>
public Task<IReadOnlyList<ObservedSymbol>> ParseSymbolsAsync(Stream stream, CancellationToken ct = default)
{
ArgumentNullException.ThrowIfNull(stream);
_logger.LogWarning(
"ElfDwarfParser is a stub - LibObjectFile 1.0.0 API migration pending. " +
"Returning empty symbol list.");
return Task.FromResult<IReadOnlyList<ObservedSymbol>>(Array.Empty<ObservedSymbol>());
}
/// <inheritdoc/>
public Task<string?> ExtractBuildIdAsync(Stream stream, CancellationToken ct = default)
{
ArgumentNullException.ThrowIfNull(stream);
_logger.LogWarning(
"ElfDwarfParser.ExtractBuildIdAsync is a stub - LibObjectFile 1.0.0 API migration pending.");
// Try to read build-id using simple heuristics
try
{
// Look for .note.gnu.build-id section marker
using var reader = new BinaryReader(stream, System.Text.Encoding.UTF8, leaveOpen: true);
// Reset to start
stream.Position = 0;
// Read ELF header to verify it's an ELF file
var magic = reader.ReadBytes(4);
if (magic.Length < 4 || magic[0] != 0x7f || magic[1] != 'E' || magic[2] != 'L' || magic[3] != 'F')
{
_logger.LogDebug("Not an ELF file");
return Task.FromResult<string?>(null);
}
_logger.LogDebug("ELF file detected, but full parsing requires LibObjectFile API migration");
return Task.FromResult<string?>(null);
}
catch (Exception ex)
{
_logger.LogDebug(ex, "Failed to read ELF header");
return Task.FromResult<string?>(null);
}
}
/// <inheritdoc/>
public Task<ObservedBuildMetadata?> ExtractBuildMetadataAsync(Stream stream, CancellationToken ct = default)
{
ArgumentNullException.ThrowIfNull(stream);
_logger.LogWarning(
"ElfDwarfParser.ExtractBuildMetadataAsync is a stub - LibObjectFile 1.0.0 API migration pending.");
return Task.FromResult<ObservedBuildMetadata?>(null);
}
}

View File

@@ -0,0 +1,80 @@
using StellaOps.BinaryIndex.GroundTruth.Abstractions;
namespace StellaOps.BinaryIndex.GroundTruth.Debuginfod.Internal;
/// <summary>
/// Interface for parsing DWARF debug information from ELF binaries.
/// </summary>
public interface IDwarfParser
{
/// <summary>
/// Parse symbols from a stored payload.
/// </summary>
/// <param name="payloadId">Blob storage ID for the ELF binary.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>List of parsed symbols.</returns>
Task<IReadOnlyList<ObservedSymbol>> ParseSymbolsAsync(Guid payloadId, CancellationToken ct = default);
/// <summary>
/// Parse symbols from a stream.
/// </summary>
/// <param name="stream">ELF binary stream.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>List of parsed symbols.</returns>
Task<IReadOnlyList<ObservedSymbol>> ParseSymbolsAsync(Stream stream, CancellationToken ct = default);
/// <summary>
/// Extract build ID from an ELF binary.
/// </summary>
/// <param name="stream">ELF binary stream.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>Build ID as hex string, or null if not found.</returns>
Task<string?> ExtractBuildIdAsync(Stream stream, CancellationToken ct = default);
/// <summary>
/// Extract build metadata from DWARF debug info.
/// </summary>
/// <param name="stream">ELF binary stream.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>Build metadata.</returns>
Task<ObservedBuildMetadata?> ExtractBuildMetadataAsync(Stream stream, CancellationToken ct = default);
}
/// <summary>
/// Stub implementation of DWARF parser for initial development.
/// Production implementation would use Gimli (Rust) or libdw bindings.
/// </summary>
public sealed class StubDwarfParser : IDwarfParser
{
/// <inheritdoc/>
public Task<IReadOnlyList<ObservedSymbol>> ParseSymbolsAsync(Guid payloadId, CancellationToken ct = default)
{
// Stub: Return empty list
// Production: Load from blob storage and parse
return Task.FromResult<IReadOnlyList<ObservedSymbol>>([]);
}
/// <inheritdoc/>
public Task<IReadOnlyList<ObservedSymbol>> ParseSymbolsAsync(Stream stream, CancellationToken ct = default)
{
// Stub: Return empty list
// Production: Parse ELF + DWARF sections
return Task.FromResult<IReadOnlyList<ObservedSymbol>>([]);
}
/// <inheritdoc/>
public Task<string?> ExtractBuildIdAsync(Stream stream, CancellationToken ct = default)
{
// Stub: Return null
// Production: Read .note.gnu.build-id section
return Task.FromResult<string?>(null);
}
/// <inheritdoc/>
public Task<ObservedBuildMetadata?> ExtractBuildMetadataAsync(Stream stream, CancellationToken ct = default)
{
// Stub: Return null
// Production: Parse DW_AT_producer and other DWARF attributes
return Task.FromResult<ObservedBuildMetadata?>(null);
}
}