Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Initial provisions for semantic Crossgen2 PDB validation #75172

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions src/tests/Common/CLRTest.CrossGen.targets
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,12 @@ if /i "$(AlwaysUseCrossGen2)" == "true" (
REM CrossGen2 Script
if defined RunCrossGen2 (
set ExtraCrossGen2Args=!ExtraCrossGen2Args! $(CrossGen2TestExtraArguments)
set CrossGen2TestCheckPdb=$(CrossGen2TestCheckPdb)
set __CreatePdb=$(__CreatePdb)

if defined LargeVersionBubble ( set ExtraCrossGen2Args=!ExtraCrossGen2Args! --inputbubble)
if defined CrossGen2TestCheckPdb ( set __CreatePdb=1)

set CrossGen2Status=0
set compilationDoneFlagFile=!ScriptPath!IL-CG2\done
if exist "IL-CG2" (
Expand All @@ -192,6 +196,7 @@ if defined RunCrossGen2 (
if defined CompositeBuildMode (
set ExtraCrossGen2Args=!ExtraCrossGen2Args! --composite
set __OutputFile=!scriptPath!\composite-r2r.dll
set __PdbFile=!scriptPath!\composite-r2r.ni.pdb
rem In composite mode, treat all dll's in the test folder as rooting inputs
set __InputFile=!scriptPath!IL-CG2\*.dll
call :CompileOneFileCrossgen2
Expand All @@ -200,6 +205,7 @@ if defined RunCrossGen2 (
set ExtraCrossGen2Args=!ExtraCrossGen2Args! -r:!scriptPath!IL-CG2\*.dll
for %%I in (!scriptPath!IL-CG2\*.dll) do (
set __OutputFile=!scriptPath!%%~nI.dll
set __PdbFile=!scriptPath!%%~nI.ni.pdb
set __InputFile=%%I
call :CompileOneFileCrossgen2
IF NOT !CrossGen2Status!==0 (
Expand All @@ -216,13 +222,14 @@ if defined RunCrossGen2 (
set __ResponseFile=!__OutputFile!.rsp
del /Q !__ResponseFile! 2>nul

set __Command=!_DebuggerFullPath!
REM Tests run locally need __TestDotNetCmd (set by runtest.py) or a compatible 5.0 dotnet runtime in the path
if defined __TestDotNetCmd (
set __Command=!__Command! "!__TestDotNetCmd!"
set __DotNet="!__TestDotNetCmd!"
) else (
set __Command=!__Command! "dotnet"
set __DotNet="dotnet"
)
set __Command=!_DebuggerFullPath!
set __Command=!__Command! !__DotNet!
set __Command=!__Command! "!CORE_ROOT!\crossgen2\crossgen2.dll"
set __Command=!__Command! @"!__ResponseFile!"
set __Command=!__Command! !ExtraCrossGen2Args!
Expand All @@ -237,7 +244,7 @@ if defined RunCrossGen2 (
echo -r:!CORE_ROOT!\netstandard.dll>>!__ResponseFile!
echo -O>>!__ResponseFile!

if not "$(__CreatePdb)" == "" (
if defined __CreatePdb (
echo --pdb>>!__ResponseFile!
)

Expand All @@ -259,6 +266,21 @@ if defined RunCrossGen2 (
endlocal
set CrossGen2Status=!ERRORLEVEL!
echo %time%

if !CrossGen2Status!==0 (
if defined CrossGen2TestCheckPdb (
set __CheckPdbCommand=!__DotNet!
set __CheckPdbCommand=!__CheckPdbCommand! "!CORE_ROOT!\PdbChecker\PdbChecker.dll"
set __CheckPdbCommand=!__CheckPdbCommand! !__PdbFile! @(CheckPdbSymbol->'%22%(Identity)%22', ' ')
echo "!__CheckPdbCommand!"
call !__CheckPdbCommand!
if not !ERRORLEVEL!==0 (
echo PDB check failed for file !__PdbFile! >2
set CrossGen2Status=42
)
)
)

Exit /b 0

:DoneCrossgen2Operations
Expand Down
3 changes: 2 additions & 1 deletion src/tests/Common/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<RunTimeDependencyCopyLocal Include="@(RunTimeDependencyCopyLocalFile -> '%(File)')" />
<RunTimeDependencyCopyLocal Include="$(TargetingPackPath)/*" />
<RunTimeDependencyCopyLocal Include="$(TargetingPackPath)/xunit.*" TargetDir="xunit/" />
<RunTimeDependencyCopyLocal Include="$(XUnitTestBinBase)/Common/PdbChecker/PdbChecker/*.*" TargetDir="PdbChecker/" />
</ItemGroup>

<ItemGroup>
Expand Down Expand Up @@ -174,7 +175,7 @@
<RuntimeDependencyCopyLocal Condition="'$(TargetOS)' != 'windows'" Include="$(MonoArtifactsPath)/libcoreclr$(LibSuffix)" TargetDir="" />
<RuntimeDependencyCopyLocal Condition="'$(TargetOS)' == 'windows'" Include="$(MonoArtifactsPath)coreclr$(LibSuffix)" TargetDir="" />
<RuntimeDependencyCopyLocal Include="$(MonoArtifactsPath)/libmono-component-*" TargetDir="" />
<RuntimeDependencyCopyLocal Include="$(MonoArtifactsPath)/*.dll" TargetDir="/" />
<RuntimeDependencyCopyLocal Include="$(MonoArtifactsPath)/*.dll" TargetDir="/" />
</ItemGroup>

<Copy
Expand Down
58 changes: 58 additions & 0 deletions src/tests/Common/PdbChecker/MSDiaSymbolReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.IO;
using Dia2Lib;

class MSDiaSymbolReader
{
private readonly IDiaDataSource _diaDataSource;
private readonly IDiaSession _diaSession;

private readonly List<string> _pdbSymbols;

public MSDiaSymbolReader(string pdbFile)
{
try
{
_diaDataSource = new DiaSourceClass();
_diaDataSource.loadDataFromPdb(pdbFile);
_diaDataSource.openSession(out _diaSession);

_pdbSymbols = new List<string>();

_diaSession.getSymbolsByAddr(out IDiaEnumSymbolsByAddr symbolEnum);
int symbolsTotal = 0;
for (IDiaSymbol symbol = symbolEnum.symbolByRVA(0); symbol != null; symbolEnum.Next(1, out symbol, out uint fetched))
{
symbolsTotal++;
if (symbol.symTag == (uint)SymTagEnum.SymTagFunction || symbol.symTag == (uint)SymTagEnum.SymTagPublicSymbol)
{
_pdbSymbols.Add(symbol.name);
}
}

Console.WriteLine("PDB file: {0}", pdbFile);
Console.WriteLine("Total symbols: {0}", symbolsTotal);
Console.WriteLine("Public symbols: {0}", _pdbSymbols.Count);
}
catch (Exception ex)
{
throw new Exception($"Error opening PDB file {pdbFile}", ex);
}
}

public void DumpSymbols()
{
Console.WriteLine("PDB public symbol list:");
foreach (string symbol in _pdbSymbols.OrderBy(s => s))
{
Console.WriteLine(symbol);
}
Console.WriteLine("End of PDB public symbol list");
}

public bool ContainsSymbol(string symbolName) => _pdbSymbols.Any(s => s.Contains(symbolName));
}
17 changes: 17 additions & 0 deletions src/tests/Common/PdbChecker/PdbChecker.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
</PropertyGroup>

<ItemGroup>
<Compile Include="*.cs" />

<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="$(TraceEventVersion)" />
</ItemGroup>

</Project>
25 changes: 25 additions & 0 deletions src/tests/Common/PdbChecker/PdbChecker.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32708.82
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PdbChecker", "PdbChecker.csproj", "{6247A503-5387-4BE1-ACA3-027CADA30CA9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6247A503-5387-4BE1-ACA3-027CADA30CA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6247A503-5387-4BE1-ACA3-027CADA30CA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6247A503-5387-4BE1-ACA3-027CADA30CA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6247A503-5387-4BE1-ACA3-027CADA30CA9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4033231C-763B-4C57-BA35-7C1AC007AD0E}
EndGlobalSection
EndGlobal
60 changes: 60 additions & 0 deletions src/tests/Common/PdbChecker/Program.cs
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.

using System;
using Dia2Lib;
class Program
{
public static int Main(string[] args)
{
try
{
TryMain(args);
return 0;
}
catch (Exception ex)
{
Console.Error.WriteLine("Fatal error: {0}", ex);
return 1;
}
}

private static void TryMain(string[] args)
{
if (args.Length == 0)
{
DisplayUsage();
return;
}
MSDiaSymbolReader reader = new MSDiaSymbolReader(args[0]);
int matchedSymbols = 0;
int missingSymbols = 0;
for (int symbolArgIndex = 1; symbolArgIndex < args.Length; symbolArgIndex++)
{
string symbolName = args[symbolArgIndex];
if (reader.ContainsSymbol(symbolName))
{
matchedSymbols++;
}
else
{
missingSymbols++;
Console.Error.WriteLine("Missing symbol: {0}", symbolName);
}
}
if (missingSymbols > 0)
{
reader.DumpSymbols();
throw new Exception($"{missingSymbols} missing symbols ({matchedSymbols} symbols matched)");
}
if (matchedSymbols > 0)
{
Console.WriteLine("Matched all {0} symbols", matchedSymbols);
}
}

private static void DisplayUsage()
{
Console.WriteLine("Usage: PdbChecker <pdb file to check> { <symbol to check for existence in the PDB file> }");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Diagnostics.Tools.RuntimeClient" Version="$(MicrosoftDiagnosticsToolsRuntimeClientVersion)" />
<ProjectReference Include="$(RepoRoot)\src\tests\Common\PdbChecker\PdbChecker.csproj" />
</ItemGroup>

<Target Name="Build" DependsOnTargets="$(TraversalBuildDependsOn)" />
Expand Down
7 changes: 7 additions & 0 deletions src/tests/readytorun/crossgen2/crossgen2smoke.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@

<!-- This is an explicit crossgen test -->
<AlwaysUseCrossGen2>true</AlwaysUseCrossGen2>
<CrossGen2TestCheckPdb>true</CrossGen2TestCheckPdb>
</PropertyGroup>

<ItemGroup>
<CheckPdbSymbol Include="System.Int32 Program+SomeClass::GetHashCode()" />
<CheckPdbSymbol Include="System.String Program::ObjectToStringOnGenericParamTestWorker(System.__Canon&amp;)" />
</ItemGroup>

<Import Project="smoketest.targets" />
</Project>