Add a source-build smoke test for native debug symbols (#16488)

This commit is contained in:
Omair Majid 2023-08-09 09:31:40 -04:00 committed by GitHub
parent 29e196f12b
commit c796ecb165
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 131 additions and 0 deletions

View file

@ -0,0 +1,122 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.DotNet.SourceBuild.SmokeTests;
public class DebugTests : SmokeTests
{
private record ScanResult(string FileName, bool HasDebugInfo, bool HasDebugAbbrevs, bool HasFileSymbols, bool HasGnuDebugLink);
public DebugTests(ITestOutputHelper outputHelper) : base(outputHelper) { }
/// <Summary>
/// Verifies that all generated native files include native debug symbols.
/// </Summary>
[Fact]
public void SourceBuiltSdkContainsNativeDebugSymbols()
{
var fileNames = Directory.EnumerateFiles(Config.DotNetDirectory, "*", SearchOption.AllDirectories);
var foundIssue = false;
StringBuilder issueDetails = new();
foreach (var fileName in fileNames)
{
if (!IsElfFile(fileName))
{
continue;
}
var result = ScanFile(fileName);
string newLine = Environment.NewLine;
if (!result.HasDebugInfo)
{
foundIssue = true;
issueDetails.Append($"missing .debug_info section in {fileName}{newLine}");
}
if (!result.HasDebugAbbrevs)
{
foundIssue = true;
issueDetails.Append($"missing .debug_abbrev section in {fileName}{newLine}");
}
if (!result.HasFileSymbols)
{
foundIssue = true;
issueDetails.Append($"missing FILE symbols in {fileName}{newLine}");
}
if (result.HasGnuDebugLink)
{
foundIssue = true;
issueDetails.Append($"unexpected .gnu_debuglink section in {fileName}{newLine}");
}
}
Assert.False(foundIssue, issueDetails.ToString());
}
private bool IsElfFile(string fileName)
{
string fileStdOut = ExecuteHelper.ExecuteProcessValidateExitCode("file", $"{fileName}", OutputHelper);
return Regex.IsMatch(fileStdOut, @"ELF 64-bit [LM]SB (?:pie )?(?:executable|shared object)");
}
private ScanResult ScanFile(string fileName)
{
string readelfSStdOut = ExecuteHelper.ExecuteProcessValidateExitCode("eu-readelf", $"-S {fileName}", OutputHelper);
// Test for .debug_* sections in the shared object. This is the main test.
// Stripped objects will not contain these.
bool hasDebugInfo = readelfSStdOut
.Split("\n")
.Where(line => line.Contains("] .debug_info"))
.Any();
bool hasDebugAbbrev = readelfSStdOut.Split("\n")
.Where(line => line.Contains("] .debug_abbrev"))
.Any();
string readelfsStdOut = ExecuteHelper.ExecuteProcessValidateExitCode("eu-readelf", $"-s {fileName}", OutputHelper);
// Test FILE symbols. These will most likely be removed by anyting that
// manipulates symbol tables because it's generally useless. So a nice test
// that nothing has messed with symbols.
bool hasFileSymbols = readelfsStdOut.Split("\n").Where(ContainsFileSymbols).Any();
// Test that there are no .gnu_debuglink sections pointing to another
// debuginfo file. There shouldn't be any debuginfo files, so the link makes
// no sense either.
bool hasGnuDebuglink = readelfsStdOut.Split("\n").Where(line => line.Contains("] .gnu_debuglink")).Any();
return new ScanResult(fileName, hasDebugInfo, hasDebugAbbrev, hasFileSymbols, hasGnuDebuglink);
}
private bool ContainsFileSymbols(string line)
{
// Try matching against output like this:
// 10: 0000000000000000 0 FILE LOCAL DEFAULT ABS coreclr_resolver.cpp
// 779: 0000000000000000 0 FILE LOCAL DEFAULT ABS header.cpp
var parts = new Regex(@"[ \t\n\r]+").Split(line);
int expectedNumberOfParts = 9;
if (parts.Length < expectedNumberOfParts)
{
return false;
}
var fileNameRegex = new Regex(@"(.*/)?[-_a-zA-Z0-9]+\.(c|cc|cpp|cxx)");
return (parts[3] == "0") && (parts[4] == "FILE") && (parts[5] == "LOCAL") && (parts[6] == "DEFAULT") &&
(parts[7] == "ABS") && (fileNameRegex.IsMatch(parts[8]));
}
}

View file

@ -3,6 +3,15 @@
* Run these tests via `build.sh --run-smoke-test`
* Various configuration settings are stored in `Config.cs`
## Dependencies
Some tests need additional dependencies. These must be installed (manually and separately) on the system for the tests to pass.
The following programs are used by some tests:
- eu-readelf
- file
## Prereq Packages
Some prerelease scenarios, usually security updates, require non-source-built packages which are not publicly available.