-
Notifications
You must be signed in to change notification settings - Fork 446
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Viktor Hofer <viktor.hofer@microsoft.com>
- Loading branch information
1 parent
bf738fd
commit 94d9faf
Showing
4 changed files
with
163 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.UnifiedBuild.Tasks/PdbUtilities.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// 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.Reflection.Metadata; | ||
using System.Reflection.PortableExecutable; | ||
|
||
namespace Microsoft.DotNet.UnifiedBuild.Tasks | ||
{ | ||
public static class PdbUtilities | ||
{ | ||
// Checks if a file in Sdk layout requires an external Pdb. | ||
// Also returns the Pdb GUID, if one was found in PE. | ||
public static bool FileInSdkLayoutRequiresAPdb(string file, out string guid) | ||
{ | ||
guid = string.Empty; | ||
|
||
// Files under packs/ are used for build only, no need for Pdbs | ||
return !file.Contains(Path.DirectorySeparatorChar + "packs" + Path.DirectorySeparatorChar) ? | ||
FileHasCompanionPdbInfo(file, out guid) : | ||
false; | ||
} | ||
|
||
// Checks if a file has debug data indicating an external companion Pdb. | ||
// Also returns the Pdb GUID, if one was found in PE. | ||
private static bool FileHasCompanionPdbInfo(string file, out string guid) | ||
{ | ||
guid = string.Empty; | ||
|
||
if (file.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase) && | ||
!file.EndsWith(".resources.dll", StringComparison.InvariantCultureIgnoreCase)) | ||
{ | ||
using var pdbStream = File.OpenRead(file); | ||
using var peReader = new PEReader(pdbStream); | ||
try | ||
{ | ||
// Check if pdb is embedded | ||
if (peReader.ReadDebugDirectory().Any(entry => entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb)) | ||
{ | ||
return false; | ||
} | ||
|
||
var debugDirectory = peReader.ReadDebugDirectory().First(entry => entry.Type == DebugDirectoryEntryType.CodeView); | ||
var codeViewData = peReader.ReadCodeViewDebugDirectoryData(debugDirectory); | ||
guid = $"{codeViewData.Guid.ToString("N").Replace("-", string.Empty)}"; | ||
} | ||
catch (Exception e) when (e is BadImageFormatException || e is InvalidOperationException) | ||
{ | ||
// Ignore binaries without debug info | ||
return false; | ||
} | ||
} | ||
|
||
return guid != string.Empty; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SymbolsTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// 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.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Xunit; | ||
using Xunit.Abstractions; | ||
using Microsoft.DotNet.UnifiedBuild.Tasks; | ||
|
||
namespace Microsoft.DotNet.SourceBuild.SmokeTests; | ||
|
||
public class SymbolsTests : SdkTests | ||
{ | ||
private static string SymbolsTestsRoot { get; } = Path.Combine(Directory.GetCurrentDirectory(), nameof(SymbolsTests)); | ||
|
||
public SymbolsTests(ITestOutputHelper outputHelper) : base(outputHelper) { } | ||
|
||
/// <summary> | ||
/// Verifies that all symbols have valid sourcelinks. | ||
/// </summary> | ||
[Fact] | ||
public void VerifySdkSymbols() | ||
{ | ||
try | ||
{ | ||
if (Directory.Exists(SymbolsTestsRoot)) | ||
{ | ||
Directory.Delete(SymbolsTestsRoot, true); | ||
} | ||
Directory.CreateDirectory(SymbolsTestsRoot); | ||
|
||
string symbolsRoot = Directory.CreateDirectory(Path.Combine(SymbolsTestsRoot, "symbols")).FullName; | ||
|
||
// We are validating dotnet-symbols-sdk-*.tar.gz which contains source-built sdk symbols | ||
Utilities.ExtractTarball( | ||
Utilities.GetFile(Path.GetDirectoryName(Config.SourceBuiltArtifactsPath)!, "dotnet-symbols-sdk-*.tar.gz"), | ||
symbolsRoot, | ||
OutputHelper); | ||
|
||
IList<string> failedFiles = VerifySdkFilesHaveMatchingSymbols(symbolsRoot, Config.DotNetDirectory); | ||
|
||
if (failedFiles.Count > 0) | ||
{ | ||
OutputHelper.WriteLine($"Did not find PDBs for the following SDK files:"); | ||
foreach (string file in failedFiles) | ||
{ | ||
OutputHelper.WriteLine(file); | ||
} | ||
} | ||
|
||
Assert.True(failedFiles.Count == 0); | ||
} | ||
finally | ||
{ | ||
Directory.Delete(SymbolsTestsRoot, true); | ||
} | ||
} | ||
|
||
private IList<string> VerifySdkFilesHaveMatchingSymbols(string symbolsRoot, string sdkRoot) | ||
{ | ||
Assert.True(Directory.Exists(sdkRoot), $"Path, with SDK files to validate, does not exist: {sdkRoot}"); | ||
|
||
var failedFiles = new ConcurrentBag<string>(); | ||
|
||
IEnumerable<string> allFiles = Directory.GetFiles(sdkRoot, "*", SearchOption.AllDirectories); | ||
Parallel.ForEach(allFiles, file => | ||
{ | ||
if (PdbUtilities.FileInSdkLayoutRequiresAPdb(file, out string guid)) | ||
{ | ||
string symbolFile = Path.ChangeExtension(file.Replace(sdkRoot, symbolsRoot), ".pdb"); | ||
if (!File.Exists(symbolFile)) | ||
{ | ||
failedFiles.Add(file); | ||
} | ||
} | ||
}); | ||
|
||
return failedFiles.ToList(); | ||
} | ||
} |