remove test dependency on peverify.exe (#4001)
* remove test dependency on peverify.exe * enable metadata-only validation
This commit is contained in:
Родитель
62e9bdfe60
Коммит
95fd5e5569
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27102.0
|
||||
VisualStudioVersion = 15.0.27116.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Private", "src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}"
|
||||
EndProject
|
||||
|
@ -138,6 +138,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceFile", "vsintegrati
|
|||
EndProject
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Build.UnitTests", "src\fsharp\FSharp.Build.UnitTests\FSharp.Build.UnitTests.fsproj", "{400FAB03-786E-40CC-85A8-04B0C2869B14}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PEVerify", "tests\fsharpqa\testenv\src\PEVerify\PEVerify.csproj", "{B0689A4E-07D8-494D-A0C8-791CB1D74E54}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -760,6 +762,18 @@ Global
|
|||
{400FAB03-786E-40CC-85A8-04B0C2869B14}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{400FAB03-786E-40CC-85A8-04B0C2869B14}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{400FAB03-786E-40CC-85A8-04B0C2869B14}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54}.Proto|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54}.Proto|x86.ActiveCfg = Debug|Any CPU
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54}.Proto|x86.Build.0 = Debug|Any CPU
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -823,6 +837,7 @@ Global
|
|||
{FF76BD3C-5E0A-4752-B6C3-044F6E15719B} = {35636A82-401A-4C3A-B2AB-EB7DC5E9C268}
|
||||
{0385564F-07B4-4264-AB8A-17C393E9140C} = {F6DAEE9A-8BE1-4C4A-BC83-09215517C7DA}
|
||||
{400FAB03-786E-40CC-85A8-04B0C2869B14} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449}
|
||||
{B0689A4E-07D8-494D-A0C8-791CB1D74E54} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {48EDBBBE-C8EE-4E3C-8B19-97184A487B37}
|
||||
|
|
|
@ -73,11 +73,17 @@
|
|||
|
||||
<ItemGroup Condition="'$(TEST_CORECLR_FSHARP_SUITE)'=='1'" >
|
||||
<ProjectsWithCoreClr Include="tests/fsharp/FSharp.Tests.FSharpSuite.DrivingCoreCLR/FSharp.Tests.FSharpSuite.DrivingCoreCLR.fsproj" />
|
||||
<ProjectsWithCoreClr Include="tests/fsharpqa/testenv/src/PEVerify/PEVerify.csproj" />
|
||||
|
||||
<ProjectsToRestore Include="tests/fsharpqa/testenv/src/PEVerify/PEVerify.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TEST_NET40_FSHARPQA_SUITE)'=='1' OR '$(TEST_NET40_FSHARP_SUITE)'=='1'" >
|
||||
<ProjectsWithNet40 Include="tests/fsharpqa/testenv/src/ILComparer/ILComparer.fsproj" />
|
||||
<ProjectsWithNet40 Include="tests/fsharpqa/testenv/src/HostedCompilerServer/HostedCompilerServer.fsproj" />
|
||||
<ProjectsWithNet40 Include="tests/fsharpqa/testenv/src/PEVerify/PEVerify.csproj" />
|
||||
|
||||
<ProjectsToRestore Include="tests/fsharpqa/testenv/src/PEVerify/PEVerify.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TEST_VS_IDEUNIT_SUITE)'=='1'" >
|
||||
|
@ -112,4 +118,9 @@
|
|||
<MSBuild Projects="@(NugetProjects)" Targets="Clean" BuildInParallel="false" Properties="Configuration=$(Configuration);$(CustomProps)" />
|
||||
<MSBuild Projects="@(SetupProjects)" Targets="Clean" BuildInParallel="false" Properties="Configuration=$(Configuration);BUILD_PUBLICSIGN=$(BUILD_PUBLICSIGN);$(CustomProps)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="Restore">
|
||||
<MSBuild Projects="@(ProjectsToRestore)" Targets="Restore" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -664,8 +664,11 @@ if "%BUILD_PROTO%" == "1" (
|
|||
echo ---------------- Done with proto, starting build ------------------------
|
||||
|
||||
if "%BUILD_PHASE%" == "1" (
|
||||
echo %_msbuildexe% %msbuildflags% build-everything.proj /p:Configuration=%BUILD_CONFIG% %BUILD_DIAG% /p:BUILD_PUBLICSIGN=%BUILD_PUBLICSIGN%
|
||||
%_msbuildexe% %msbuildflags% build-everything.proj /p:Configuration=%BUILD_CONFIG% %BUILD_DIAG% /p:BUILD_PUBLICSIGN=%BUILD_PUBLICSIGN%
|
||||
echo %_msbuildexe% %msbuildflags% build-everything.proj /t:Restore
|
||||
%_msbuildexe% %msbuildflags% build-everything.proj /t:Restore
|
||||
|
||||
echo %_msbuildexe% %msbuildflags% build-everything.proj /p:Configuration=%BUILD_CONFIG% %BUILD_DIAG% /p:BUILD_PUBLICSIGN=%BUILD_PUBLICSIGN%
|
||||
%_msbuildexe% %msbuildflags% build-everything.proj /p:Configuration=%BUILD_CONFIG% %BUILD_DIAG% /p:BUILD_PUBLICSIGN=%BUILD_PUBLICSIGN%
|
||||
|
||||
@if ERRORLEVEL 1 echo Error build failed && goto :failure
|
||||
)
|
||||
|
|
|
@ -106,7 +106,6 @@ module Commands =
|
|||
type TestConfig =
|
||||
{ EnvironmentVariables : Map<string, string>
|
||||
CORDIR : string
|
||||
CORSDK : string
|
||||
CSC : string
|
||||
csc_flags : string
|
||||
BUILD_CONFIG : string
|
||||
|
@ -132,7 +131,7 @@ module WindowsPlatform =
|
|||
[| "PROCESSOR_ARCHITECTURE" |] |> Seq.tryPick (fun s -> find s) |> function None -> "" | Some x -> x
|
||||
value = "AMD64"
|
||||
|
||||
let clrPaths envVars =
|
||||
let clrPath envVars =
|
||||
|
||||
let windir =
|
||||
match envVars |> Map.tryFind "windir" with
|
||||
|
@ -149,15 +148,7 @@ module WindowsPlatform =
|
|||
if Is64BitOperatingSystem envVars then
|
||||
CORDIR <- CORDIR.Replace("Framework", "Framework64")
|
||||
|
||||
let CORSDK =
|
||||
let find s = envVars |> Map.tryFind s
|
||||
[| "WINSDKNETFXTOOLS"; "WindowsSDK_ExecutablePath_x64"; "WindowsSDK_ExecutablePath_x86" |]
|
||||
|> Seq.tryPick find
|
||||
|> function
|
||||
| None -> @"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\x64\"
|
||||
| Some x -> x
|
||||
|
||||
CORDIR, CORSDK
|
||||
CORDIR
|
||||
|
||||
type FSLibPaths =
|
||||
{ FSCOREDLLPATH : string }
|
||||
|
@ -173,13 +164,13 @@ let config configurationName envVars =
|
|||
let csc_flags = "/nologo"
|
||||
let fsc_flags = "-r:System.Core.dll --nowarn:20 --define:COMPILED"
|
||||
let fsi_flags = "-r:System.Core.dll --nowarn:20 --define:INTERACTIVE --maxerrors:1 --abortonerror"
|
||||
let CORDIR, CORSDK = WindowsPlatform.clrPaths envVars
|
||||
let CORDIR = WindowsPlatform.clrPath envVars
|
||||
let Is64BitOperatingSystem = WindowsPlatform.Is64BitOperatingSystem envVars
|
||||
let architectureMoniker = if Is64BitOperatingSystem then "x64" else "x86"
|
||||
let CSC = requireFile (CORDIR ++ "csc.exe")
|
||||
let ILDASM = requireFile (packagesDir ++ ("runtime.win-" + architectureMoniker + ".Microsoft.NETCore.ILDAsm.2.0.3") ++ "runtimes" ++ ("win-" + architectureMoniker) ++ "native" ++ "ildasm.exe")
|
||||
let coreclrdll = requireFile (packagesDir ++ ("runtime.win-" + architectureMoniker + ".Microsoft.NETCore.Runtime.CoreCLR.2.0.3") ++ "runtimes" ++ ("win-" + architectureMoniker) ++ "native" ++ "coreclr.dll")
|
||||
let PEVERIFY = requireFile (CORSDK ++ "peverify.exe")
|
||||
let PEVERIFY = requireFile (SCRIPT_ROOT ++ ".." ++ "fsharpqa" ++ "testenv" ++ "src" ++ "PEVerify" ++ "bin" ++ configurationName ++ "net46" ++ "PEVerify.exe")
|
||||
let FSI_FOR_SCRIPTS =
|
||||
match envVars |> Map.tryFind "_fsiexe" with
|
||||
| Some fsiexe when (not (String.IsNullOrWhiteSpace fsiexe)) -> requireFile (SCRIPT_ROOT ++ ".." ++ ".." ++ (fsiexe.Trim([| '\"' |])))
|
||||
|
@ -214,7 +205,6 @@ let config configurationName envVars =
|
|||
|
||||
{ EnvironmentVariables = envVars
|
||||
CORDIR = CORDIR |> Commands.pathAddBackslash
|
||||
CORSDK = CORSDK |> Commands.pathAddBackslash
|
||||
FSCBinPath = FSCBinPath |> Commands.pathAddBackslash
|
||||
FSCOREDLLPATH = FSCOREDLLPATH
|
||||
ILDASM = ILDASM
|
||||
|
@ -236,7 +226,6 @@ let logConfig (cfg: TestConfig) =
|
|||
log "Executables"
|
||||
log ""
|
||||
log "CORDIR =%s" cfg.CORDIR
|
||||
log "CORSDK =%s" cfg.CORSDK
|
||||
log "CSC =%s" cfg.CSC
|
||||
log "BUILD_CONFIG =%s" cfg.BUILD_CONFIG
|
||||
log "csc_flags =%s" cfg.csc_flags
|
||||
|
|
|
@ -264,11 +264,14 @@ if($ENV{REDUCED_RUNTIME} ne "1"){
|
|||
# check/set PEVerify
|
||||
my $PEVERIFY = $ENV{PEVERIFY};
|
||||
unless(defined($PEVERIFY)) {
|
||||
# Only use peverify if it is in the path
|
||||
foreach $_ (split /;/, $ENV{PATH}) {
|
||||
$PEVERIFY = "peverify.exe" if(-e "$_\\peverify.exe");
|
||||
my $scriptPath = dirname(__FILE__);
|
||||
$PEVERIFY = "$scriptPath\\..\\testenv\\src\\PEVerify\\bin\\Release\\net46\\PEVerify.exe";
|
||||
if (-e $PEVERIFY) {
|
||||
$ENV{PEVERIFY} = $PEVERIFY;
|
||||
}
|
||||
else {
|
||||
$ENV{PEVERIFY} = "$scriptPath\\..\\testenv\\src\\PEVerify\\bin\\Debug\\net46\\PEVerify.exe";
|
||||
}
|
||||
$ENV{PEVERIFY} = $PEVERIFY;
|
||||
}
|
||||
|
||||
# Use $ENV{PEVER} if it is defined
|
||||
|
|
|
@ -0,0 +1,344 @@
|
|||
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
// ported from https://github.com/dotnet/roslyn/blob/aaee215045c03c4f4b38a66b56d35261ee7f0ddc/src/Test/Utilities/Portable/Platform/Desktop/CLRHelpers.cs
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using PEVerify;
|
||||
using Roslyn.Test.Utilities.Desktop.ComTypes;
|
||||
|
||||
namespace Roslyn.Test.Utilities.Desktop
|
||||
{
|
||||
public static class CLRHelpers
|
||||
{
|
||||
private static readonly Guid s_clsIdClrRuntimeHost = new Guid("90F1A06E-7712-4762-86B5-7A5EBA6BDB02");
|
||||
private static readonly Guid s_clsIdCorMetaDataDispenser = new Guid("E5CB7A31-7512-11d2-89CE-0080C792E5D8");
|
||||
|
||||
public static event ResolveEventHandler ReflectionOnlyAssemblyResolve;
|
||||
|
||||
static CLRHelpers()
|
||||
{
|
||||
// Work around CLR bug:
|
||||
// PE Verifier adds a handler to ReflectionOnlyAssemblyResolve event in AppDomain.EnableResolveAssembliesForIntrospection
|
||||
// (called from ValidateWorker in Validator.cpp) in which it directly calls Assembly.ReflectionOnlyLoad.
|
||||
// If that happens before we get a chance to resolve the assembly the resolution fails.
|
||||
//
|
||||
// The handlers are invoked in the order they were added until one of them returns non-null assembly.
|
||||
// Therefore once we call Validate we can't add any more handlers -- they would all follow the CLR one, which fails.
|
||||
//
|
||||
// As A workaround we add a single forwarding handler before any calls to Validate and then subscribe all of our true handlers
|
||||
// to this event.
|
||||
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ReflectionOnlyAssemblyResolveHandler;
|
||||
}
|
||||
|
||||
private static Assembly ReflectionOnlyAssemblyResolveHandler(object sender, ResolveEventArgs args)
|
||||
{
|
||||
var handler = ReflectionOnlyAssemblyResolve;
|
||||
if (handler != null)
|
||||
{
|
||||
return handler(sender, args);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static object GetRuntimeInterfaceAsObject(Guid clsid, Guid riid)
|
||||
{
|
||||
// This API isn't available on Mono hence we must use reflection to access it.
|
||||
Debug.Assert(!MonoHelpers.IsRunningOnMono());
|
||||
|
||||
var getRuntimeInterfaceAsObject = typeof(RuntimeEnvironment).GetMethod("GetRuntimeInterfaceAsObject", BindingFlags.Public | BindingFlags.Static);
|
||||
return getRuntimeInterfaceAsObject.Invoke(null, new object[] { clsid, riid });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the specified image. Subscribe to <see cref="ReflectionOnlyAssemblyResolve"/> to provide a loader for dependent assemblies.
|
||||
/// </summary>
|
||||
public static string[] PeVerify(byte[] peImage, bool metadataOnly)
|
||||
{
|
||||
// fileName must be null, otherwise AssemblyResolve events won't fire
|
||||
return PeVerify(peImage, AppDomain.CurrentDomain.Id, assemblyPath: null, metadataOnly: metadataOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the specified file. All dependencies must be on disk next to the file.
|
||||
/// </summary>
|
||||
public static string[] PeVerify(string filePath, bool metadataOnly)
|
||||
{
|
||||
return PeVerify(File.ReadAllBytes(filePath), AppDomain.CurrentDomain.Id, filePath, metadataOnly: metadataOnly);
|
||||
}
|
||||
|
||||
private static readonly object s_guard = new object();
|
||||
|
||||
private static string[] PeVerify(byte[] peImage, int domainId, string assemblyPath, bool metadataOnly)
|
||||
{
|
||||
if (MonoHelpers.IsRunningOnMono())
|
||||
{
|
||||
// PEverify is currently unsupported on Mono hence return an empty
|
||||
// set of messages
|
||||
return new string[0];
|
||||
}
|
||||
|
||||
lock (s_guard)
|
||||
{
|
||||
GCHandle pinned = GCHandle.Alloc(peImage, GCHandleType.Pinned);
|
||||
try
|
||||
{
|
||||
IntPtr buffer = pinned.AddrOfPinnedObject();
|
||||
|
||||
ICLRValidator validator = (ICLRValidator)GetRuntimeInterfaceAsObject(s_clsIdClrRuntimeHost, typeof(ICLRRuntimeHost).GUID);
|
||||
ValidationErrorHandler errorHandler = new ValidationErrorHandler(validator);
|
||||
|
||||
IMetaDataDispenser dispenser = (IMetaDataDispenser)GetRuntimeInterfaceAsObject(s_clsIdCorMetaDataDispenser, typeof(IMetaDataDispenser).GUID);
|
||||
|
||||
// the buffer needs to be pinned during validation
|
||||
Guid riid = typeof(IMetaDataImport).GUID;
|
||||
object metaDataImport = null;
|
||||
if (assemblyPath != null)
|
||||
{
|
||||
dispenser.OpenScope(assemblyPath, CorOpenFlags.ofRead, ref riid, out metaDataImport);
|
||||
}
|
||||
else
|
||||
{
|
||||
dispenser.OpenScopeOnMemory(buffer, (uint)peImage.Length, CorOpenFlags.ofRead, ref riid, out metaDataImport);
|
||||
}
|
||||
|
||||
IMetaDataValidate metaDataValidate = (IMetaDataValidate)metaDataImport;
|
||||
metaDataValidate.ValidatorInit(CorValidatorModuleType.ValidatorModuleTypePE, errorHandler);
|
||||
metaDataValidate.ValidateMetaData();
|
||||
|
||||
if (!metadataOnly)
|
||||
{
|
||||
validator.Validate(errorHandler, (uint)domainId, ValidatorFlags.VALIDATOR_EXTRA_VERBOSE,
|
||||
ulMaxError: 10, token: 0, fileName: assemblyPath, pe: buffer, ulSize: (uint)peImage.Length);
|
||||
}
|
||||
|
||||
return errorHandler.GetOutput();
|
||||
}
|
||||
finally
|
||||
{
|
||||
pinned.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ValidationErrorHandler : IVEHandler
|
||||
{
|
||||
private readonly ICLRValidator _validator;
|
||||
private readonly List<string> _output;
|
||||
private const int MessageLength = 256;
|
||||
|
||||
public ValidationErrorHandler(ICLRValidator validator)
|
||||
{
|
||||
_validator = validator;
|
||||
_output = new List<string>();
|
||||
}
|
||||
|
||||
public void SetReporterFtn(long lFnPtr)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void VEHandler(int VECode, tag_VerError Context, Array psa)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(MessageLength);
|
||||
string message = null;
|
||||
|
||||
if (Context.Flags == (uint)ValidatorFlags.VALIDATOR_CHECK_PEFORMAT_ONLY)
|
||||
{
|
||||
GetErrorResourceString(VECode, sb);
|
||||
string formatString = ReplaceFormatItems(sb.ToString(), "%08x", ":x8");
|
||||
formatString = ReplaceFormatItems(formatString, "%d", "");
|
||||
if (psa == null)
|
||||
{
|
||||
psa = new object[0];
|
||||
}
|
||||
|
||||
message = string.Format(formatString, (object[])psa);
|
||||
}
|
||||
else
|
||||
{
|
||||
_validator.FormatEventInfo(VECode, Context, sb, (uint)MessageLength - 1, psa);
|
||||
message = sb.ToString();
|
||||
}
|
||||
|
||||
// retail version of peverify.exe filters out CLS warnings...
|
||||
if (!message.Contains("[CLS]"))
|
||||
{
|
||||
_output.Add(message);
|
||||
}
|
||||
}
|
||||
|
||||
public string[] GetOutput()
|
||||
{
|
||||
return _output.ToArray();
|
||||
}
|
||||
|
||||
private static readonly string s_resourceFilePath = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "mscorrc.dll");
|
||||
private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
|
||||
private static readonly IntPtr s_hMod = LoadLibraryEx(s_resourceFilePath, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
|
||||
|
||||
private static void GetErrorResourceString(int code, StringBuilder message)
|
||||
{
|
||||
LoadString(s_hMod, (uint)(code & 0x0000FFFF), message, MessageLength - 1);
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern int LoadString(IntPtr hInstance, uint uID, StringBuilder lpBuffer, int nBufferMax);
|
||||
|
||||
private static string ReplaceFormatItems(string input, string oldFormat, string newFormat)
|
||||
{
|
||||
// not foolproof/efficient, but easy to write/understand...
|
||||
var parts = input.Replace(oldFormat, "|").Split('|');
|
||||
|
||||
var formatString = new StringBuilder();
|
||||
for (int i = 0; i < parts.Length; i++)
|
||||
{
|
||||
formatString.Append(parts[i]);
|
||||
if (i < (parts.Length - 1))
|
||||
{
|
||||
formatString.Append('{');
|
||||
formatString.Append(i);
|
||||
formatString.Append(newFormat);
|
||||
formatString.Append('}');
|
||||
}
|
||||
}
|
||||
|
||||
return formatString.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace ComTypes
|
||||
{
|
||||
[ComImport, CoClass(typeof(object)), Guid("90F1A06C-7712-4762-86B5-7A5EBA6BDB02"), TypeIdentifier]
|
||||
public interface CLRRuntimeHost : ICLRRuntimeHost
|
||||
{
|
||||
}
|
||||
|
||||
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("90F1A06C-7712-4762-86B5-7A5EBA6BDB02"), TypeIdentifier]
|
||||
public interface ICLRRuntimeHost
|
||||
{
|
||||
}
|
||||
|
||||
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("63DF8730-DC81-4062-84A2-1FF943F59FDD"), TypeIdentifier]
|
||||
public interface ICLRValidator
|
||||
{
|
||||
void Validate(
|
||||
[In, MarshalAs(UnmanagedType.Interface)] IVEHandler veh,
|
||||
[In] uint ulAppDomainId,
|
||||
[In] ValidatorFlags ulFlags,
|
||||
[In] uint ulMaxError,
|
||||
[In] uint token,
|
||||
[In, MarshalAs(UnmanagedType.LPWStr)] string fileName,
|
||||
[In] IntPtr pe,
|
||||
[In] uint ulSize);
|
||||
|
||||
void FormatEventInfo(
|
||||
[In, MarshalAs(UnmanagedType.Error)] int hVECode,
|
||||
[In] tag_VerError Context,
|
||||
[In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder msg,
|
||||
[In] uint ulMaxLength,
|
||||
[In, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] Array psa);
|
||||
}
|
||||
|
||||
[ComImport, Guid("856CA1B2-7DAB-11D3-ACEC-00C04F86C309"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeIdentifier]
|
||||
public interface IVEHandler
|
||||
{
|
||||
void VEHandler([In, MarshalAs(UnmanagedType.Error)] int VECode, [In] tag_VerError Context, [In, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] Array psa);
|
||||
void SetReporterFtn([In] long lFnPtr);
|
||||
}
|
||||
|
||||
[ComImport, Guid("809C652E-7396-11D2-9771-00A0C9B4D50C"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeIdentifier]
|
||||
public interface IMetaDataDispenser
|
||||
{
|
||||
void DefineScope(
|
||||
[In] ref Guid rclsid,
|
||||
[In] uint dwCreateFlags,
|
||||
[In] ref Guid riid,
|
||||
[Out, MarshalAs(UnmanagedType.IUnknown)] out object ppIUnk);
|
||||
|
||||
void OpenScope(
|
||||
[In, MarshalAs(UnmanagedType.LPWStr)] string szScope,
|
||||
[In] CorOpenFlags dwOpenFlags,
|
||||
[In] ref Guid riid,
|
||||
[Out, MarshalAs(UnmanagedType.IUnknown)] out object ppIUnk);
|
||||
|
||||
void OpenScopeOnMemory(
|
||||
[In] IntPtr pData,
|
||||
[In] uint cbData,
|
||||
[In] CorOpenFlags dwOpenFlags,
|
||||
[In] ref Guid riid,
|
||||
[Out, MarshalAs(UnmanagedType.IUnknown)] out object ppIUnk);
|
||||
}
|
||||
|
||||
[ComImport, Guid("7DAC8207-D3AE-4c75-9B67-92801A497D44"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeIdentifier]
|
||||
public interface IMetaDataImport
|
||||
{
|
||||
}
|
||||
|
||||
[ComImport, Guid("4709C9C6-81FF-11D3-9FC7-00C04F79A0A3"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeIdentifier]
|
||||
public interface IMetaDataValidate
|
||||
{
|
||||
void ValidatorInit([In] CorValidatorModuleType dwModuleType, [In, MarshalAs(UnmanagedType.IUnknown)] object pUnk);
|
||||
void ValidateMetaData();
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4), TypeIdentifier("5477469e-83b1-11d2-8b49-00a0c9b7c9c4", "mscoree.tag_VerError")]
|
||||
public struct tag_VerError
|
||||
{
|
||||
public uint Flags;
|
||||
public uint opcode;
|
||||
public uint uOffset;
|
||||
public uint Token;
|
||||
public uint item1_flags;
|
||||
public IntPtr item1_data;
|
||||
public uint item2_flags;
|
||||
public IntPtr item2_data;
|
||||
}
|
||||
|
||||
public enum ValidatorFlags : uint
|
||||
{
|
||||
VALIDATOR_EXTRA_VERBOSE = 0x00000001,
|
||||
VALIDATOR_SHOW_SOURCE_LINES = 0x00000002,
|
||||
VALIDATOR_CHECK_ILONLY = 0x00000004,
|
||||
VALIDATOR_CHECK_PEFORMAT_ONLY = 0x00000008,
|
||||
VALIDATOR_NOCHECK_PEFORMAT = 0x00000010
|
||||
};
|
||||
|
||||
public enum CorValidatorModuleType : uint
|
||||
{
|
||||
ValidatorModuleTypeInvalid = 0x00000000,
|
||||
ValidatorModuleTypeMin = 0x00000001,
|
||||
ValidatorModuleTypePE = 0x00000001,
|
||||
ValidatorModuleTypeObj = 0x00000002,
|
||||
ValidatorModuleTypeEnc = 0x00000003,
|
||||
ValidatorModuleTypeIncr = 0x00000004,
|
||||
ValidatorModuleTypeMax = 0x00000004
|
||||
};
|
||||
|
||||
public enum CorOpenFlags : uint
|
||||
{
|
||||
ofRead = 0x00000000,
|
||||
ofWrite = 0x00000001,
|
||||
ofReadWriteMask = 0x00000001,
|
||||
ofCopyMemory = 0x00000002,
|
||||
ofCacheImage = 0x00000004,
|
||||
ofManifestMetadata = 0x00000008,
|
||||
ofReadOnly = 0x00000010,
|
||||
ofTakeOwnership = 0x00000020,
|
||||
ofNoTypeLib = 0x00000080,
|
||||
ofReserved1 = 0x00000100,
|
||||
ofReserved2 = 0x00000200,
|
||||
ofReserved = 0xffffff40,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace PEVerify
|
||||
{
|
||||
public class MonoHelpers
|
||||
{
|
||||
public static bool IsRunningOnMono()
|
||||
{
|
||||
return Type.GetType("Mono.Runtime") != null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net46</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Roslyn.Test.Utilities.Desktop;
|
||||
|
||||
namespace PEVerify
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static int Main(string[] args)
|
||||
{
|
||||
string assemblyPath = null;
|
||||
bool metadataOnly = false;
|
||||
foreach (var arg in args)
|
||||
{
|
||||
switch (arg.ToUpperInvariant())
|
||||
{
|
||||
case "/IL":
|
||||
case "/NOLOGO":
|
||||
case "/UNIQUE":
|
||||
// ignore these options
|
||||
break;
|
||||
case "/MD":
|
||||
metadataOnly = true;
|
||||
break;
|
||||
default:
|
||||
if (assemblyPath != null)
|
||||
{
|
||||
Console.WriteLine("Assembly already specified or unknown option.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
assemblyPath = arg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Path.IsPathRooted(assemblyPath))
|
||||
{
|
||||
var workingDir = Directory.GetCurrentDirectory();
|
||||
assemblyPath = Path.Combine(workingDir, assemblyPath);
|
||||
}
|
||||
|
||||
var errors = CLRHelpers.PeVerify(assemblyPath, metadataOnly);
|
||||
foreach (var error in errors)
|
||||
{
|
||||
Console.WriteLine(error);
|
||||
}
|
||||
|
||||
return errors.Length;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,32 +47,12 @@ type PEVerifier () =
|
|||
if runsOnMono then
|
||||
Some ("pedump", "--verify all")
|
||||
else
|
||||
let rec tryFindFile (fileName : string) (dir : DirectoryInfo) =
|
||||
let file = Path.Combine(dir.FullName, fileName)
|
||||
if File.Exists file then Some file
|
||||
else
|
||||
dir.GetDirectories()
|
||||
|> Array.sortBy(fun d -> d.Name)
|
||||
|> Array.filter(fun d ->
|
||||
match d.Name with
|
||||
// skip old SDK directories
|
||||
| "v6.0" | "v6.0A" | "v7.0" | "v7.0A" | "v7.1" | "v7.1A" -> false
|
||||
| _ -> true)
|
||||
|> Array.rev // order by descending -- get latest version
|
||||
|> Array.tryPick (tryFindFile fileName)
|
||||
|
||||
let tryGetSdkDir (progFiles : Environment.SpecialFolder) =
|
||||
let progFilesFolder = Environment.GetFolderPath(progFiles)
|
||||
let dI = DirectoryInfo(Path.Combine(progFilesFolder, "Microsoft SDKs", "Windows"))
|
||||
if dI.Exists then Some dI
|
||||
else None
|
||||
|
||||
match Array.tryPick tryGetSdkDir [| Environment.SpecialFolder.ProgramFilesX86; Environment.SpecialFolder.ProgramFiles |] with
|
||||
| None -> None
|
||||
| Some sdkDir ->
|
||||
match tryFindFile "peverify.exe" sdkDir with
|
||||
| None -> None
|
||||
| Some pe -> Some (pe, "/UNIQUE /IL /NOLOGO")
|
||||
let peverifyPath configuration =
|
||||
Path.Combine(__SOURCE_DIRECTORY__, "..", "fsharpqa", "testenv", "src", "PEVerify", "bin", configuration, "net46", "PEVerify.exe")
|
||||
let peverify =
|
||||
if File.Exists(peverifyPath "Debug") then peverifyPath "Debug"
|
||||
else peverifyPath "Release"
|
||||
Some (peverify, "/UNIQUE /IL /NOLOGO")
|
||||
#endif
|
||||
|
||||
static let execute (fileName : string, arguments : string) =
|
||||
|
|
Загрузка…
Ссылка в новой задаче