sprints work.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user