Merge pull request #15794 from michaelnebel/csharp/removecil

C#: Delete the CIL extractor.
This commit is contained in:
Michael Nebel 2024-03-12 12:48:41 +01:00 коммит произвёл GitHub
Родитель 1a42e55095 eb62c033aa
Коммит 50851210ea
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
154 изменённых файлов: 7 добавлений и 25943 удалений

Просмотреть файл

@ -268,6 +268,5 @@ csharp_style_var_elsewhere = true:suggestion
#
[extractor/Semmle.Extraction/Tuples.cs,
extractor/Semmle.Extraction.CSharp/Tuples.cs,
extractor/Semmle.Extraction.CIL/Tuples.cs]
extractor/Semmle.Extraction.CSharp/Tuples.cs]
dotnet_naming_rule.members_should_be_pascal_case.severity = none

Просмотреть файл

@ -8,8 +8,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction", "extrac
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp", "extractor\Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj", "{C4D62DA0-B64B-440B-86DC-AB52318CB8BF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CIL", "extractor\Semmle.Extraction.CIL\Semmle.Extraction.CIL.csproj", "{399A1579-68F0-40F4-9A23-F241BA697F9C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.DependencyFetching", "extractor\Semmle.Extraction.CSharp.DependencyFetching\Semmle.Extraction.CSharp.DependencyFetching.csproj", "{541D1AC5-E42C-4AB2-A1A4-C2355CE2A2EF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.Standalone", "extractor\Semmle.Extraction.CSharp.Standalone\Semmle.Extraction.CSharp.Standalone.csproj", "{D00E7D25-0FA0-48EC-B048-CD60CE1B30D8}"
@ -18,8 +16,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.St
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.Util", "extractor\Semmle.Extraction.CSharp.Util\Semmle.Extraction.CSharp.Util.csproj", "{998A0D4C-8BFC-4513-A28D-4816AFB89882}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CIL.Driver", "extractor\Semmle.Extraction.CIL.Driver\Semmle.Extraction.CIL.Driver.csproj", "{EFA400B3-C1CE-446F-A4E2-8B44E61EF47C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.CSharp.Driver", "extractor\Semmle.Extraction.CSharp.Driver\Semmle.Extraction.CSharp.Driver.csproj", "{C36453BF-0C82-448A-B15D-26947503A2D3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Semmle.Extraction.Tests", "extractor\Semmle.Extraction.Tests\Semmle.Extraction.Tests.csproj", "{CD8D3F90-AD2E-4BB5-8E82-B94AA293864A}"

Просмотреть файл

@ -47,13 +47,6 @@ options:
the code (for example if it uses inaccessible dependencies).
type: string
pattern: "^(false|true)$"
cil:
title: Whether to enable CIL extraction.
description: >
A value indicating, whether CIL extraction should be enabled.
The default is 'true'.
type: string
pattern: "^(false|true)$"
logging:
title: Options pertaining to logging.
type: object

Просмотреть файл

@ -1,250 +0,0 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Driver
{
/// <summary>
/// Information about a single assembly.
/// In particular, provides references between assemblies.
/// </summary>
internal class AssemblyInfo
{
public override string ToString() => Filename;
private static AssemblyName CreateAssemblyName(MetadataReader mdReader, StringHandle name, System.Version version, StringHandle culture)
{
var cultureString = mdReader.GetString(culture);
var assemblyName = new AssemblyName()
{
Name = mdReader.GetString(name),
Version = version
};
if (cultureString != "neutral")
assemblyName.CultureInfo = CultureInfo.GetCultureInfo(cultureString);
return assemblyName;
}
private static AssemblyName CreateAssemblyName(MetadataReader mdReader, AssemblyReference ar)
{
var an = CreateAssemblyName(mdReader, ar.Name, ar.Version, ar.Culture);
if (!ar.PublicKeyOrToken.IsNil)
an.SetPublicKeyToken(mdReader.GetBlobBytes(ar.PublicKeyOrToken));
return an;
}
private static AssemblyName CreateAssemblyName(MetadataReader mdReader, AssemblyDefinition ad)
{
var an = CreateAssemblyName(mdReader, ad.Name, ad.Version, ad.Culture);
if (!ad.PublicKey.IsNil)
an.SetPublicKey(mdReader.GetBlobBytes(ad.PublicKey));
return an;
}
/// <summary>
/// Initializes a new instance of the <see cref="AssemblyInfo"/> class.
/// </summary>
/// <param name="path">Path of the assembly.</param>
/// <exception cref="Semmle.Extraction.CIL.Driver.InvalidAssemblyException">
/// Thrown when the input file is not a valid assembly.
/// </exception>
public AssemblyInfo(string path)
{
Filename = path;
// Attempt to open the file and see if it's a valid assembly.
using var stream = File.OpenRead(path);
using var peReader = new PEReader(stream);
try
{
if (!peReader.HasMetadata)
throw new InvalidAssemblyException();
var mdReader = peReader.GetMetadataReader();
if (!mdReader.IsAssembly)
throw new InvalidAssemblyException();
// Get our own assembly name
Name = CreateAssemblyName(mdReader, mdReader.GetAssemblyDefinition());
References = mdReader.AssemblyReferences
.Select(r => mdReader.GetAssemblyReference(r))
.Select(ar => CreateAssemblyName(mdReader, ar))
.ToArray();
}
catch (System.BadImageFormatException)
{
// This failed on one of the Roslyn tests that includes
// a deliberately malformed assembly.
// In this case, we just skip the extraction of this assembly.
throw new InvalidAssemblyException();
}
}
public AssemblyName Name { get; }
public string Filename { get; }
public bool Extract { get; set; }
public AssemblyName[] References { get; }
}
/// <summary>
/// Helper to manage a collection of assemblies.
/// Resolves references between assemblies and determines which
/// additional assemblies need to be extracted.
/// </summary>
internal class AssemblyList
{
private class AssemblyNameComparer : IEqualityComparer<AssemblyName>
{
bool IEqualityComparer<AssemblyName>.Equals(AssemblyName? x, AssemblyName? y) =>
object.ReferenceEquals(x, y) ||
x?.Name == y?.Name && x?.Version == y?.Version;
int IEqualityComparer<AssemblyName>.GetHashCode(AssemblyName obj) =>
(obj.Name, obj.Version).GetHashCode();
}
private readonly Dictionary<AssemblyName, AssemblyInfo> assembliesRead = new Dictionary<AssemblyName, AssemblyInfo>(new AssemblyNameComparer());
public void AddFile(string assemblyPath, bool extractAll)
{
if (!filesAnalyzed.Contains(assemblyPath))
{
filesAnalyzed.Add(assemblyPath);
try
{
var info = new AssemblyInfo(assemblyPath)
{
Extract = extractAll
};
if (!assembliesRead.ContainsKey(info.Name))
assembliesRead.Add(info.Name, info);
}
catch (InvalidAssemblyException)
{ }
}
}
public IEnumerable<AssemblyInfo> AssembliesToExtract => assembliesRead.Values.Where(info => info.Extract);
private IEnumerable<AssemblyName> AssembliesToReference => AssembliesToExtract.SelectMany(info => info.References);
public void ResolveReferences()
{
var assembliesToReference = new Stack<AssemblyName>(AssembliesToReference);
while (assembliesToReference.Any())
{
var item = assembliesToReference.Pop();
if (assembliesRead.TryGetValue(item, out var info))
{
if (!info.Extract)
{
info.Extract = true;
foreach (var reference in info.References)
assembliesToReference.Push(reference);
}
}
else
{
MissingReferences.Add(item);
}
}
}
private readonly HashSet<string> filesAnalyzed = new HashSet<string>();
public HashSet<AssemblyName> MissingReferences { get; } = new HashSet<AssemblyName>();
}
/// <summary>
/// Parses the command line and collates a list of DLLs/EXEs to extract.
/// </summary>
internal class ExtractorOptions : CommonOptions
{
private readonly AssemblyList assemblyList = new AssemblyList();
public ExtractorOptions(string[] args)
{
this.ParseArguments(args.Append("--pdb").ToArray());
AddFrameworkDirectories(false);
assemblyList.ResolveReferences();
AssembliesToExtract = assemblyList.AssembliesToExtract.ToArray();
}
public void AddDirectory(string directory, bool extractAll)
{
foreach (var file in
Directory.EnumerateFiles(directory, "*.dll", SearchOption.AllDirectories).
Concat(Directory.EnumerateFiles(directory, "*.exe", SearchOption.AllDirectories)))
{
assemblyList.AddFile(file, extractAll);
}
}
private void AddFrameworkDirectories(bool extractAll)
{
AddDirectory(RuntimeEnvironment.GetRuntimeDirectory(), extractAll);
}
private void AddFileOrDirectory(string path)
{
path = Path.GetFullPath(path);
if (File.Exists(path))
{
assemblyList.AddFile(path, true);
var directory = Path.GetDirectoryName(path);
if (directory is null)
{
throw new InternalError($"Directory of path '{path}' is null");
}
AddDirectory(directory, false);
}
else if (Directory.Exists(path))
{
AddDirectory(path, true);
}
}
public IEnumerable<AssemblyInfo> AssembliesToExtract { get; }
/// <summary>
/// Gets the assemblies that were referenced but were not available to be
/// extracted. This is not an error, it just means that the database is not
/// as complete as it could be.
/// </summary>
public IEnumerable<AssemblyName> MissingReferences => assemblyList.MissingReferences;
public override bool HandleFlag(string flag, bool value)
{
switch (flag)
{
case "dotnet":
if (value)
AddFrameworkDirectories(true);
return true;
default:
return base.HandleFlag(flag, value);
}
}
public override bool HandleArgument(string argument)
{
AddFileOrDirectory(argument);
return true;
}
public override void InvalidArgument(string argument) { }
}
}

Просмотреть файл

@ -1,7 +0,0 @@
using System;
namespace Semmle.Extraction.CIL.Driver
{
public class InvalidAssemblyException : Exception
{ }
}

Просмотреть файл

@ -1,64 +0,0 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Semmle.Util.Logging;
namespace Semmle.Extraction.CIL.Driver
{
public static class Program
{
private static void DisplayHelp()
{
Console.WriteLine("CIL command line extractor");
Console.WriteLine();
Console.WriteLine("Usage: Semmle.Extraction.CIL.Driver.exe [options] path ...");
Console.WriteLine(" --verbose Turn on verbose output");
Console.WriteLine(" --dotnet Extract the .Net Framework");
Console.WriteLine(" --nocache Overwrite existing trap files");
Console.WriteLine(" --no-pdb Do not extract PDB files");
Console.WriteLine(" path A directory/dll/exe to analyze");
}
private static void ExtractAssembly(string assemblyPath, ILogger logger, CommonOptions options)
{
var sw = new Stopwatch();
sw.Start();
Analyser.ExtractCIL(assemblyPath, logger, options, out _, out _);
sw.Stop();
logger.Log(Severity.Info, " {0} ({1})", assemblyPath, sw.Elapsed);
}
public static void Main(string[] args)
{
if (args.Length == 0)
{
DisplayHelp();
return;
}
var options = new ExtractorOptions(args);
using ILogger logger = new ConsoleLogger(options.Verbosity, logThreadId: false);
var actions = options.AssembliesToExtract
.Select(asm => asm.Filename)
.Select<string, Action>(filename => () => ExtractAssembly(filename, logger, options))
.ToArray();
foreach (var missingRef in options.MissingReferences)
logger.LogInfo(" Missing assembly " + missingRef);
var sw = new Stopwatch();
sw.Start();
var piOptions = new ParallelOptions
{
MaxDegreeOfParallelism = options.Threads
};
Parallel.Invoke(piOptions, actions);
sw.Stop();
logger.Log(Severity.Info, "Extraction completed in {0}", sw.Elapsed);
}
}
}

Просмотреть файл

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Semmle.Extraction.CIL.Driver")]
[assembly: AssemblyDescription("Semmle CIL extractor")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Semmle Ltd")]
[assembly: AssemblyProduct("Semmle.Extraction.CIL.Driver")]
[assembly: AssemblyCopyright("Copyright © Semmle 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("5642ae68-9c26-43c9-bd3c-49923dddf02d")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<AssemblyName>Semmle.Extraction.CIL.Driver</AssemblyName>
<RootNamespace>Semmle.Extraction.CIL.Driver</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Semmle.Extraction.CIL\Semmle.Extraction.CIL.csproj" />
<ProjectReference Include="..\Semmle.Extraction\Semmle.Extraction.csproj" />
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,52 +0,0 @@
using System;
using Semmle.Util;
using Semmle.Util.Logging;
using Semmle.Extraction.CIL.Entities;
namespace Semmle.Extraction.CIL
{
public static class Analyser
{
private static void ExtractCIL(TracingExtractor extractor, TrapWriter trapWriter, bool extractPdbs)
{
using var cilContext = new Context(extractor, trapWriter, extractor.OutputPath, extractPdbs);
cilContext.Populate(new Assembly(cilContext));
cilContext.PopulateAll();
}
/// <summary>
/// Main entry point to the CIL extractor.
/// Call this to extract a given assembly.
/// </summary>
/// <param name="layout">The trap layout.</param>
/// <param name="assemblyPath">The full path of the assembly to extract.</param>
/// <param name="logger">The logger.</param>
/// <param name="nocache">True to overwrite existing trap file.</param>
/// <param name="extractPdbs">Whether to extract PDBs.</param>
/// <param name="trapFile">The path of the trap file.</param>
/// <param name="extracted">Whether the file was extracted (false=cached).</param>
public static void ExtractCIL(string assemblyPath, ILogger logger, CommonOptions options, out string trapFile, out bool extracted)
{
trapFile = "";
extracted = false;
try
{
var canonicalPathCache = CanonicalPathCache.Create(logger, 1000);
var pathTransformer = new PathTransformer(canonicalPathCache);
var extractor = new TracingExtractor(assemblyPath, logger, pathTransformer, options);
var transformedAssemblyPath = pathTransformer.Transform(assemblyPath);
using var trapWriter = transformedAssemblyPath.WithSuffix(".cil").CreateTrapWriter(logger, options.TrapCompression, discardDuplicates: true);
trapFile = trapWriter.TrapFile;
if (!options.Cache || !System.IO.File.Exists(trapFile))
{
ExtractCIL(extractor, trapWriter, options.PDB);
extracted = true;
}
}
catch (Exception ex) // lgtm[cs/catch-of-all-exceptions]
{
logger.LogError(string.Format("Exception extracting {0}: {1}", assemblyPath, ex));
}
}
}
}

Просмотреть файл

@ -1,68 +0,0 @@
using System;
using System.Collections.Generic;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// A factory and a cache for mapping source entities to target entities.
/// Could be considered as a memoizer.
/// </summary>
/// <typeparam name="TSrc">The type of the source.</typeparam>
/// <typeparam name="TTarget">The type of the generated object.</typeparam>
public class CachedFunction<TSrc, TTarget> where TSrc : notnull
{
private readonly Func<TSrc, TTarget> generator;
private readonly Dictionary<TSrc, TTarget> cache;
/// <summary>
/// Initializes the factory with a given mapping.
/// </summary>
/// <param name="g">The mapping.</param>
public CachedFunction(Func<TSrc, TTarget> g)
{
generator = g;
cache = new Dictionary<TSrc, TTarget>();
}
/// <summary>
/// Gets the target for a given source.
/// Create it if it does not exist.
/// </summary>
/// <param name="src">The source object.</param>
/// <returns>The created object.</returns>
public TTarget this[TSrc src]
{
get
{
if (!cache.TryGetValue(src, out var result))
{
result = generator(src);
cache[src] = result;
}
return result;
}
}
}
/// <summary>
/// A factory for mapping a pair of source entities to a target entity.
/// </summary>
/// <typeparam name="TSrcEntity1">Source entity type 1.</typeparam>
/// <typeparam name="TSrcEntity2">Source entity type 2.</typeparam>
/// <typeparam name="TTarget">The target type.</typeparam>
public class CachedFunction<TSrcEntity1, TSrcEntity2, TTarget>
{
private readonly CachedFunction<(TSrcEntity1, TSrcEntity2), TTarget> factory;
/// <summary>
/// Initializes the factory with a given mapping.
/// </summary>
/// <param name="g">The mapping.</param>
public CachedFunction(Func<TSrcEntity1, TSrcEntity2, TTarget> g)
{
factory = new CachedFunction<(TSrcEntity1, TSrcEntity2), TTarget>(p => g(p.Item1, p.Item2));
}
public TTarget this[TSrcEntity1 s1, TSrcEntity2 s2] => factory[(s1, s2)];
}
}

Просмотреть файл

@ -1,253 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using Semmle.Extraction.CIL.Entities;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// Provides methods for creating and caching various entities.
/// </summary>
internal sealed partial class Context
{
private readonly Dictionary<object, Label> ids = new Dictionary<object, Label>();
internal T Populate<T>(T e) where T : IExtractedEntity
{
if (e.Label.Valid)
{
return e; // Already populated
}
if (ids.TryGetValue(e, out var existing))
{
// It exists already
e.Label = existing;
}
else
{
e.Label = GetNewLabel();
DefineLabel(e);
ids.Add(e, e.Label);
PopulateLater(() =>
{
foreach (var c in e.Contents)
c.Extract(this);
});
#if DEBUG_LABELS
using var writer = new EscapingTextWriter();
e.WriteId(writer);
var id = writer.ToString();
if (debugLabels.TryGetValue(id, out var previousEntity))
{
Extractor.Message(new Message("Duplicate trap ID", id, null, severity: Util.Logging.Severity.Warning));
}
else
{
debugLabels.Add(id, e);
}
#endif
}
return e;
}
#if DEBUG_LABELS
private readonly Dictionary<string, IExtractedEntity> debugLabels = new Dictionary<string, IExtractedEntity>();
#endif
public IExtractedEntity Create(Handle h)
{
var entity = CreateGeneric(defaultGenericContext, h);
return entity;
}
// Lazily cache primitive types.
private readonly PrimitiveType[] primitiveTypes = new PrimitiveType[(int)PrimitiveTypeCode.Object + 1];
public PrimitiveType Create(PrimitiveTypeCode code)
{
var e = primitiveTypes[(int)code];
if (e is null)
{
e = new PrimitiveType(this, code)
{
Label = GetNewLabel()
};
DefineLabel(e);
primitiveTypes[(int)code] = e;
}
return e;
}
/// <summary>
/// Creates an entity from a Handle in a GenericContext.
/// The type of the returned entity depends on the type of the handle.
/// The GenericContext is needed because some handles are generics which
/// need to be expanded in terms of the current instantiation. If this sounds
/// complex, you are right.
///
/// The pair (h,genericContext) is cached in case it is needed again.
/// </summary>
/// <param name="h">The handle of the entity.</param>
/// <param name="genericContext">The generic context.</param>
/// <returns></returns>
public IExtractedEntity CreateGeneric(IGenericContext genericContext, Handle h) => genericHandleFactory[genericContext, h];
private readonly IGenericContext defaultGenericContext;
private IExtractedEntity CreateGenericHandle(IGenericContext gc, Handle handle)
{
IExtractedEntity entity;
switch (handle.Kind)
{
case HandleKind.MethodDefinition:
entity = new DefinitionMethod(gc, (MethodDefinitionHandle)handle);
break;
case HandleKind.MemberReference:
entity = Create(gc, (MemberReferenceHandle)handle);
break;
case HandleKind.MethodSpecification:
entity = new MethodSpecificationMethod(gc, (MethodSpecificationHandle)handle);
break;
case HandleKind.FieldDefinition:
entity = new DefinitionField(gc.Context, (FieldDefinitionHandle)handle);
break;
case HandleKind.TypeReference:
var tr = new TypeReferenceType(this, (TypeReferenceHandle)handle);
if (tr.TryGetPrimitiveType(out var pt))
// Map special names like `System.Int32` to `int`
return pt;
entity = tr;
break;
case HandleKind.TypeSpecification:
return Entities.Type.DecodeType(gc, (TypeSpecificationHandle)handle);
case HandleKind.TypeDefinition:
entity = new TypeDefinitionType(this, (TypeDefinitionHandle)handle);
break;
case HandleKind.StandaloneSignature:
var signature = MdReader.GetStandaloneSignature((StandaloneSignatureHandle)handle);
var method = signature.DecodeMethodSignature(gc.Context.TypeSignatureDecoder, gc);
entity = new FunctionPointerType(this, method);
break;
default:
throw new InternalError("Unhandled handle kind " + handle.Kind);
}
Populate(entity);
return entity;
}
private IExtractedEntity Create(IGenericContext gc, MemberReferenceHandle handle)
{
var mr = MdReader.GetMemberReference(handle);
switch (mr.GetKind())
{
case MemberReferenceKind.Method:
return new MemberReferenceMethod(gc, handle);
case MemberReferenceKind.Field:
return new MemberReferenceField(gc, handle);
default:
throw new InternalError("Unhandled member reference handle");
}
}
/// <summary>
/// Gets the string for a string handle.
/// </summary>
/// <param name="h">The string handle.</param>
/// <returns>The string.</returns>
public string GetString(StringHandle h) => MdReader.GetString(h);
#region Namespaces
private readonly CachedFunction<StringHandle, Namespace> namespaceFactory;
public Namespace CreateNamespace(StringHandle fqn) => namespaceFactory[fqn];
private readonly Lazy<Namespace> globalNamespace, systemNamespace;
/// <summary>
/// The entity representing the global namespace.
/// </summary>
public Namespace GlobalNamespace => globalNamespace.Value;
/// <summary>
/// The entity representing the System namespace.
/// </summary>
public Namespace SystemNamespace => systemNamespace.Value;
/// <summary>
/// Creates a namespace from a fully-qualified name.
/// </summary>
/// <param name="fqn">The fully-qualified namespace name.</param>
/// <returns>The namespace entity.</returns>
private Namespace CreateNamespace(string fqn) => Populate(new Namespace(this, fqn));
private readonly CachedFunction<NamespaceDefinitionHandle, Namespace> namespaceDefinitionFactory;
/// <summary>
/// Creates a namespace from a namespace handle.
/// </summary>
/// <param name="handle">The handle of the namespace.</param>
/// <returns>The namespace entity.</returns>
public Namespace Create(NamespaceDefinitionHandle handle) => namespaceDefinitionFactory[handle];
private Namespace CreateNamespace(NamespaceDefinitionHandle handle)
{
if (handle.IsNil)
return GlobalNamespace;
var nd = MdReader.GetNamespaceDefinition(handle);
return Populate(new Namespace(this, GetString(nd.Name), Create(nd.Parent)));
}
#endregion
#region Locations
private readonly CachedFunction<PDB.ISourceFile, PdbSourceFile> sourceFiles;
private readonly CachedFunction<PathTransformer.ITransformedPath, Folder> folders;
private readonly CachedFunction<PDB.Location, PdbSourceLocation> sourceLocations;
/// <summary>
/// Creates a source file entity from a PDB source file.
/// </summary>
/// <param name="file">The PDB source file.</param>
/// <returns>A source file entity.</returns>
public PdbSourceFile CreateSourceFile(PDB.ISourceFile file) => sourceFiles[file];
/// <summary>
/// Creates a folder entity with the given path.
/// </summary>
/// <param name="path">The path of the folder.</param>
/// <returns>A folder entity.</returns>
public Folder CreateFolder(PathTransformer.ITransformedPath path) => folders[path];
/// <summary>
/// Creates a source location.
/// </summary>
/// <param name="loc">The source location from PDB.</param>
/// <returns>A source location entity.</returns>
public PdbSourceLocation CreateSourceLocation(PDB.Location loc) => sourceLocations[loc];
#endregion
private readonly CachedFunction<IGenericContext, Handle, IExtractedEntity> genericHandleFactory;
/// <summary>
/// Gets the short name of a member, without the preceding interface qualifier.
/// </summary>
/// <param name="handle">The handle of the name.</param>
/// <returns>The short name.</returns>
public string ShortName(StringHandle handle)
{
var str = MdReader.GetString(handle);
if (str.EndsWith(".ctor"))
return ".ctor";
if (str.EndsWith(".cctor"))
return ".cctor";
var dot = str.LastIndexOf('.');
return dot == -1 ? str : str.Substring(dot + 1);
}
}
}

Просмотреть файл

@ -1,115 +0,0 @@
using System;
using System.IO;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// Extraction context for CIL extraction.
/// Adds additional context that is specific for CIL extraction.
/// One context = one DLL/EXE.
/// </summary>
internal sealed partial class Context : Extraction.Context, IDisposable
{
private readonly FileStream stream;
private Entities.Assembly? assemblyNull;
public MetadataReader MdReader { get; }
public PEReader PeReader { get; }
public string AssemblyPath { get; }
public Entities.Assembly Assembly
{
get { return assemblyNull!; }
set { assemblyNull = value; }
}
public PDB.IPdb? Pdb { get; }
public Context(Extractor extractor, TrapWriter trapWriter, string assemblyPath, bool extractPdbs)
: base(extractor, trapWriter)
{
this.AssemblyPath = assemblyPath;
stream = File.OpenRead(assemblyPath);
PeReader = new PEReader(stream, PEStreamOptions.PrefetchEntireImage);
MdReader = PeReader.GetMetadataReader();
TypeSignatureDecoder = new Entities.TypeSignatureDecoder(this);
globalNamespace = new Lazy<Entities.Namespace>(() => Populate(new Entities.Namespace(this, "", null)));
systemNamespace = new Lazy<Entities.Namespace>(() => Populate(new Entities.Namespace(this, "System")));
genericHandleFactory = new CachedFunction<IGenericContext, Handle, IExtractedEntity>(CreateGenericHandle);
namespaceFactory = new CachedFunction<StringHandle, Entities.Namespace>(n => CreateNamespace(MdReader.GetString(n)));
namespaceDefinitionFactory = new CachedFunction<NamespaceDefinitionHandle, Entities.Namespace>(CreateNamespace);
sourceFiles = new CachedFunction<PDB.ISourceFile, Entities.PdbSourceFile>(path => new Entities.PdbSourceFile(this, path));
folders = new CachedFunction<PathTransformer.ITransformedPath, Entities.Folder>(path => new Entities.Folder(this, path));
sourceLocations = new CachedFunction<PDB.Location, Entities.PdbSourceLocation>(location => new Entities.PdbSourceLocation(this, location));
defaultGenericContext = new EmptyContext(this);
if (extractPdbs)
{
Pdb = PDB.PdbReader.Create(assemblyPath, PeReader);
if (Pdb is not null)
{
Extractor.Logger.Log(Util.Logging.Severity.Info, string.Format("Found PDB information for {0}", assemblyPath));
}
}
}
public void Dispose()
{
if (Pdb is not null)
Pdb.Dispose();
PeReader.Dispose();
stream.Dispose();
}
/// <summary>
/// Extract the contents of a given entity.
/// </summary>
/// <param name="entity">The entity to extract.</param>
public void Extract(IExtractedEntity entity)
{
foreach (var content in entity.Contents)
{
content.Extract(this);
}
}
public void WriteAssemblyPrefix(TextWriter trapFile)
{
var def = MdReader.GetAssemblyDefinition();
trapFile.Write(GetString(def.Name));
trapFile.Write('_');
trapFile.Write(def.Version.ToString());
trapFile.Write(Entities.Type.AssemblyTypeNameSeparator);
}
public Entities.TypeSignatureDecoder TypeSignatureDecoder { get; }
/// <summary>
/// A type used to signify something we can't handle yet.
/// Specifically, function pointers (used in C++).
/// </summary>
public Entities.Type ErrorType
{
get
{
var errorType = new Entities.ErrorType(this);
Populate(errorType);
return errorType;
}
}
/// <summary>
/// Attempt to locate debugging information for a particular method.
///
/// Returns null on failure, for example if there was no PDB information found for the
/// DLL, or if the particular method is compiler generated or doesn't come from source code.
/// </summary>
/// <param name="handle">The handle of the method.</param>
/// <returns>The debugging information, or null if the information could not be located.</returns>
public PDB.Method? GetMethodDebugInformation(MethodDefinitionHandle handle)
{
return Pdb?.GetMethod(handle.ToDebugInformationHandle());
}
}
}

Просмотреть файл

@ -1,22 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// A generic context which does not contain any type parameters.
/// </summary>
internal class EmptyContext : IGenericContext
{
public EmptyContext(Context cx)
{
Context = cx;
}
public Context Context { get; }
public IEnumerable<Entities.Type> TypeParameters { get { yield break; } }
public IEnumerable<Entities.Type> MethodParameters { get { yield break; } }
}
}

Просмотреть файл

@ -1,74 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// An array type.
/// </summary>
internal sealed class ArrayType : Type
{
private readonly Type elementType;
private readonly int rank;
public ArrayType(Context cx, Type elementType, int rank) : base(cx)
{
this.rank = rank;
this.elementType = elementType;
}
public ArrayType(Context cx, Type elementType) : this(cx, elementType, 1)
{
}
public override bool Equals(object? obj)
{
return obj is ArrayType array && elementType.Equals(array.elementType) && rank == array.rank;
}
public override int GetHashCode() => HashCode.Combine(elementType, rank);
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
elementType.WriteId(trapFile, inContext);
trapFile.Write('[');
for (var i = 1; i < rank; ++i)
{
trapFile.Write(',');
}
trapFile.Write(']');
}
public override string Name => elementType.Name + "[]";
public override Namespace ContainingNamespace => Context.SystemNamespace;
public override Type? ContainingType => null;
public override int ThisTypeParameterCount => elementType.ThisTypeParameterCount;
public override CilTypeKind Kind => CilTypeKind.Array;
public override Type Construct(IEnumerable<Type> typeArguments) => Context.Populate(new ArrayType(Context, elementType.Construct(typeArguments)));
public override Type SourceDeclaration => Context.Populate(new ArrayType(Context, elementType.SourceDeclaration));
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var c in base.Contents)
yield return c;
yield return Tuples.cil_array_type(this, elementType, rank);
}
}
public override void WriteAssemblyPrefix(TextWriter trapFile) => elementType.WriteAssemblyPrefix(trapFile);
public override IEnumerable<Type> GenericArguments => elementType.GenericArguments;
public override IEnumerable<Type> TypeParameters => elementType.TypeParameters;
}
}

Просмотреть файл

@ -1,101 +0,0 @@
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using Semmle.Extraction.Entities;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// An assembly to extract.
/// </summary>
internal class Assembly : LabelledEntity, ILocation
{
private readonly File file;
private readonly AssemblyName assemblyName;
public Assembly(Context cx) : base(cx)
{
cx.Assembly = this;
var def = cx.MdReader.GetAssemblyDefinition();
assemblyName = new AssemblyName
{
Name = cx.MdReader.GetString(def.Name),
Version = def.Version,
CultureInfo = new CultureInfo(cx.MdReader.GetString(def.Culture))
};
if (!def.PublicKey.IsNil)
assemblyName.SetPublicKey(cx.MdReader.GetBlobBytes(def.PublicKey));
file = new File(cx, cx.AssemblyPath);
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(FullName);
trapFile.Write("#file:///");
trapFile.Write(Context.AssemblyPath.Replace("\\", "/"));
trapFile.Write(";assembly");
}
public override bool Equals(object? obj)
{
return GetType() == obj?.GetType() && Equals(file, ((Assembly)obj).file);
}
public override int GetHashCode() => 7 * file.GetHashCode();
private string FullName => assemblyName.GetPublicKey() is null ? assemblyName.FullName + ", PublicKeyToken=null" : assemblyName.FullName;
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return file;
yield return Tuples.assemblies(this, file, FullName, assemblyName.Name ?? string.Empty, assemblyName.Version?.ToString() ?? string.Empty);
if (Context.Pdb is not null)
{
foreach (var f in Context.Pdb.SourceFiles)
{
yield return Context.CreateSourceFile(f);
}
}
foreach (var handle in Context.MdReader.TypeDefinitions)
{
IExtractionProduct? product = null;
try
{
product = Context.Create(handle);
}
catch (InternalError e)
{
Context.ExtractionError("Error processing type definition", e.Message, GeneratedLocation.Create(Context), e.StackTrace);
}
// Limitation of C#: Cannot yield return inside a try-catch.
if (product is not null)
yield return product;
}
foreach (var handle in Context.MdReader.MethodDefinitions)
{
IExtractionProduct? product = null;
try
{
product = Context.Create(handle);
}
catch (InternalError e)
{
Context.ExtractionError("Error processing bytecode", e.Message, GeneratedLocation.Create(Context), e.StackTrace);
}
if (product is not null)
yield return product;
}
}
}
}
}

Просмотреть файл

@ -1,90 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Entity representing a CIL attribute.
/// </summary>
internal sealed class Attribute : UnlabelledEntity
{
private readonly CustomAttributeHandle handle;
private readonly CustomAttribute attrib;
private readonly IExtractedEntity @object;
public Attribute(Context cx, IExtractedEntity @object, CustomAttributeHandle handle) : base(cx)
{
attrib = cx.MdReader.GetCustomAttribute(handle);
this.handle = handle;
this.@object = @object;
}
public override bool Equals(object? obj)
{
return obj is Attribute attribute && handle.Equals(attribute.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
var constructor = (Method)Context.Create(attrib.Constructor);
yield return constructor;
yield return Tuples.cil_attribute(this, @object, constructor);
CustomAttributeValue<Type> decoded;
try
{
decoded = attrib.DecodeValue(new CustomAttributeDecoder(Context));
}
catch
{
Context.Extractor.Logger.Log(Util.Logging.Severity.Info,
$"Attribute decoding is partial. Decoding attribute {constructor.DeclaringType.GetQualifiedName()} failed on {@object}.");
yield break;
}
for (var index = 0; index < decoded.FixedArguments.Length; ++index)
{
var stringValue = GetStringValue(decoded.FixedArguments[index].Type, decoded.FixedArguments[index].Value);
yield return Tuples.cil_attribute_positional_argument(this, index, stringValue);
}
foreach (var p in decoded.NamedArguments)
{
var stringValue = GetStringValue(p.Type, p.Value);
yield return Tuples.cil_attribute_named_argument(this, p.Name!, stringValue);
}
}
}
private static string GetStringValue(Type type, object? value)
{
if (value is System.Collections.Immutable.ImmutableArray<CustomAttributeTypedArgument<Type>> values)
{
return "[" + string.Join(",", values.Select(v => GetStringValue(v.Type, v.Value))) + "]";
}
if (type.GetQualifiedName() == "System.Type" &&
value is Type t)
{
return t.GetQualifiedName();
}
return value?.ToString() ?? "null";
}
public static IEnumerable<IExtractionProduct> Populate(Context cx, IExtractedEntity @object, CustomAttributeHandleCollection attributes)
{
foreach (var attrib in attributes)
{
yield return new Attribute(cx, @object, attrib);
}
}
}
}

Просмотреть файл

@ -1,16 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// A CIL entity which has been extracted.
/// </summary>
internal interface IExtractedEntity : IExtractionProduct, IEntity
{
/// <summary>
/// The contents of the entity.
/// </summary>
IEnumerable<IExtractionProduct> Contents { get; }
}
}

Просмотреть файл

@ -1,24 +0,0 @@
namespace Semmle.Extraction.CIL
{
/// <summary>
/// Something that is extracted from an entity.
/// </summary>
///
/// <remarks>
/// The extraction algorithm proceeds as follows:
/// - Construct entity
/// - Call Extract()
/// - IExtractedEntity check if already extracted
/// - Enumerate Contents to produce more extraction products
/// - Extract these until there is nothing left to extract
/// </remarks>
internal interface IExtractionProduct
{
/// <summary>
/// Perform further extraction/population of this item as necessary.
/// </summary>
///
/// <param name="cx">The extraction context.</param>
void Extract(Context cx);
}
}

Просмотреть файл

@ -1,24 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// When we decode a type/method signature, we need access to
/// generic parameters.
/// </summary>
internal interface IGenericContext
{
Context Context { get; }
/// <summary>
/// The list of generic type parameters/arguments, including type parameters/arguments of
/// containing types.
/// </summary>
IEnumerable<Entities.Type> TypeParameters { get; }
/// <summary>
/// The list of generic method parameters/arguments.
/// </summary>
IEnumerable<Entities.Type> MethodParameters { get; }
}
}

Просмотреть файл

@ -1,36 +0,0 @@
using System;
using System.Collections.Generic;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// An entity that needs to be populated during extraction.
/// This assigns a key and optionally extracts its contents.
/// </summary>
internal abstract class LabelledEntity : Extraction.LabelledEntity, IExtractedEntity
{
public override Context Context => (Context)base.Context;
protected LabelledEntity(Context cx) : base(cx)
{
}
public override Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException();
public void Extract(Context cx2)
{
cx2.Populate(this);
}
public override string ToString()
{
using var writer = new EscapingTextWriter();
WriteQuotedId(writer);
return writer.ToString();
}
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
public abstract IEnumerable<IExtractionProduct> Contents { get; }
}
}

Просмотреть файл

@ -1,22 +0,0 @@
namespace Semmle.Extraction.CIL
{
/// <summary>
/// A tuple that is an extraction product.
/// </summary>
internal class Tuple : IExtractionProduct
{
private readonly Extraction.Tuple tuple;
public Tuple(string name, params object[] args)
{
tuple = new Extraction.Tuple(name, args);
}
public void Extract(Context cx)
{
cx.TrapWriter.Emit(tuple);
}
public override string ToString() => tuple.ToString();
}
}

Просмотреть файл

@ -1,29 +0,0 @@
using System;
using System.Collections.Generic;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// An entity that has contents to extract. There is no need to populate
/// a key as it's done in the constructor.
/// </summary>
internal abstract class UnlabelledEntity : Extraction.UnlabelledEntity, IExtractedEntity
{
public override Context Context => (Context)base.Context;
protected UnlabelledEntity(Context cx) : base(cx)
{
}
public override Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException();
public void Extract(Context cx2)
{
cx2.Extract(this);
}
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
public abstract IEnumerable<IExtractionProduct> Contents { get; }
}
}

Просмотреть файл

@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Types that are passed by reference are not written directly to trap files. Instead, the annotation is stored on
/// the entity.
/// </summary>
internal sealed class ByRefType : Type
{
public ByRefType(Context cx, Type elementType) : base(cx)
{
ElementType = elementType;
}
public override CilTypeKind Kind => throw new NotImplementedException();
public override Namespace? ContainingNamespace => throw new NotImplementedException();
public override Type? ContainingType => throw new NotImplementedException();
public override int ThisTypeParameterCount => throw new NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
public override string Name => $"{ElementType.Name}&";
public Type ElementType { get; }
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
ElementType.WriteId(trapFile, inContext);
trapFile.Write('&');
}
}
}

Просмотреть файл

@ -1,14 +0,0 @@
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// The CIL database type-kind.
/// </summary>
public enum CilTypeKind
{
ValueOrRefType,
TypeParameter,
Array,
Pointer,
FunctionPointer
}
}

Просмотреть файл

@ -1,118 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A constructed type.
/// </summary>
internal sealed class ConstructedType : Type
{
private readonly Type unboundGenericType;
// Either null or notEmpty
private readonly Type[]? thisTypeArguments;
private readonly Type? containingType;
private readonly NamedTypeIdWriter idWriter;
public ConstructedType(Context cx, Type unboundType, IEnumerable<Type> typeArguments) : base(cx)
{
idWriter = new NamedTypeIdWriter(this);
var suppliedArgs = typeArguments.Count();
if (suppliedArgs != unboundType.TotalTypeParametersCount)
throw new InternalError("Unexpected number of type arguments in ConstructedType");
unboundGenericType = unboundType;
var thisParams = unboundType.ThisTypeParameterCount;
if (typeArguments.Count() == thisParams)
{
containingType = unboundType.ContainingType;
thisTypeArguments = typeArguments.ToArray();
}
else if (thisParams == 0)
{
// all type arguments belong to containing type
containingType = unboundType.ContainingType!.Construct(typeArguments);
}
else
{
// some type arguments belong to containing type
var parentParams = suppliedArgs - thisParams;
containingType = unboundType.ContainingType!.Construct(typeArguments.Take(parentParams));
thisTypeArguments = typeArguments.Skip(parentParams).ToArray();
}
}
public override bool Equals(object? obj)
{
if (obj is ConstructedType t && Equals(unboundGenericType, t.unboundGenericType) && Equals(containingType, t.containingType))
{
if (thisTypeArguments is null)
return t.thisTypeArguments is null;
if (!(t.thisTypeArguments is null))
return thisTypeArguments.SequenceEqual(t.thisTypeArguments);
}
return false;
}
public override int GetHashCode()
{
var h = unboundGenericType.GetHashCode();
h = 13 * h + (containingType is null ? 0 : containingType.GetHashCode());
if (!(thisTypeArguments is null))
h = h * 13 + thisTypeArguments.SequenceHash();
return h;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var c in base.Contents)
yield return c;
var i = 0;
foreach (var type in ThisTypeArguments)
{
yield return type;
yield return Tuples.cil_type_argument(this, i++, type);
}
}
}
public override Type SourceDeclaration => unboundGenericType;
public override Type? ContainingType => containingType;
public override string Name => unboundGenericType.Name;
public override Namespace ContainingNamespace => unboundGenericType.ContainingNamespace!;
public override CilTypeKind Kind => unboundGenericType.Kind;
public override Type Construct(IEnumerable<Type> typeArguments)
{
throw new NotImplementedException();
}
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
idWriter.WriteId(trapFile, inContext);
}
public override void WriteAssemblyPrefix(TextWriter trapFile) => unboundGenericType.WriteAssemblyPrefix(trapFile);
public override int ThisTypeParameterCount => thisTypeArguments?.Length ?? 0;
public override IEnumerable<Type> TypeParameters => GenericArguments;
public override IEnumerable<Type> ThisTypeArguments => thisTypeArguments.EnumerateNull();
public override IEnumerable<Type> ThisGenericArguments => thisTypeArguments.EnumerateNull();
}
}

Просмотреть файл

@ -1,63 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Helper class to decode the attribute structure.
/// Note that there are some unhandled cases that should be fixed in due course.
/// </summary>
internal class CustomAttributeDecoder : ICustomAttributeTypeProvider<Type>
{
private readonly Context cx;
public CustomAttributeDecoder(Context cx) { this.cx = cx; }
public Type GetPrimitiveType(PrimitiveTypeCode typeCode) => cx.Create(typeCode);
public Type GetSystemType() => new NoMetadataHandleType(cx, "System.Type");
public Type GetSZArrayType(Type elementType) =>
cx.Populate(new ArrayType(cx, elementType));
public Type GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) =>
(Type)cx.Create(handle);
public Type GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) =>
(Type)cx.Create(handle);
public Type GetTypeFromSerializedName(string name) => new NoMetadataHandleType(cx, name);
public PrimitiveTypeCode GetUnderlyingEnumType(Type type)
{
if (type is TypeDefinitionType tdt &&
tdt.GetUnderlyingEnumType() is PrimitiveTypeCode underlying)
{
return underlying;
}
var name = type.GetQualifiedName();
if (wellKnownEnums.TryGetValue(name, out var code))
{
cx.Extractor.Logger.Log(Util.Logging.Severity.Debug, $"Using hard coded underlying enum type for {name}");
return code;
}
cx.Extractor.Logger.Log(Util.Logging.Severity.Info, $"Couldn't get underlying enum type for {name}");
// We can't fall back to Int32, because the type returned here defines how many bytes are read from the
// stream and how those bytes are interpreted.
throw new NotImplementedException();
}
public bool IsSystemType(Type type) => type.GetQualifiedName() == "System.Type";
private static readonly Dictionary<string, PrimitiveTypeCode> wellKnownEnums = new Dictionary<string, PrimitiveTypeCode>
{
{ "System.AttributeTargets", PrimitiveTypeCode.Int32 },
{ "System.ComponentModel.EditorBrowsableState", PrimitiveTypeCode.Int32 },
{ "System.Diagnostics.DebuggerBrowsableState", PrimitiveTypeCode.Int32 }
};
}
}

Просмотреть файл

@ -1,66 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class DefinitionField : Field
{
private readonly Handle handle;
private readonly FieldDefinition fd;
public DefinitionField(Context cx, FieldDefinitionHandle handle) : base(cx)
{
this.handle = handle;
fd = Context.MdReader.GetFieldDefinition(handle);
}
public override bool Equals(object? obj)
{
return obj is DefinitionField field && handle.Equals(field.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.metadata_handle(this, Context.Assembly, MetadataTokens.GetToken(handle));
foreach (var c in base.Contents)
yield return c;
if (fd.Attributes.HasFlag(FieldAttributes.Private))
yield return Tuples.cil_private(this);
if (fd.Attributes.HasFlag(FieldAttributes.Public))
yield return Tuples.cil_public(this);
if (fd.Attributes.HasFlag(FieldAttributes.Family))
yield return Tuples.cil_protected(this);
if (fd.Attributes.HasFlag(FieldAttributes.Static))
yield return Tuples.cil_static(this);
if (fd.Attributes.HasFlag(FieldAttributes.Assembly))
yield return Tuples.cil_internal(this);
foreach (var c in Attribute.Populate(Context, this, fd.GetCustomAttributes()))
yield return c;
}
}
public override string Name => Context.GetString(fd.Name);
public override Type DeclaringType => (Type)Context.Create(fd.GetDeclaringType());
public override Type Type => fd.DecodeSignature(Context.TypeSignatureDecoder, DeclaringType);
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override IEnumerable<Type> MethodParameters => throw new NotImplementedException();
}
}

Просмотреть файл

@ -1,299 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A definition method - a method defined in the current assembly.
/// </summary>
internal sealed class DefinitionMethod : Method
{
private readonly Handle handle;
private readonly MethodDefinition md;
private readonly PDB.Method? methodDebugInformation;
private readonly Type declaringType;
private readonly string name;
private LocalVariable[]? locals;
public MethodImplementation? Implementation { get; private set; }
public override IList<LocalVariable>? LocalVariables => locals;
public DefinitionMethod(IGenericContext gc, MethodDefinitionHandle handle) : base(gc)
{
md = Context.MdReader.GetMethodDefinition(handle);
this.gc = gc;
this.handle = handle;
name = Context.GetString(md.Name);
declaringType = (Type)Context.CreateGeneric(this, md.GetDeclaringType());
signature = md.DecodeSignature(new SignatureDecoder(), this);
methodDebugInformation = Context.GetMethodDebugInformation(handle);
}
public override bool Equals(object? obj)
{
return obj is DefinitionMethod method && handle.Equals(method.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override bool IsStatic => !signature.Header.IsInstance;
public override Type DeclaringType => declaringType;
public override string Name => Context.ShortName(md.Name);
public override string NameLabel => name;
/// <summary>
/// Holds if this method has bytecode.
/// </summary>
public bool HasBytecode => md.ImplAttributes == MethodImplAttributes.IL && md.RelativeVirtualAddress != 0;
public override IEnumerable<IExtractionProduct> Contents
{
get
{
if (md.GetGenericParameters().Any())
{
// We need to perform a 2-phase population because some type parameters can
// depend on other type parameters (as a constraint).
genericParams = new MethodTypeParameter[md.GetGenericParameters().Count];
for (var i = 0; i < genericParams.Length; ++i)
genericParams[i] = Context.Populate(new MethodTypeParameter(this, this, i));
for (var i = 0; i < genericParams.Length; ++i)
genericParams[i].PopulateHandle(md.GetGenericParameters()[i]);
foreach (var p in genericParams)
yield return p;
}
var typeSignature = md.DecodeSignature(Context.TypeSignatureDecoder, this);
var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray();
Parameters = parameters.OfType<Parameter>().ToArray();
foreach (var c in parameters)
yield return c;
foreach (var c in PopulateFlags)
yield return c;
foreach (var p in md.GetParameters().Select(h => Context.MdReader.GetParameter(h)).Where(p => p.SequenceNumber > 0))
{
var pe = Parameters[IsStatic ? p.SequenceNumber - 1 : p.SequenceNumber];
if (p.Attributes.HasFlag(ParameterAttributes.Out))
yield return Tuples.cil_parameter_out(pe);
if (p.Attributes.HasFlag(ParameterAttributes.In))
yield return Tuples.cil_parameter_in(pe);
foreach (var c in Attribute.Populate(Context, pe, p.GetCustomAttributes()))
yield return c;
}
yield return Tuples.metadata_handle(this, Context.Assembly, MetadataTokens.GetToken(handle));
foreach (var m in GetMethodExtractionProducts(Name, declaringType, typeSignature.ReturnType))
{
yield return m;
}
yield return Tuples.cil_method_source_declaration(this, this);
yield return Tuples.cil_method_location(this, Context.Assembly);
if (HasBytecode)
{
Implementation = new MethodImplementation(this);
yield return Implementation;
var body = Context.PeReader.GetMethodBody(md.RelativeVirtualAddress);
if (!body.LocalSignature.IsNil)
{
var localVariableTypes = System.Collections.Immutable.ImmutableArray<Type>.Empty;
var hasError = false;
try
{
var locals = Context.MdReader.GetStandaloneSignature(body.LocalSignature);
localVariableTypes = locals.DecodeLocalSignature(Context.TypeSignatureDecoder, this);
}
catch (System.BadImageFormatException exc)
{
Context.Extractor.Logger.Log(Util.Logging.Severity.Info,
$"Could not decode locals in method {declaringType.GetQualifiedName()}.{name}. {exc}");
hasError = true;
}
if (!hasError)
{
this.locals = new LocalVariable[localVariableTypes.Length];
for (var l = 0; l < this.locals.Length; ++l)
{
var t = localVariableTypes[l];
if (t is ByRefType brt)
{
t = brt.ElementType;
this.locals[l] = Context.Populate(new LocalVariable(Context, Implementation, l, t));
yield return this.locals[l];
yield return Tuples.cil_type_annotation(this.locals[l], TypeAnnotation.Ref);
}
else
{
this.locals[l] = Context.Populate(new LocalVariable(Context, Implementation, l, t));
yield return this.locals[l];
}
}
}
}
var jump_table = new Dictionary<int, Instruction>();
foreach (var c in Decode(body.GetILBytes(), jump_table))
yield return c;
var filter_index = 0;
foreach (var region in body.ExceptionRegions)
{
yield return new ExceptionRegion(this, Implementation, filter_index++, region, jump_table);
}
yield return Tuples.cil_method_stack_size(Implementation, body.MaxStack);
if (methodDebugInformation is not null)
{
var sourceLocation = Context.CreateSourceLocation(methodDebugInformation.Location);
yield return sourceLocation;
yield return Tuples.cil_method_location(this, sourceLocation);
}
}
// Flags
if (md.Attributes.HasFlag(MethodAttributes.Private))
yield return Tuples.cil_private(this);
if (md.Attributes.HasFlag(MethodAttributes.Public))
yield return Tuples.cil_public(this);
if (md.Attributes.HasFlag(MethodAttributes.Family))
yield return Tuples.cil_protected(this);
if (md.Attributes.HasFlag(MethodAttributes.Final))
yield return Tuples.cil_sealed(this);
if (md.Attributes.HasFlag(MethodAttributes.Virtual))
yield return Tuples.cil_virtual(this);
if (md.Attributes.HasFlag(MethodAttributes.Abstract))
yield return Tuples.cil_abstract(this);
if (md.Attributes.HasFlag(MethodAttributes.HasSecurity))
yield return Tuples.cil_security(this);
if (md.Attributes.HasFlag(MethodAttributes.RequireSecObject))
yield return Tuples.cil_requiresecobject(this);
if (md.Attributes.HasFlag(MethodAttributes.SpecialName))
yield return Tuples.cil_specialname(this);
if (md.Attributes.HasFlag(MethodAttributes.NewSlot))
yield return Tuples.cil_newslot(this);
// Populate attributes
foreach (var c in Attribute.Populate(Context, this, md.GetCustomAttributes()))
yield return c;
}
}
private IEnumerable<IExtractionProduct> Decode(byte[]? ilbytes, Dictionary<int, Instruction> jump_table)
{
// Sequence points are stored in order of offset.
// We use an enumerator to locate the correct sequence point for each instruction.
// The sequence point gives the location of each instruction.
// The location of an instruction is given by the sequence point *after* the
// instruction.
IEnumerator<PDB.SequencePoint>? nextSequencePoint = null;
PdbSourceLocation? instructionLocation = null;
if (methodDebugInformation is not null)
{
nextSequencePoint = methodDebugInformation.SequencePoints.GetEnumerator();
if (nextSequencePoint.MoveNext())
{
instructionLocation = Context.CreateSourceLocation(nextSequencePoint.Current.Location);
yield return instructionLocation;
}
else
{
nextSequencePoint = null;
}
}
var child = 0;
for (var offset = 0; offset < (ilbytes?.Length ?? 0);)
{
var instruction = new Instruction(Context, this, ilbytes!, offset, child++);
yield return instruction;
if (nextSequencePoint is not null && offset >= nextSequencePoint.Current.Offset)
{
instructionLocation = Context.CreateSourceLocation(nextSequencePoint.Current.Location);
yield return instructionLocation;
if (!nextSequencePoint.MoveNext())
nextSequencePoint = null;
}
if (instructionLocation is not null)
yield return Tuples.cil_instruction_location(instruction, instructionLocation);
jump_table.Add(instruction.Offset, instruction);
offset += instruction.Width;
}
foreach (var i in jump_table)
{
foreach (var t in i.Value.JumpContents(jump_table))
yield return t;
}
}
/// <summary>
/// Display the instructions in the method in the debugger.
/// This is only used for debugging, not in the code itself.
/// </summary>
public IEnumerable<Instruction> DebugInstructions
{
get
{
if (md.ImplAttributes == MethodImplAttributes.IL && md.RelativeVirtualAddress != 0)
{
var body = Context.PeReader.GetMethodBody(md.RelativeVirtualAddress);
var ilbytes = body.GetILBytes();
var child = 0;
for (var offset = 0; offset < (ilbytes?.Length ?? 0);)
{
Instruction decoded;
try
{
decoded = new Instruction(Context, this, ilbytes!, offset, child++);
offset += decoded.Width;
}
catch // lgtm[cs/catch-of-all-exceptions]
{
yield break;
}
yield return decoded;
}
}
}
}
}
}

Просмотреть файл

@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class ErrorType : Type
{
public ErrorType(Context cx) : base(cx)
{
}
public override void WriteId(EscapingTextWriter trapFile, bool inContext) => trapFile.Write("<ErrorType>");
public override CilTypeKind Kind => CilTypeKind.ValueOrRefType;
public override string Name => "!error";
public override Namespace ContainingNamespace => Context.GlobalNamespace;
public override Type? ContainingType => null;
public override int ThisTypeParameterCount => 0;
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
}
}

Просмотреть файл

@ -1,73 +0,0 @@
using System.Collections.Generic;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// An event entity.
/// </summary>
internal sealed class Event : LabelledEntity
{
private readonly EventDefinitionHandle handle;
private readonly Type parent;
private readonly EventDefinition ed;
public Event(Context cx, Type parent, EventDefinitionHandle handle) : base(cx)
{
this.handle = handle;
this.parent = parent;
ed = cx.MdReader.GetEventDefinition(handle);
}
public override void WriteId(EscapingTextWriter trapFile)
{
parent.WriteId(trapFile);
trapFile.Write('.');
trapFile.Write(Context.ShortName(ed.Name));
trapFile.Write(";cil-event");
}
public override bool Equals(object? obj)
{
return obj is Event e && handle.Equals(e.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
var signature = (Type)Context.CreateGeneric(parent, ed.Type);
yield return signature;
yield return Tuples.cil_event(this, parent, Context.ShortName(ed.Name), signature);
var accessors = ed.GetAccessors();
if (!accessors.Adder.IsNil)
{
var adder = (Method)Context.CreateGeneric(parent, accessors.Adder);
yield return adder;
yield return Tuples.cil_adder(this, adder);
}
if (!accessors.Remover.IsNil)
{
var remover = (Method)Context.CreateGeneric(parent, accessors.Remover);
yield return remover;
yield return Tuples.cil_remover(this, remover);
}
if (!accessors.Raiser.IsNil)
{
var raiser = (Method)Context.CreateGeneric(parent, accessors.Raiser);
yield return raiser;
yield return Tuples.cil_raiser(this, raiser);
}
foreach (var c in Attribute.Populate(Context, this, ed.GetCustomAttributes()))
yield return c;
}
}
}
}

Просмотреть файл

@ -1,56 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// An exception region entity.
/// </summary>
internal class ExceptionRegion : UnlabelledEntity
{
private readonly IGenericContext gc;
private readonly MethodImplementation method;
private readonly int index;
private readonly System.Reflection.Metadata.ExceptionRegion r;
private readonly Dictionary<int, Instruction> jump_table;
public ExceptionRegion(IGenericContext gc, MethodImplementation method, int index, System.Reflection.Metadata.ExceptionRegion r, Dictionary<int, Instruction> jump_table) : base(gc.Context)
{
this.gc = gc;
this.method = method;
this.index = index;
this.r = r;
this.jump_table = jump_table;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
if (!jump_table.TryGetValue(r.TryOffset, out var try_start))
throw new InternalError("Failed to retrieve handler");
if (!jump_table.TryGetValue(r.TryOffset + r.TryLength, out var try_end))
throw new InternalError("Failed to retrieve handler");
if (!jump_table.TryGetValue(r.HandlerOffset, out var handler_start))
throw new InternalError("Failed to retrieve handler");
yield return Tuples.cil_handler(this, method, index, (int)r.Kind, try_start, try_end, handler_start);
if (r.FilterOffset != -1)
{
if (!jump_table.TryGetValue(r.FilterOffset, out var filter_start))
throw new InternalError("ExceptionRegion filter clause");
yield return Tuples.cil_handler_filter(this, filter_start);
}
if (!r.CatchType.IsNil)
{
var catchType = (Type)Context.CreateGeneric(gc, r.CatchType);
yield return catchType;
yield return Tuples.cil_handler_type(this, catchType);
}
}
}
}
}

Просмотреть файл

@ -1,51 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// An entity representing a field.
/// </summary>
internal abstract class Field : LabelledEntity, IGenericContext, IMember, ICustomModifierReceiver
{
protected Field(Context cx) : base(cx)
{
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(DeclaringType);
trapFile.Write('.');
trapFile.Write(Name);
trapFile.Write(";cil-field");
}
public abstract string Name { get; }
public abstract Type DeclaringType { get; }
public abstract Type Type { get; }
public override IEnumerable<IExtractionProduct> Contents
{
get
{
var t = Type;
if (t is ModifiedType mt)
{
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
if (t is ByRefType brt)
{
t = brt.ElementType;
yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref);
}
yield return Tuples.cil_field(this, DeclaringType, Name, t);
}
}
public abstract IEnumerable<Type> TypeParameters { get; }
public abstract IEnumerable<Type> MethodParameters { get; }
}
}

Просмотреть файл

@ -1,43 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
internal class File : LabelledEntity, IFileOrFolder
{
protected string OriginalPath { get; }
protected PathTransformer.ITransformedPath TransformedPath { get; }
public File(Context cx, string path) : base(cx)
{
this.OriginalPath = path;
TransformedPath = Context.Extractor.PathTransformer.Transform(OriginalPath);
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(TransformedPath.DatabaseId);
trapFile.Write(";sourcefile");
}
public override bool Equals(object? obj)
{
return GetType() == obj?.GetType() && OriginalPath == ((File)obj).OriginalPath;
}
public override int GetHashCode() => 11 * OriginalPath.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
if (TransformedPath.ParentDirectory is PathTransformer.ITransformedPath dir)
{
var parent = Context.CreateFolder(dir);
yield return parent;
yield return Tuples.containerparent(parent, this);
}
yield return Tuples.files(this, TransformedPath.Value);
}
}
}
}

Просмотреть файл

@ -1,41 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class Folder : LabelledEntity, IFileOrFolder
{
private readonly PathTransformer.ITransformedPath transformedPath;
public Folder(Context cx, PathTransformer.ITransformedPath path) : base(cx)
{
this.transformedPath = path;
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.Write(transformedPath.DatabaseId);
trapFile.Write(";folder");
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
if (transformedPath.ParentDirectory is PathTransformer.ITransformedPath parent)
{
var parentFolder = Context.CreateFolder(parent);
yield return parentFolder;
yield return Tuples.containerparent(parentFolder, this);
}
yield return Tuples.folders(this, transformedPath.Value);
}
}
public override bool Equals(object? obj)
{
return obj is Folder folder && transformedPath == folder.transformedPath;
}
public override int GetHashCode() => transformedPath.GetHashCode();
}
}

Просмотреть файл

@ -1,114 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class FunctionPointerType : Type, IParameterizable, ICustomModifierReceiver
{
private readonly MethodSignature<Type> signature;
public FunctionPointerType(Context cx, MethodSignature<Type> signature) : base(cx)
{
this.signature = signature;
}
public override CilTypeKind Kind => CilTypeKind.FunctionPointer;
public override string Name
{
get
{
using var id = new StringWriter();
WriteName(
id.Write,
t => id.Write(t.Name),
signature
);
return id.ToString();
}
}
public override Namespace? ContainingNamespace => Context.GlobalNamespace;
public override Type? ContainingType => null;
public override int ThisTypeParameterCount => throw new System.NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new System.NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new System.NotImplementedException();
public override void WriteAssemblyPrefix(TextWriter trapFile) { }
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
WriteName(
trapFile.Write,
t => t.WriteId(trapFile, inContext),
signature
);
}
internal static void WriteName<TType>(Action<string> write, Action<TType> writeType, MethodSignature<TType> signature)
{
write("delegate* ");
write(GetCallingConvention(signature.Header.CallingConvention));
write("<");
foreach (var pt in signature.ParameterTypes)
{
writeType(pt);
write(",");
}
writeType(signature.ReturnType);
write(">");
}
internal static string GetCallingConvention(SignatureCallingConvention callingConvention)
{
if (callingConvention == SignatureCallingConvention.Default)
{
return "managed";
}
if (callingConvention == SignatureCallingConvention.Unmanaged)
{
return "unmanaged";
}
return $"unmanaged[{callingConvention}]";
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var c in base.Contents)
{
yield return c;
}
var retType = signature.ReturnType;
if (retType is ModifiedType mt)
{
retType = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
if (retType is ByRefType byRefType)
{
retType = byRefType.ElementType;
yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref);
}
yield return Tuples.cil_function_pointer_return_type(this, retType);
yield return Tuples.cil_function_pointer_calling_conventions(this, signature.Header.CallingConvention);
foreach (var p in Method.GetParameterExtractionProducts(signature.ParameterTypes, this, this, Context, 0))
{
yield return p;
}
}
}
}
}

Просмотреть файл

@ -1,59 +0,0 @@
using System.Collections.Generic;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
internal static class GenericsHelper
{
public static TypeTypeParameter[] MakeTypeParameters(Type container, int count)
{
var newTypeParams = new TypeTypeParameter[count];
for (var i = 0; i < newTypeParams.Length; ++i)
{
newTypeParams[i] = new TypeTypeParameter(container, i);
}
return newTypeParams;
}
public static string GetNonGenericName(StringHandle name, MetadataReader reader)
{
var n = reader.GetString(name);
return GetNonGenericName(n);
}
public static string GetNonGenericName(string name)
{
var tick = name.LastIndexOf('`');
return tick == -1
? name
: name.Substring(0, tick);
}
public static int GetGenericTypeParameterCount(StringHandle name, MetadataReader reader)
{
var n = reader.GetString(name);
return GetGenericTypeParameterCount(n);
}
public static int GetGenericTypeParameterCount(string name)
{
var tick = name.LastIndexOf('`');
return tick == -1
? 0
: int.Parse(name.Substring(tick + 1));
}
public static IEnumerable<Type> GetAllTypeParameters(Type? container, IEnumerable<TypeTypeParameter> thisTypeParameters)
{
if (container is not null)
{
foreach (var t in container.TypeParameters)
yield return t;
}
foreach (var t in thisTypeParameters)
yield return t;
}
}
}

Просмотреть файл

@ -1,6 +0,0 @@
namespace Semmle.Extraction.CIL.Entities
{
internal interface IFileOrFolder : IEntity
{
}
}

Просмотреть файл

@ -1,6 +0,0 @@
namespace Semmle.Extraction.CIL.Entities
{
public interface ILocation : IEntity
{
}
}

Просмотреть файл

@ -1,10 +0,0 @@
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// An entity representing a member.
/// Used to type tuples correctly.
/// </summary>
internal interface IMember : IExtractedEntity
{
}
}

Просмотреть файл

@ -1,7 +0,0 @@
namespace Semmle.Extraction.CIL.Entities
{
internal interface IParameterizable : IEntity
{
}
}

Просмотреть файл

@ -1,7 +0,0 @@
namespace Semmle.Extraction.CIL.Entities
{
internal interface ITypeSignature
{
void WriteId(EscapingTextWriter trapFile, IGenericContext gc);
}
}

Просмотреть файл

@ -1,508 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A CIL instruction.
/// </summary>
internal class Instruction : UnlabelledEntity
{
/// <summary>
/// The additional data following the opcode, if any.
/// </summary>
public enum Payload
{
None, TypeTok, Field, Target8, Class,
Method, Arg8, Local8, Target32, Int8,
Int16, Int32, Int64, Float32, Float64,
CallSiteDesc, Switch, String, Constructor, ValueType,
Type, Arg16, Ignore8, Token, Local16, MethodRef
}
/// <summary>
/// For each Payload, how many additional bytes in the bytestream need to be read.
/// </summary>
private static readonly int[] payloadSizes = {
0, 4, 4, 1, 4,
4, 1, 1, 4, 1,
2, 4, 8, 4, 8,
4, -1, 4, 4, 4,
4, 2, 1, 4, 2, 4 };
// Maps opcodes to payloads for each instruction.
private static readonly Dictionary<ILOpCode, Payload> opPayload = new Dictionary<ILOpCode, Payload>()
{
{ ILOpCode.Nop, Payload.None },
{ ILOpCode.Break, Payload.None },
{ ILOpCode.Ldarg_0, Payload.None },
{ ILOpCode.Ldarg_1, Payload.None },
{ ILOpCode.Ldarg_2, Payload.None },
{ ILOpCode.Ldarg_3, Payload.None },
{ ILOpCode.Ldloc_0, Payload.None },
{ ILOpCode.Ldloc_1, Payload.None },
{ ILOpCode.Ldloc_2, Payload.None },
{ ILOpCode.Ldloc_3, Payload.None },
{ ILOpCode.Stloc_0, Payload.None },
{ ILOpCode.Stloc_1, Payload.None },
{ ILOpCode.Stloc_2, Payload.None },
{ ILOpCode.Stloc_3, Payload.None },
{ ILOpCode.Ldarg_s, Payload.Arg8 },
{ ILOpCode.Ldarga_s, Payload.Arg8 },
{ ILOpCode.Starg_s, Payload.Arg8 },
{ ILOpCode.Ldloc_s, Payload.Local8 },
{ ILOpCode.Ldloca_s, Payload.Local8 },
{ ILOpCode.Stloc_s, Payload.Local8 },
{ ILOpCode.Ldnull, Payload.None },
{ ILOpCode.Ldc_i4_m1, Payload.None },
{ ILOpCode.Ldc_i4_0, Payload.None },
{ ILOpCode.Ldc_i4_1, Payload.None },
{ ILOpCode.Ldc_i4_2, Payload.None },
{ ILOpCode.Ldc_i4_3, Payload.None },
{ ILOpCode.Ldc_i4_4, Payload.None },
{ ILOpCode.Ldc_i4_5, Payload.None },
{ ILOpCode.Ldc_i4_6, Payload.None },
{ ILOpCode.Ldc_i4_7, Payload.None },
{ ILOpCode.Ldc_i4_8, Payload.None },
{ ILOpCode.Ldc_i4_s, Payload.Int8 },
{ ILOpCode.Ldc_i4, Payload.Int32 },
{ ILOpCode.Ldc_i8, Payload.Int64 },
{ ILOpCode.Ldc_r4, Payload.Float32 },
{ ILOpCode.Ldc_r8, Payload.Float64 },
{ ILOpCode.Dup, Payload.None },
{ ILOpCode.Pop, Payload.None },
{ ILOpCode.Jmp, Payload.Method },
{ ILOpCode.Call, Payload.Method },
{ ILOpCode.Calli, Payload.CallSiteDesc },
{ ILOpCode.Ret, Payload.None },
{ ILOpCode.Br_s, Payload.Target8 },
{ ILOpCode.Brfalse_s, Payload.Target8 },
{ ILOpCode.Brtrue_s, Payload.Target8 },
{ ILOpCode.Beq_s, Payload.Target8 },
{ ILOpCode.Bge_s, Payload.Target8 },
{ ILOpCode.Bgt_s, Payload.Target8 },
{ ILOpCode.Ble_s, Payload.Target8 },
{ ILOpCode.Blt_s, Payload.Target8 },
{ ILOpCode.Bne_un_s, Payload.Target8 },
{ ILOpCode.Bge_un_s, Payload.Target8 },
{ ILOpCode.Bgt_un_s, Payload.Target8 },
{ ILOpCode.Ble_un_s, Payload.Target8 },
{ ILOpCode.Blt_un_s, Payload.Target8 },
{ ILOpCode.Br, Payload.Target32 },
{ ILOpCode.Brfalse, Payload.Target32 },
{ ILOpCode.Brtrue, Payload.Target32 },
{ ILOpCode.Beq, Payload.Target32 },
{ ILOpCode.Bge, Payload.Target32 },
{ ILOpCode.Bgt, Payload.Target32 },
{ ILOpCode.Ble, Payload.Target32 },
{ ILOpCode.Blt, Payload.Target32 },
{ ILOpCode.Bne_un, Payload.Target32 },
{ ILOpCode.Bge_un, Payload.Target32 },
{ ILOpCode.Bgt_un, Payload.Target32 },
{ ILOpCode.Ble_un, Payload.Target32 },
{ ILOpCode.Blt_un, Payload.Target32 },
{ ILOpCode.Switch, Payload.Switch },
{ ILOpCode.Ldind_i1, Payload.None },
{ ILOpCode.Ldind_u1, Payload.None },
{ ILOpCode.Ldind_i2, Payload.None },
{ ILOpCode.Ldind_u2, Payload.None },
{ ILOpCode.Ldind_i4, Payload.None },
{ ILOpCode.Ldind_u4, Payload.None },
{ ILOpCode.Ldind_i8, Payload.None },
{ ILOpCode.Ldind_i, Payload.None },
{ ILOpCode.Ldind_r4, Payload.None },
{ ILOpCode.Ldind_r8, Payload.None },
{ ILOpCode.Ldind_ref, Payload.None },
{ ILOpCode.Stind_ref, Payload.None },
{ ILOpCode.Stind_i1, Payload.None },
{ ILOpCode.Stind_i2, Payload.None },
{ ILOpCode.Stind_i4, Payload.None },
{ ILOpCode.Stind_i8, Payload.None },
{ ILOpCode.Stind_r4, Payload.None },
{ ILOpCode.Stind_r8, Payload.None },
{ ILOpCode.Add, Payload.None },
{ ILOpCode.Sub, Payload.None },
{ ILOpCode.Mul, Payload.None },
{ ILOpCode.Div, Payload.None },
{ ILOpCode.Div_un, Payload.None },
{ ILOpCode.Rem, Payload.None },
{ ILOpCode.Rem_un, Payload.None },
{ ILOpCode.And, Payload.None },
{ ILOpCode.Or, Payload.None },
{ ILOpCode.Xor, Payload.None },
{ ILOpCode.Shl, Payload.None },
{ ILOpCode.Shr, Payload.None },
{ ILOpCode.Shr_un, Payload.None },
{ ILOpCode.Neg, Payload.None },
{ ILOpCode.Not, Payload.None },
{ ILOpCode.Conv_i1, Payload.None },
{ ILOpCode.Conv_i2, Payload.None },
{ ILOpCode.Conv_i4, Payload.None },
{ ILOpCode.Conv_i8, Payload.None },
{ ILOpCode.Conv_r4, Payload.None },
{ ILOpCode.Conv_r8, Payload.None },
{ ILOpCode.Conv_u4, Payload.None },
{ ILOpCode.Conv_u8, Payload.None },
{ ILOpCode.Callvirt, Payload.MethodRef },
{ ILOpCode.Cpobj, Payload.TypeTok },
{ ILOpCode.Ldobj, Payload.TypeTok },
{ ILOpCode.Ldstr, Payload.String },
{ ILOpCode.Newobj, Payload.Constructor },
{ ILOpCode.Castclass, Payload.Class },
{ ILOpCode.Isinst, Payload.Class },
{ ILOpCode.Conv_r_un, Payload.None },
{ ILOpCode.Unbox, Payload.ValueType },
{ ILOpCode.Throw, Payload.None },
{ ILOpCode.Ldfld, Payload.Field },
{ ILOpCode.Ldflda, Payload.Field },
{ ILOpCode.Stfld, Payload.Field },
{ ILOpCode.Ldsfld, Payload.Field },
{ ILOpCode.Ldsflda, Payload.Field },
{ ILOpCode.Stsfld, Payload.Field },
{ ILOpCode.Stobj, Payload.Field },
{ ILOpCode.Conv_ovf_i1_un, Payload.None },
{ ILOpCode.Conv_ovf_i2_un, Payload.None },
{ ILOpCode.Conv_ovf_i4_un, Payload.None },
{ ILOpCode.Conv_ovf_i8_un, Payload.None },
{ ILOpCode.Conv_ovf_u1_un, Payload.None },
{ ILOpCode.Conv_ovf_u2_un, Payload.None },
{ ILOpCode.Conv_ovf_u4_un, Payload.None },
{ ILOpCode.Conv_ovf_u8_un, Payload.None },
{ ILOpCode.Conv_ovf_i_un, Payload.None },
{ ILOpCode.Conv_ovf_u_un, Payload.None },
{ ILOpCode.Box, Payload.TypeTok },
{ ILOpCode.Newarr, Payload.TypeTok },
{ ILOpCode.Ldlen, Payload.None },
{ ILOpCode.Ldelema, Payload.Class },
{ ILOpCode.Ldelem_i1, Payload.None },
{ ILOpCode.Ldelem_u1, Payload.None },
{ ILOpCode.Ldelem_i2, Payload.None },
{ ILOpCode.Ldelem_u2, Payload.None },
{ ILOpCode.Ldelem_i4, Payload.None },
{ ILOpCode.Ldelem_u4, Payload.None },
{ ILOpCode.Ldelem_i8, Payload.None },
{ ILOpCode.Ldelem_i, Payload.None },
{ ILOpCode.Ldelem_r4, Payload.None },
{ ILOpCode.Ldelem_r8, Payload.None },
{ ILOpCode.Ldelem_ref, Payload.None },
{ ILOpCode.Stelem_i, Payload.None },
{ ILOpCode.Stelem_i1, Payload.None },
{ ILOpCode.Stelem_i2, Payload.None },
{ ILOpCode.Stelem_i4, Payload.None },
{ ILOpCode.Stelem_i8, Payload.None },
{ ILOpCode.Stelem_r4, Payload.None },
{ ILOpCode.Stelem_r8, Payload.None },
{ ILOpCode.Stelem_ref, Payload.None },
{ ILOpCode.Ldelem, Payload.TypeTok },
{ ILOpCode.Stelem, Payload.TypeTok },
{ ILOpCode.Unbox_any, Payload.TypeTok },
{ ILOpCode.Conv_ovf_i1, Payload.None },
{ ILOpCode.Conv_ovf_u1, Payload.None },
{ ILOpCode.Conv_ovf_i2, Payload.None },
{ ILOpCode.Conv_ovf_u2, Payload.None },
{ ILOpCode.Conv_ovf_i4, Payload.None },
{ ILOpCode.Conv_ovf_u4, Payload.None },
{ ILOpCode.Conv_ovf_i8, Payload.None },
{ ILOpCode.Conv_ovf_u8, Payload.None },
{ ILOpCode.Refanyval, Payload.Type },
{ ILOpCode.Ckfinite, Payload.None },
{ ILOpCode.Mkrefany, Payload.Class },
{ ILOpCode.Ldtoken, Payload.Token },
{ ILOpCode.Conv_u2, Payload.None },
{ ILOpCode.Conv_u1, Payload.None },
{ ILOpCode.Conv_i, Payload.None },
{ ILOpCode.Conv_ovf_i, Payload.None },
{ ILOpCode.Conv_ovf_u, Payload.None },
{ ILOpCode.Add_ovf, Payload.None },
{ ILOpCode.Add_ovf_un, Payload.None },
{ ILOpCode.Mul_ovf, Payload.None },
{ ILOpCode.Mul_ovf_un, Payload.None },
{ ILOpCode.Sub_ovf, Payload.None },
{ ILOpCode.Sub_ovf_un, Payload.None },
{ ILOpCode.Endfinally, Payload.None },
{ ILOpCode.Leave, Payload.Target32 },
{ ILOpCode.Leave_s, Payload.Target8 },
{ ILOpCode.Stind_i, Payload.None },
{ ILOpCode.Conv_u, Payload.None },
{ ILOpCode.Arglist, Payload.None },
{ ILOpCode.Ceq, Payload.None },
{ ILOpCode.Cgt, Payload.None },
{ ILOpCode.Cgt_un, Payload.None },
{ ILOpCode.Clt, Payload.None },
{ ILOpCode.Clt_un, Payload.None },
{ ILOpCode.Ldftn, Payload.Method },
{ ILOpCode.Ldvirtftn, Payload.Method },
{ ILOpCode.Ldarg, Payload.Arg16 },
{ ILOpCode.Ldarga, Payload.Arg16 },
{ ILOpCode.Starg, Payload.Arg16 },
{ ILOpCode.Ldloc, Payload.Local16 },
{ ILOpCode.Ldloca, Payload.Local16 },
{ ILOpCode.Stloc, Payload.Local16 },
{ ILOpCode.Localloc, Payload.None },
{ ILOpCode.Endfilter, Payload.None },
{ ILOpCode.Unaligned, Payload.Ignore8 },
{ ILOpCode.Volatile, Payload.None },
{ ILOpCode.Tail, Payload.None },
{ ILOpCode.Initobj, Payload.TypeTok },
{ ILOpCode.Constrained, Payload.Type },
{ ILOpCode.Cpblk, Payload.None },
{ ILOpCode.Initblk, Payload.None },
{ ILOpCode.Rethrow, Payload.None },
{ ILOpCode.Sizeof, Payload.TypeTok },
{ ILOpCode.Refanytype, Payload.None },
{ ILOpCode.Readonly, Payload.None }
};
public DefinitionMethod Method { get; }
public ILOpCode OpCode { get; }
public int Offset { get; }
public int Index { get; }
private readonly int payloadValue;
private readonly uint unsignedPayloadValue;
public Payload PayloadType
{
get
{
if (!opPayload.TryGetValue(OpCode, out var result))
throw new InternalError("Unknown op code " + OpCode);
return result;
}
}
public override string ToString() => Index + ": " + OpCode;
/// <summary>
/// The number of bytes of this instruction,
/// including the payload (if any).
/// </summary>
public int Width
{
get
{
if (OpCode == ILOpCode.Switch)
return 5 + 4 * payloadValue;
return ((int)OpCode > 255 ? 2 : 1) + PayloadSize;
}
}
private readonly byte[] data;
private int PayloadSize => payloadSizes[(int)PayloadType];
/// <summary>
/// Reads the instruction from a byte stream.
/// </summary>
/// <param name="data">The byte stream.</param>
/// <param name="offset">The offset of the instruction.</param>
/// <param name="index">The index of this instruction in the callable.</param>
public Instruction(Context cx, DefinitionMethod method, byte[] data, int offset, int index) : base(cx)
{
Method = method;
Offset = offset;
Index = index;
this.data = data;
int opcode = data[offset];
++offset;
/*
* An opcode is either 1 or 2 bytes, followed by an optional payload depending on the instruction.
* Instructions where the first byte is 0xfe are 2-byte instructions.
*/
if (opcode == 0xfe)
opcode = opcode << 8 | data[offset++];
OpCode = (ILOpCode)opcode;
switch (PayloadSize)
{
case 0:
payloadValue = 0;
break;
case 1:
payloadValue = (sbyte)data[offset];
unsignedPayloadValue = data[offset];
break;
case 2:
payloadValue = BitConverter.ToInt16(data, offset);
unsignedPayloadValue = BitConverter.ToUInt16(data, offset);
break;
case -1: // Switch
case 4:
payloadValue = BitConverter.ToInt32(data, offset);
break;
case 8: // Not handled here.
break;
default:
throw new InternalError("Unhandled CIL instruction Payload");
}
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
var offset = Offset;
if (Method.Implementation is null)
{
yield break;
}
yield return Tuples.cil_instruction(this, (int)OpCode, Index, Method.Implementation);
switch (PayloadType)
{
case Payload.String:
yield return Tuples.cil_value(this, Context.MdReader.GetUserString(MetadataTokens.UserStringHandle(payloadValue)));
break;
case Payload.Float32:
yield return Tuples.cil_value(this, BitConverter.ToSingle(data, offset).ToString());
break;
case Payload.Float64:
yield return Tuples.cil_value(this, BitConverter.ToDouble(data, offset).ToString());
break;
case Payload.Int8:
yield return Tuples.cil_value(this, data[offset].ToString());
break;
case Payload.Int16:
yield return Tuples.cil_value(this, BitConverter.ToInt16(data, offset).ToString());
break;
case Payload.Int32:
yield return Tuples.cil_value(this, BitConverter.ToInt32(data, offset).ToString());
break;
case Payload.Int64:
yield return Tuples.cil_value(this, BitConverter.ToInt64(data, offset).ToString());
break;
case Payload.Constructor:
case Payload.Method:
case Payload.MethodRef:
case Payload.Class:
case Payload.TypeTok:
case Payload.Token:
case Payload.Type:
case Payload.Field:
case Payload.ValueType:
{
// A generic EntityHandle.
var handle = MetadataTokens.EntityHandle(payloadValue);
var target = Context.CreateGeneric(Method, handle);
yield return target;
if (target is not null)
{
yield return Tuples.cil_access(this, target);
}
else
{
throw new InternalError($"Unable to create payload type {PayloadType} for opcode {OpCode}");
}
break;
}
case Payload.Arg8:
case Payload.Arg16:
if (Method.Parameters is not null)
{
yield return Tuples.cil_access(this, Method.Parameters[(int)unsignedPayloadValue]);
}
break;
case Payload.Local8:
case Payload.Local16:
if (Method.LocalVariables is not null)
{
yield return Tuples.cil_access(this, Method.LocalVariables[(int)unsignedPayloadValue]);
}
break;
case Payload.None:
case Payload.Target8:
case Payload.Target32:
case Payload.Switch:
case Payload.Ignore8:
// These are not handled here.
// Some of these are handled by JumpContents().
break;
case Payload.CallSiteDesc:
{
var handle = MetadataTokens.EntityHandle(payloadValue);
IExtractedEntity? target = null;
try
{
target = Context.CreateGeneric(Method, handle);
}
catch (Exception exc)
{
Context.Extractor.Logger.Log(Util.Logging.Severity.Warning, $"Couldn't interpret payload of payload type {PayloadType} as a function pointer type. {exc.Message} {exc.StackTrace}");
}
if (target is not null)
{
yield return target;
yield return Tuples.cil_access(this, target);
}
else
{
throw new InternalError($"Unable to create payload type {PayloadType} for opcode {OpCode}");
}
break;
}
default:
throw new InternalError($"Unhandled payload type {PayloadType}");
}
}
}
// Called to populate the jumps in each instruction.
public IEnumerable<IExtractionProduct> JumpContents(Dictionary<int, Instruction> jump_table)
{
int target;
Instruction? inst;
switch (PayloadType)
{
case Payload.Target8:
target = Offset + payloadValue + 2;
break;
case Payload.Target32:
target = Offset + payloadValue + 5;
break;
case Payload.Switch:
var end = Offset + Width;
var offset = Offset + 5;
for (var b = 0; b < payloadValue; ++b, offset += 4)
{
target = BitConverter.ToInt32(data, offset) + end;
if (jump_table.TryGetValue(target, out inst))
{
yield return Tuples.cil_switch(this, b, inst);
}
else
{
throw new InternalError("Invalid jump target");
}
}
yield break;
default:
// Not a jump
yield break;
}
if (jump_table.TryGetValue(target, out inst))
{
yield return Tuples.cil_jump(this, inst);
}
else
{
// Sometimes instructions can jump outside the current method.
// TODO: Find a solution to this.
// For now, just log the error
Context.ExtractionError("A CIL instruction jumps outside the current method", null, Extraction.Entities.GeneratedLocation.Create(Context), "", Util.Logging.Severity.Warning);
}
}
}
}

Просмотреть файл

@ -1,35 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
internal class LocalVariable : LabelledEntity
{
private readonly MethodImplementation method;
private readonly int index;
private readonly Type type;
public LocalVariable(Context cx, MethodImplementation m, int i, Type t) : base(cx)
{
method = m;
index = i;
type = t;
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(method);
trapFile.Write('_');
trapFile.Write(index);
trapFile.Write(";cil-local");
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return type;
yield return Tuples.cil_local_variable(this, method, index, type);
}
}
}
}

Просмотреть файл

@ -1,42 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class MemberReferenceField : Field
{
private readonly MemberReferenceHandle handle;
private readonly MemberReference mr;
private readonly IGenericContext gc;
private readonly Type declType;
public MemberReferenceField(IGenericContext gc, MemberReferenceHandle handle) : base(gc.Context)
{
this.handle = handle;
this.gc = gc;
mr = Context.MdReader.GetMemberReference(handle);
declType = (Type)Context.CreateGeneric(gc, mr.Parent);
}
public override bool Equals(object? obj)
{
return obj is MemberReferenceField field && handle.Equals(field.handle);
}
public override int GetHashCode()
{
return handle.GetHashCode();
}
public override string Name => Context.GetString(mr.Name);
public override Type DeclaringType => declType;
public override Type Type => mr.DecodeFieldSignature(Context.TypeSignatureDecoder, this);
public override IEnumerable<Type> TypeParameters => gc.TypeParameters.Concat(declType.TypeParameters);
public override IEnumerable<Type> MethodParameters => gc.MethodParameters.Concat(declType.MethodParameters);
}
}

Просмотреть файл

@ -1,95 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// This is a late-bound reference to a method.
/// </summary>
internal sealed class MemberReferenceMethod : Method
{
private readonly MemberReferenceHandle handle;
private readonly MemberReference mr;
private readonly Type declaringType;
private readonly IGenericContext parent;
private readonly Method? sourceDeclaration;
public MemberReferenceMethod(IGenericContext gc, MemberReferenceHandle handle) : base(gc)
{
this.handle = handle;
this.gc = gc;
mr = Context.MdReader.GetMemberReference(handle);
signature = mr.DecodeMethodSignature(new SignatureDecoder(), gc);
parent = (IGenericContext)Context.CreateGeneric(gc, mr.Parent);
var declType = parent is Method parentMethod
? parentMethod.DeclaringType
: parent as Type;
if (declType is null)
throw new InternalError("Parent context of method is not a type");
declaringType = declType;
nameLabel = Context.GetString(mr.Name);
var typeSourceDeclaration = declaringType.SourceDeclaration;
sourceDeclaration = typeSourceDeclaration == declaringType ? (Method)this : typeSourceDeclaration.LookupMethod(mr.Name, mr.Signature);
}
private readonly string nameLabel;
public override string NameLabel => nameLabel;
public override bool Equals(object? obj)
{
return obj is MemberReferenceMethod method && handle.Equals(method.handle);
}
public override int GetHashCode()
{
return handle.GetHashCode();
}
public override Method? SourceDeclaration => sourceDeclaration;
public override bool IsStatic => !signature.Header.IsInstance;
public override Type DeclaringType => declaringType;
public override string Name => Context.ShortName(mr.Name);
public override IEnumerable<Type> TypeParameters => parent.TypeParameters.Concat(gc.TypeParameters);
public override IEnumerable<IExtractionProduct> Contents
{
get
{
genericParams = new MethodTypeParameter[signature.GenericParameterCount];
for (var p = 0; p < genericParams.Length; ++p)
genericParams[p] = Context.Populate(new MethodTypeParameter(this, this, p));
foreach (var p in genericParams)
yield return p;
var typeSignature = mr.DecodeMethodSignature(Context.TypeSignatureDecoder, this);
var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray();
Parameters = parameters.OfType<Parameter>().ToArray();
foreach (var p in parameters) yield return p;
foreach (var f in PopulateFlags) yield return f;
foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, typeSignature.ReturnType))
{
yield return m;
}
if (SourceDeclaration is not null)
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);
}
}
}
}

Просмотреть файл

@ -1,131 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A method entity.
/// </summary>
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver, IParameterizable
{
protected MethodTypeParameter[]? genericParams;
protected IGenericContext gc;
protected MethodSignature<ITypeSignature> signature;
protected Method(IGenericContext gc) : base(gc.Context)
{
this.gc = gc;
}
public ITypeSignature ReturnType => signature.ReturnType;
public override IEnumerable<Type> TypeParameters => gc.TypeParameters.Concat(DeclaringType.TypeParameters);
public override IEnumerable<Type> MethodParameters =>
genericParams is null ? gc.MethodParameters : gc.MethodParameters.Concat(genericParams);
public int GenericParameterCount => signature.GenericParameterCount;
public virtual Method? SourceDeclaration => this;
public abstract Type DeclaringType { get; }
public abstract string Name { get; }
public virtual IList<LocalVariable>? LocalVariables => throw new NotImplementedException();
public IList<Parameter>? Parameters { get; protected set; }
public abstract string NameLabel { get; }
public override void WriteId(EscapingTextWriter trapFile)
{
signature.ReturnType.WriteId(trapFile, this);
trapFile.Write(' ');
DeclaringType.WriteId(trapFile);
trapFile.Write('.');
trapFile.Write(NameLabel);
if (signature.GenericParameterCount > 0)
{
trapFile.Write('`');
trapFile.Write(signature.GenericParameterCount);
}
trapFile.Write('(');
var index = 0;
foreach (var param in signature.ParameterTypes)
{
trapFile.WriteSeparator(",", ref index);
param.WriteId(trapFile, this);
}
trapFile.Write(");cil-method");
}
protected IEnumerable<IExtractionProduct> PopulateFlags
{
get
{
if (IsStatic)
yield return Tuples.cil_static(this);
}
}
public abstract bool IsStatic { get; }
protected IEnumerable<IExtractionProduct> GetParameterExtractionProducts(IEnumerable<Type> parameterTypes)
{
var i = 0;
if (!IsStatic)
{
yield return Context.Populate(new Parameter(Context, this, i++, DeclaringType));
}
foreach (var p in GetParameterExtractionProducts(parameterTypes, this, this, Context, i))
{
yield return p;
}
}
internal static IEnumerable<IExtractionProduct> GetParameterExtractionProducts(IEnumerable<Type> parameterTypes, IParameterizable parameterizable, ICustomModifierReceiver receiver, Context cx, int firstChildIndex)
{
var i = firstChildIndex;
foreach (var p in parameterTypes)
{
var t = p;
if (t is ModifiedType mt)
{
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(receiver, mt.Modifier, mt.IsRequired);
}
if (t is ByRefType brt)
{
t = brt.ElementType;
var parameter = cx.Populate(new Parameter(cx, parameterizable, i++, t));
yield return parameter;
yield return Tuples.cil_type_annotation(parameter, TypeAnnotation.Ref);
}
else
{
yield return cx.Populate(new Parameter(cx, parameterizable, i++, t));
}
}
}
protected IEnumerable<IExtractionProduct> GetMethodExtractionProducts(string name, Type declaringType, Type returnType)
{
var t = returnType;
if (t is ModifiedType mt)
{
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
if (t is ByRefType brt)
{
t = brt.ElementType;
yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref);
}
yield return Tuples.cil_method(this, name, declaringType, t);
}
}
}

Просмотреть файл

@ -1,26 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A method implementation entity.
/// In the database, the same method could in principle have multiple implementations.
/// </summary>
internal class MethodImplementation : UnlabelledEntity
{
private readonly Method m;
public MethodImplementation(Method m) : base(m.Context)
{
this.m = m;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.cil_method_implementation(this, m, Context.Assembly);
}
}
}
}

Просмотреть файл

@ -1,104 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.Metadata;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A constructed method.
/// </summary>
internal sealed class MethodSpecificationMethod : Method
{
private readonly MethodSpecificationHandle handle;
private readonly MethodSpecification ms;
private readonly Method unboundMethod;
private readonly ImmutableArray<Type> typeParams;
public MethodSpecificationMethod(IGenericContext gc, MethodSpecificationHandle handle) : base(gc)
{
this.handle = handle;
ms = Context.MdReader.GetMethodSpecification(handle);
typeParams = ms.DecodeSignature(Context.TypeSignatureDecoder, gc);
unboundMethod = (Method)Context.CreateGeneric(gc, ms.Method);
}
public override void WriteId(EscapingTextWriter trapFile)
{
unboundMethod.WriteId(trapFile);
trapFile.Write('<');
var index = 0;
foreach (var param in typeParams)
{
trapFile.WriteSeparator(",", ref index);
trapFile.WriteSubId(param);
}
trapFile.Write('>');
}
public override string NameLabel => throw new NotImplementedException();
public override bool Equals(object? obj)
{
return obj is MethodSpecificationMethod method && handle.Equals(method.handle) && typeParams.SequenceEqual(method.typeParams);
}
public override int GetHashCode() => handle.GetHashCode() * 11 + typeParams.SequenceHash();
public override Method SourceDeclaration => unboundMethod;
public override Type DeclaringType => unboundMethod.DeclaringType;
public override string Name => unboundMethod.Name;
public override bool IsStatic => unboundMethod.IsStatic;
public override IEnumerable<Type> MethodParameters => typeParams;
public override IEnumerable<IExtractionProduct> Contents
{
get
{
MethodSignature<Type> constructedTypeSignature;
switch (ms.Method.Kind)
{
case HandleKind.MemberReference:
var mr = Context.MdReader.GetMemberReference((MemberReferenceHandle)ms.Method);
constructedTypeSignature = mr.DecodeMethodSignature(Context.TypeSignatureDecoder, this);
break;
case HandleKind.MethodDefinition:
var md = Context.MdReader.GetMethodDefinition((MethodDefinitionHandle)ms.Method);
constructedTypeSignature = md.DecodeSignature(Context.TypeSignatureDecoder, this);
break;
default:
throw new InternalError($"Unexpected constructed method handle kind {ms.Method.Kind}");
}
var parameters = GetParameterExtractionProducts(constructedTypeSignature.ParameterTypes).ToArray();
Parameters = parameters.OfType<Parameter>().ToArray();
foreach (var p in parameters)
yield return p;
foreach (var f in PopulateFlags)
yield return f;
foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, constructedTypeSignature.ReturnType))
{
yield return m;
}
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);
if (typeParams.Length != unboundMethod.GenericParameterCount)
throw new InternalError("Method type parameter mismatch");
for (var p = 0; p < typeParams.Length; ++p)
{
yield return Tuples.cil_type_argument(this, p, typeParams[p]);
}
}
}
}
}

Просмотреть файл

@ -1,52 +0,0 @@
using System;
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class MethodTypeParameter : TypeParameter
{
private readonly Method method;
private readonly int index;
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
if (!(inContext && method == gc))
{
trapFile.WriteSubId(method);
}
trapFile.Write("!");
trapFile.Write(index);
}
public override string Name => "!" + index;
public MethodTypeParameter(IGenericContext gc, Method m, int index) : base(gc)
{
method = m;
this.index = index;
}
public override bool Equals(object? obj)
{
return obj is MethodTypeParameter tp && method.Equals(tp.method) && index == tp.index;
}
public override int GetHashCode()
{
return method.GetHashCode() * 29 + index;
}
public override TypeContainer Parent => method;
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.cil_type(this, Name, Kind, method, SourceDeclaration);
yield return Tuples.cil_type_parameter(method, index, this);
}
}
}
}

Просмотреть файл

@ -1,49 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Modified types are not written directly to trap files. Instead, the modifiers are stored
/// on the modifiable entity (field type, property/method/function pointer parameter or return types).
/// </summary>
internal sealed class ModifiedType : Type
{
public ModifiedType(Context cx, Type unmodified, Type modifier, bool isRequired) : base(cx)
{
Unmodified = unmodified;
Modifier = modifier;
IsRequired = isRequired;
}
public Type Unmodified { get; }
public Type Modifier { get; }
public bool IsRequired { get; }
public override CilTypeKind Kind => throw new NotImplementedException();
public override Namespace? ContainingNamespace => throw new NotImplementedException();
public override Type? ContainingType => throw new NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override int ThisTypeParameterCount => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
public override string Name => $"{Unmodified.Name} {(IsRequired ? "modreq" : "modopt")}({Modifier.Name})";
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
Unmodified.WriteId(trapFile, inContext);
trapFile.Write(IsRequired ? " modreq" : " modopt");
trapFile.Write("(");
Modifier.WriteId(trapFile, inContext);
trapFile.Write(")");
}
}
}

Просмотреть файл

@ -1,61 +0,0 @@
using System.Linq;
namespace Semmle.Extraction.CIL.Entities
{
internal class NamedTypeIdWriter
{
private readonly Type type;
public NamedTypeIdWriter(Type type)
{
this.type = type;
}
public void WriteId(EscapingTextWriter trapFile, bool inContext)
{
if (type.IsPrimitiveType)
{
Type.WritePrimitiveTypeId(trapFile, type.Name);
return;
}
var ct = type.ContainingType;
if (ct is not null)
{
ct.WriteId(trapFile, inContext);
trapFile.Write('.');
}
else
{
type.WriteAssemblyPrefix(trapFile);
var ns = type.ContainingNamespace!;
if (!ns.IsGlobalNamespace)
{
ns.WriteId(trapFile);
trapFile.Write('.');
}
}
trapFile.Write(type.Name);
var thisTypeArguments = type.ThisTypeArguments;
if (thisTypeArguments is not null && thisTypeArguments.Any())
{
trapFile.Write('<');
var index = 0;
foreach (var t in thisTypeArguments)
{
trapFile.WriteSeparator(",", ref index);
t.WriteId(trapFile);
}
trapFile.Write('>');
}
else if (type.ThisTypeParameterCount > 0)
{
trapFile.Write('`');
trapFile.Write(type.ThisTypeParameterCount);
}
}
}
}

Просмотреть файл

@ -1,83 +0,0 @@
using System;
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A namespace.
/// </summary>
internal sealed class Namespace : TypeContainer
{
public Namespace? ParentNamespace { get; }
public string Name { get; }
public bool IsGlobalNamespace => ParentNamespace is null;
public override void WriteId(EscapingTextWriter trapFile)
{
if (ParentNamespace is not null && !ParentNamespace.IsGlobalNamespace)
{
ParentNamespace.WriteId(trapFile);
trapFile.Write('.');
}
trapFile.Write(Name);
trapFile.Write(";namespace");
}
public override bool Equals(object? obj)
{
if (obj is Namespace ns && Name == ns.Name)
{
if (ParentNamespace is null)
return ns.ParentNamespace is null;
if (!(ns.ParentNamespace is null))
return ParentNamespace.Equals(ns.ParentNamespace);
}
return false;
}
public override int GetHashCode()
{
var h = ParentNamespace is null ? 19 : ParentNamespace.GetHashCode();
return 13 * h + Name.GetHashCode();
}
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override IEnumerable<Type> MethodParameters => throw new NotImplementedException();
private static string parseNamespaceName(string fqn)
{
var i = fqn.LastIndexOf('.');
return i == -1 ? fqn : fqn.Substring(i + 1);
}
private static Namespace? createParentNamespace(Context cx, string fqn)
{
if (fqn.Length == 0)
return null;
var i = fqn.LastIndexOf('.');
return i == -1 ? cx.GlobalNamespace : cx.Populate(new Namespace(cx, fqn.Substring(0, i)));
}
public Namespace(Context cx, string fqn) : this(cx, parseNamespaceName(fqn), createParentNamespace(cx, fqn))
{
}
public Namespace(Context cx, string name, Namespace? parent) : base(cx)
{
Name = name;
ParentNamespace = parent;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.namespaces(this, Name);
if (ParentNamespace is not null)
yield return Tuples.parent_namespace(this, ParentNamespace);
}
}
}
}

Просмотреть файл

@ -1,162 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed partial class NoMetadataHandleType
{
/// <summary>
/// Parser to split a fully qualified name into short name, namespace or declaring type name, assembly name, and
/// type argument names. Names are in the following format:
/// <c>N1.N2.T1`2+T2`2[T3,[T4, A1, Version=...],T5,T6], A2, Version=...</c>
/// </summary>
/// <example>
/// <code>typeof(System.Collections.Generic.List<int>.Enumerator)
/// -> System.Collections.Generic.List`1+Enumerator[[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
/// typeof(System.Collections.Generic.List<>.Enumerator)
/// -> System.Collections.Generic.List`1+Enumerator, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
/// </code>
/// </example>
private class FullyQualifiedNameParser
{
public string ShortName { get; internal set; }
public string? AssemblyName { get; private set; }
public IEnumerable<string>? TypeArguments { get; internal set; }
public string? UnboundGenericTypeName { get; internal set; }
public string ContainerName { get; internal set; }
public bool IsContainerNamespace { get; internal set; }
private string AssemblySuffix => string.IsNullOrWhiteSpace(AssemblyName) ? "" : $", {AssemblyName}";
public FullyQualifiedNameParser(string name)
{
ExtractAssemblyName(ref name, out var lastBracketIndex);
ExtractTypeArguments(ref name, lastBracketIndex, out var containerTypeArguments);
ContainerName = ExtractContainer(ref name, containerTypeArguments);
ShortName = name;
}
private void ExtractTypeArguments(ref string name, int lastBracketIndex, out string containerTypeArguments)
{
var firstBracketIndex = name.IndexOf('[');
if (firstBracketIndex < 0)
{
// not generic or non-constructed generic
TypeArguments = null;
containerTypeArguments = "";
UnboundGenericTypeName = null;
return;
}
// "T3,[T4, Assembly1, Version=...],T5,T6"
string typeArgs;
(name, _, typeArgs, _) = name.Split(firstBracketIndex, firstBracketIndex + 1, lastBracketIndex);
var thisTypeArgCount = GenericsHelper.GetGenericTypeParameterCount(name);
if (thisTypeArgCount == 0)
{
// not generic or non-constructed generic; container is constructed
TypeArguments = null;
containerTypeArguments = $"[{typeArgs}]";
UnboundGenericTypeName = null;
return;
}
// constructed generic
// "T3,[T4, Assembly1, Version=...]", ["T5", "T6"]
var (containerTypeArgs, thisTypeArgs) = ParseTypeArgumentStrings(typeArgs, thisTypeArgCount);
TypeArguments = thisTypeArgs;
containerTypeArguments = string.IsNullOrWhiteSpace(containerTypeArgs)
? "" // containing type is not constructed generics
: $"[{containerTypeArgs}]"; // "T3,[T4, Assembly1, Version=...],,]"
UnboundGenericTypeName = $"{name}{AssemblySuffix}";
}
private string ExtractContainer(ref string name, string containerTypeArguments)
{
var lastPlusIndex = name.LastIndexOf('+');
IsContainerNamespace = lastPlusIndex < 0;
if (IsContainerNamespace)
{
return ExtractContainerNamespace(ref name);
}
return ExtractContainerType(ref name, containerTypeArguments, lastPlusIndex);
}
private static string ExtractContainerNamespace(ref string name)
{
var lastDotIndex = name.LastIndexOf('.');
if (lastDotIndex >= 0)
{
string containerName;
(containerName, _, name) = name.Split(lastDotIndex, lastDotIndex + 1);
return containerName;
}
return ""; // global namespace name
}
private string ExtractContainerType(ref string name, string containerTypeArguments, int lastPlusIndex)
{
string containerName;
(containerName, _, name) = name.Split(lastPlusIndex, lastPlusIndex + 1);
return $"{containerName}{containerTypeArguments}{AssemblySuffix}";
}
private void ExtractAssemblyName(ref string name, out int lastBracketIndex)
{
lastBracketIndex = name.LastIndexOf(']');
var assemblyCommaIndex = name.IndexOf(',', lastBracketIndex < 0 ? 0 : lastBracketIndex);
if (assemblyCommaIndex >= 0)
{
// "Assembly2, Version=..."
(name, _, AssemblyName) = name.Split(assemblyCommaIndex, assemblyCommaIndex + 2);
}
}
private static (string, IEnumerable<string>) ParseTypeArgumentStrings(string typeArgs, int thisTypeArgCount)
{
var thisTypeArgs = new Stack<string>(thisTypeArgCount);
while (typeArgs.Length > 0 && thisTypeArgCount > 0)
{
int startCurrentType;
if (typeArgs[^1] != ']')
{
startCurrentType = typeArgs.LastIndexOf(',') + 1;
thisTypeArgs.Push(typeArgs.Substring(startCurrentType));
}
else
{
var bracketCount = 1;
for (startCurrentType = typeArgs.Length - 2; startCurrentType >= 0 && bracketCount > 0; startCurrentType--)
{
if (typeArgs[startCurrentType] == ']')
{
bracketCount++;
}
else if (typeArgs[startCurrentType] == '[')
{
bracketCount--;
}
}
startCurrentType++;
thisTypeArgs.Push(typeArgs[(startCurrentType + 1)..^1]);
}
typeArgs = startCurrentType != 0
? typeArgs.Substring(0, startCurrentType - 1)
: "";
thisTypeArgCount--;
}
return (typeArgs, thisTypeArgs.ToList());
}
}
}
}

Просмотреть файл

@ -1,161 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed partial class NoMetadataHandleType : Type
{
private readonly string originalName;
private readonly string name;
private readonly string? assemblyName;
private readonly string containerName;
private readonly bool isContainerNamespace;
private readonly Lazy<TypeTypeParameter[]>? typeParams;
// Either null or notEmpty
private readonly Type[]? thisTypeArguments;
private readonly Type unboundGenericType;
private readonly Type? containingType;
private readonly Namespace? containingNamespace;
private readonly NamedTypeIdWriter idWriter;
public NoMetadataHandleType(Context cx, string originalName) : base(cx)
{
this.originalName = originalName;
this.idWriter = new NamedTypeIdWriter(this);
var nameParser = new FullyQualifiedNameParser(originalName);
name = nameParser.ShortName;
assemblyName = nameParser.AssemblyName;
isContainerNamespace = nameParser.IsContainerNamespace;
containerName = nameParser.ContainerName;
unboundGenericType = nameParser.UnboundGenericTypeName is null
? this
: new NoMetadataHandleType(Context, nameParser.UnboundGenericTypeName);
if (nameParser.TypeArguments is not null)
{
thisTypeArguments = nameParser.TypeArguments.Select(t => new NoMetadataHandleType(Context, t)).ToArray();
}
else
{
typeParams = new Lazy<TypeTypeParameter[]>(GenericsHelper.MakeTypeParameters(this, ThisTypeParameterCount));
}
containingType = isContainerNamespace
? null
: new NoMetadataHandleType(Context, containerName);
containingNamespace = isContainerNamespace
? containerName == Context.GlobalNamespace.Name
? Context.GlobalNamespace
: containerName == Context.SystemNamespace.Name
? Context.SystemNamespace
: new Namespace(Context, containerName)
: null;
Populate();
}
private void Populate()
{
if (ContainingNamespace is not null)
{
Context.Populate(ContainingNamespace);
}
Context.Populate(this);
}
public override bool Equals(object? obj)
{
return obj is NoMetadataHandleType t && originalName.Equals(t.originalName, StringComparison.Ordinal);
}
public override int GetHashCode()
{
return originalName.GetHashCode(StringComparison.Ordinal);
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var tp in typeParams?.Value ?? Array.Empty<TypeTypeParameter>())
yield return tp;
foreach (var c in base.Contents)
yield return c;
var i = 0;
foreach (var type in ThisTypeArguments)
{
yield return type;
yield return Tuples.cil_type_argument(this, i++, type);
}
}
}
public override CilTypeKind Kind => CilTypeKind.ValueOrRefType;
public override string Name => GenericsHelper.GetNonGenericName(name);
public override Namespace? ContainingNamespace => containingNamespace;
public override Type? ContainingType => containingType;
public override Type SourceDeclaration => unboundGenericType;
public override Type Construct(IEnumerable<Type> typeArguments)
{
if (TotalTypeParametersCount != typeArguments.Count())
throw new InternalError("Mismatched type arguments");
return Context.Populate(new ConstructedType(Context, this, typeArguments));
}
public override void WriteAssemblyPrefix(TextWriter trapFile)
{
if (!string.IsNullOrWhiteSpace(assemblyName))
{
var an = new AssemblyName(assemblyName);
trapFile.Write(an.Name);
trapFile.Write('_');
trapFile.Write((an.Version ?? new Version(0, 0, 0, 0)).ToString());
trapFile.Write(Type.AssemblyTypeNameSeparator);
}
else
{
Context.WriteAssemblyPrefix(trapFile);
}
}
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
idWriter.WriteId(trapFile, inContext);
}
public override int ThisTypeParameterCount => unboundGenericType == this
? GenericsHelper.GetGenericTypeParameterCount(name)
: thisTypeArguments!.Length;
public override IEnumerable<Type> TypeParameters => unboundGenericType == this
? GenericsHelper.GetAllTypeParameters(containingType, typeParams!.Value)
: GenericArguments;
public override IEnumerable<Type> ThisTypeArguments => unboundGenericType == this
? base.ThisTypeArguments
: thisTypeArguments!;
public override IEnumerable<Type> ThisGenericArguments => unboundGenericType == this
? typeParams!.Value
: thisTypeArguments!;
}
}

Просмотреть файл

@ -1,47 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A parameter entity.
/// </summary>
internal sealed class Parameter : LabelledEntity
{
private readonly IParameterizable parameterizable;
private readonly int index;
private readonly Type type;
public Parameter(Context cx, IParameterizable p, int i, Type t) : base(cx)
{
parameterizable = p;
index = i;
type = t;
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(parameterizable);
trapFile.Write('_');
trapFile.Write(index);
trapFile.Write(";cil-parameter");
}
public override bool Equals(object? obj)
{
return obj is Parameter param && parameterizable.Equals(param.parameterizable) && index == param.index;
}
public override int GetHashCode()
{
return 23 * parameterizable.GetHashCode() + index;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.cil_parameter(this, parameterizable, index, type);
}
}
}
}

Просмотреть файл

@ -1,32 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
internal class PdbSourceFile : File
{
private readonly PDB.ISourceFile file;
public PdbSourceFile(Context cx, PDB.ISourceFile file) : base(cx, file.Path)
{
this.file = file;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var c in base.Contents)
yield return c;
var text = file.Contents;
if (text is null)
Context.Extractor.Logger.Log(Util.Logging.Severity.Warning, string.Format("PDB source file {0} could not be found", OriginalPath));
else
Context.TrapWriter.Archive(TransformedPath, text);
yield return Tuples.file_extraction_mode(this, Context.Extractor.Mode | ExtractorMode.Pdb);
}
}
}
}

Просмотреть файл

@ -1,64 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class PointerType : Type
{
private readonly Type pointee;
public PointerType(Context cx, Type pointee) : base(cx)
{
this.pointee = pointee;
if (pointee is ModifiedType mt)
{
cx.Extractor.Logger.Log(
Util.Logging.Severity.Info,
$"Pointer to modified type {pointee.GetQualifiedName()} is changed to {mt.Unmodified.GetQualifiedName()}");
this.pointee = mt.Unmodified;
}
}
public override bool Equals(object? obj)
{
return obj is PointerType pt && pointee.Equals(pt.pointee);
}
public override int GetHashCode() => HashCode.Combine(pointee, nameof(PointerType));
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
pointee.WriteId(trapFile, inContext);
trapFile.Write('*');
}
public override string Name => pointee.Name + "*";
public override Namespace? ContainingNamespace => pointee.ContainingNamespace;
public override Type? ContainingType => pointee.ContainingType;
public override TypeContainer Parent => pointee.Parent;
public override int ThisTypeParameterCount => 0;
public override CilTypeKind Kind => CilTypeKind.Pointer;
public override void WriteAssemblyPrefix(TextWriter trapFile) => pointee.WriteAssemblyPrefix(trapFile);
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var c in base.Contents) yield return c;
yield return Tuples.cil_pointer_type(this, pointee);
}
}
}
}

Просмотреть файл

@ -1,44 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class PrimitiveType : Type
{
private readonly PrimitiveTypeCode typeCode;
public PrimitiveType(Context cx, PrimitiveTypeCode tc) : base(cx)
{
typeCode = tc;
}
public override bool Equals(object? obj)
{
return obj is PrimitiveType pt && typeCode == pt.typeCode;
}
public override int GetHashCode() => typeCode.GetHashCode();
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
Type.WritePrimitiveTypeId(trapFile, Name);
}
public override string Name => typeCode.Id();
public override Namespace ContainingNamespace => Context.SystemNamespace;
public override Type? ContainingType => null;
public override int ThisTypeParameterCount => 0;
public override CilTypeKind Kind => CilTypeKind.ValueOrRefType;
public override void WriteAssemblyPrefix(TextWriter trapFile) { }
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
}
}

Просмотреть файл

@ -1,91 +0,0 @@
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A property.
/// </summary>
internal sealed class Property : LabelledEntity, ICustomModifierReceiver
{
private readonly Handle handle;
private readonly Type type;
private readonly PropertyDefinition pd;
private readonly IGenericContext gc;
public Property(IGenericContext gc, Type type, PropertyDefinitionHandle handle) : base(gc.Context)
{
this.gc = gc;
this.handle = handle;
pd = Context.MdReader.GetPropertyDefinition(handle);
this.type = type;
}
public override void WriteId(EscapingTextWriter trapFile)
{
trapFile.WriteSubId(type);
trapFile.Write('.');
trapFile.Write(Context.GetString(pd.Name));
trapFile.Write("(");
var index = 0;
var signature = pd.DecodeSignature(new SignatureDecoder(), gc);
foreach (var param in signature.ParameterTypes)
{
trapFile.WriteSeparator(",", ref index);
param.WriteId(trapFile, gc);
}
trapFile.Write(")");
trapFile.Write(";cil-property");
}
public override bool Equals(object? obj)
{
return obj is Property property && Equals(handle, property.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.metadata_handle(this, Context.Assembly, MetadataTokens.GetToken(handle));
var sig = pd.DecodeSignature(Context.TypeSignatureDecoder, type);
var name = Context.ShortName(pd.Name);
var t = sig.ReturnType;
if (t is ModifiedType mt)
{
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
if (t is ByRefType brt)
{
t = brt.ElementType;
yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref);
}
yield return Tuples.cil_property(this, type, name, t);
var accessors = pd.GetAccessors();
if (!accessors.Getter.IsNil)
{
var getter = (Method)Context.CreateGeneric(type, accessors.Getter);
yield return getter;
yield return Tuples.cil_getter(this, getter);
}
if (!accessors.Setter.IsNil)
{
var setter = (Method)Context.CreateGeneric(type, accessors.Setter);
yield return setter;
yield return Tuples.cil_setter(this, setter);
}
foreach (var c in Attribute.Populate(Context, this, pd.GetCustomAttributes()))
yield return c;
}
}
}
}

Просмотреть файл

@ -1,289 +0,0 @@
using System.Collections.Immutable;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
public class SignatureDecoder : ISignatureTypeProvider<ITypeSignature, object>
{
private struct Array : ITypeSignature
{
private readonly ITypeSignature elementType;
private readonly ArrayShape shape;
public Array(ITypeSignature elementType, ArrayShape shape) : this()
{
this.elementType = elementType;
this.shape = shape;
}
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
elementType.WriteId(trapFile, gc);
trapFile.Write('[');
for (var i = 1; i < shape.Rank; ++i)
{
trapFile.Write(',');
}
trapFile.Write(']');
}
}
private struct ByRef : ITypeSignature
{
private readonly ITypeSignature elementType;
public ByRef(ITypeSignature elementType)
{
this.elementType = elementType;
}
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
elementType.WriteId(trapFile, gc);
trapFile.Write('&');
}
}
private struct FnPtr : ITypeSignature
{
private readonly MethodSignature<ITypeSignature> signature;
public FnPtr(MethodSignature<ITypeSignature> signature)
{
this.signature = signature;
}
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
FunctionPointerType.WriteName(
trapFile.Write,
t => t.WriteId(trapFile, gc),
signature
);
}
}
ITypeSignature IConstructedTypeProvider<ITypeSignature>.GetArrayType(ITypeSignature elementType, ArrayShape shape) =>
new Array(elementType, shape);
ITypeSignature IConstructedTypeProvider<ITypeSignature>.GetByReferenceType(ITypeSignature elementType) =>
new ByRef(elementType);
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetFunctionPointerType(MethodSignature<ITypeSignature> signature) =>
new FnPtr(signature);
private class Instantiation : ITypeSignature
{
private readonly ITypeSignature genericType;
private readonly ImmutableArray<ITypeSignature> typeArguments;
public Instantiation(ITypeSignature genericType, ImmutableArray<ITypeSignature> typeArguments)
{
this.genericType = genericType;
this.typeArguments = typeArguments;
}
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
genericType.WriteId(trapFile, gc);
trapFile.Write('<');
var index = 0;
foreach (var arg in typeArguments)
{
trapFile.WriteSeparator(",", ref index);
arg.WriteId(trapFile, gc);
}
trapFile.Write('>');
}
}
ITypeSignature IConstructedTypeProvider<ITypeSignature>.GetGenericInstantiation(ITypeSignature genericType, ImmutableArray<ITypeSignature> typeArguments) =>
new Instantiation(genericType, typeArguments);
private class GenericMethodParameter : ITypeSignature
{
private readonly object innerGc;
private readonly int index;
public GenericMethodParameter(object innerGc, int index)
{
this.innerGc = innerGc;
this.index = index;
}
public void WriteId(EscapingTextWriter trapFile, IGenericContext outerGc)
{
if (!ReferenceEquals(innerGc, outerGc) && innerGc is Method method)
{
trapFile.WriteSubId(method);
}
trapFile.Write("M!");
trapFile.Write(index);
}
}
private class GenericTypeParameter : ITypeSignature
{
private readonly int index;
public GenericTypeParameter(int index)
{
this.index = index;
}
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
trapFile.Write("T!");
trapFile.Write(index);
}
}
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetGenericMethodParameter(object genericContext, int index) =>
new GenericMethodParameter(genericContext, index);
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetGenericTypeParameter(object genericContext, int index) =>
new GenericTypeParameter(index);
private class Modified : ITypeSignature
{
private readonly ITypeSignature unmodifiedType;
private readonly ITypeSignature modifier;
private readonly bool isRequired;
public Modified(ITypeSignature unmodifiedType, ITypeSignature modifier, bool isRequired)
{
this.unmodifiedType = unmodifiedType;
this.modifier = modifier;
this.isRequired = isRequired;
}
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
unmodifiedType.WriteId(trapFile, gc);
trapFile.Write(isRequired ? " modreq(" : " modopt(");
modifier.WriteId(trapFile, gc);
trapFile.Write(")");
}
}
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetModifiedType(ITypeSignature modifier, ITypeSignature unmodifiedType, bool isRequired)
{
return new Modified(unmodifiedType, modifier, isRequired);
}
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetPinnedType(ITypeSignature elementType)
{
return elementType;
}
private class PointerType : ITypeSignature
{
private readonly ITypeSignature elementType;
public PointerType(ITypeSignature elementType)
{
this.elementType = elementType;
}
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
elementType.WriteId(trapFile, gc);
trapFile.Write('*');
}
}
ITypeSignature IConstructedTypeProvider<ITypeSignature>.GetPointerType(ITypeSignature elementType)
{
return new PointerType(elementType);
}
private class Primitive : ITypeSignature
{
private readonly PrimitiveTypeCode typeCode;
public Primitive(PrimitiveTypeCode typeCode)
{
this.typeCode = typeCode;
}
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
trapFile.Write(typeCode.Id());
}
}
ITypeSignature ISimpleTypeProvider<ITypeSignature>.GetPrimitiveType(PrimitiveTypeCode typeCode)
{
return new Primitive(typeCode);
}
private class SzArrayType : ITypeSignature
{
private readonly ITypeSignature elementType;
public SzArrayType(ITypeSignature elementType)
{
this.elementType = elementType;
}
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
elementType.WriteId(trapFile, gc);
trapFile.Write("[]");
}
}
ITypeSignature ISZArrayTypeProvider<ITypeSignature>.GetSZArrayType(ITypeSignature elementType)
{
return new SzArrayType(elementType);
}
private class TypeDefinition : ITypeSignature
{
private readonly TypeDefinitionHandle handle;
public TypeDefinition(TypeDefinitionHandle handle)
{
this.handle = handle;
}
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
var type = (Type)gc.Context.Create(handle);
type.WriteId(trapFile);
}
}
ITypeSignature ISimpleTypeProvider<ITypeSignature>.GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
return new TypeDefinition(handle);
}
private class TypeReference : ITypeSignature
{
private readonly TypeReferenceHandle handle;
public TypeReference(TypeReferenceHandle handle)
{
this.handle = handle;
}
public void WriteId(EscapingTextWriter trapFile, IGenericContext gc)
{
var type = (Type)gc.Context.Create(handle);
type.WriteId(trapFile);
}
}
ITypeSignature ISimpleTypeProvider<ITypeSignature>.GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{
return new TypeReference(handle);
}
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetTypeFromSpecification(MetadataReader reader, object genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{
var ts = reader.GetTypeSpecification(handle);
return ts.DecodeSignature(this, genericContext);
}
}
}

Просмотреть файл

@ -1,47 +0,0 @@
using System.Collections.Generic;
using Semmle.Extraction.PDB;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class PdbSourceLocation : LabelledEntity, ILocation
{
private readonly Location location;
private readonly PdbSourceFile file;
public PdbSourceLocation(Context cx, PDB.Location location) : base(cx)
{
this.location = location;
file = cx.CreateSourceFile(location.File);
}
public override void WriteId(EscapingTextWriter trapFile)
{
file.WriteId(trapFile);
trapFile.Write(',');
trapFile.Write(location.StartLine);
trapFile.Write(',');
trapFile.Write(location.StartColumn);
trapFile.Write(',');
trapFile.Write(location.EndLine);
trapFile.Write(',');
trapFile.Write(location.EndColumn);
trapFile.Write(";sourcelocation");
}
public override bool Equals(object? obj)
{
return obj is PdbSourceLocation l && location.Equals(l.location);
}
public override int GetHashCode() => location.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return file;
yield return Tuples.locations_default(this, file, location.StartLine, location.StartColumn, location.EndLine, location.EndColumn);
}
}
}
}

Просмотреть файл

@ -1,209 +0,0 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A type.
/// </summary>
internal abstract class Type : TypeContainer, IMember
{
internal const string AssemblyTypeNameSeparator = "::";
internal const string PrimitiveTypePrefix = "builtin" + AssemblyTypeNameSeparator + "System.";
protected Type(Context cx) : base(cx) { }
/// <summary>
/// Find the method in this type matching the name and signature.
/// </summary>
/// <param name="methodName">The handle to the name.</param>
/// <param name="signature">
/// The handle to the signature. Note that comparing handles is a valid
/// shortcut to comparing the signature bytes since handles are unique.
/// </param>
/// <returns>The method, or 'null' if not found or not supported.</returns>
internal virtual Method? LookupMethod(StringHandle methodName, BlobHandle signature)
{
return null;
}
/// <summary>
/// Writes the assembly identifier of this type.
/// </summary>
public abstract void WriteAssemblyPrefix(TextWriter trapFile);
/// <summary>
/// Writes the ID part to be used in a method ID.
/// </summary>
/// <param name="inContext">
/// Whether we should output the context prefix of type parameters.
/// (This is to avoid infinite recursion generating a method ID that returns a
/// type parameter.)
/// </param>
public abstract void WriteId(EscapingTextWriter trapFile, bool inContext);
public sealed override void WriteId(EscapingTextWriter trapFile)
{
WriteId(trapFile, false);
trapFile.Write(";cil-type");
}
/// <summary>
/// Returns the friendly qualified name of types, such as
/// ``"System.Collection.Generic.List`1"`` or
/// ``"System.Collection.Generic.List<System.Int32>"``.
///
/// Note that method/type generic type parameters never show up in the returned name.
/// </summary>
public string GetQualifiedName()
{
using var writer = new EscapingTextWriter();
WriteId(writer, false);
var name = writer.ToString();
return name.Substring(name.IndexOf(AssemblyTypeNameSeparator) + 2).
Replace(";namespace", "").
Replace(";cil-type", "");
}
public abstract CilTypeKind Kind { get; }
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.cil_type(this, Name, Kind, Parent, SourceDeclaration);
}
}
public abstract string Name { get; }
public abstract Namespace? ContainingNamespace { get; }
public abstract Type? ContainingType { get; }
public virtual TypeContainer Parent => (TypeContainer?)ContainingType ?? ContainingNamespace!;
public abstract Type Construct(IEnumerable<Type> typeArguments);
/// <summary>
/// Returns the type arguments of constructed types. For non-constructed types it returns an
/// empty collection.
/// </summary>
public virtual IEnumerable<Type> ThisTypeArguments
{
get
{
yield break;
}
}
/// <summary>
/// The number of type parameters for non-constructed generic types, the number of type arguments
/// for constructed types, or 0.
/// </summary>
public abstract int ThisTypeParameterCount { get; }
/// <summary>
/// The total number of type parameters/type arguments (including parent types).
/// This is used for internal consistency checking only.
/// </summary>
public int TotalTypeParametersCount =>
ThisTypeParameterCount + (ContainingType?.TotalTypeParametersCount ?? 0);
/// <summary>
/// Returns all bound/unbound generic arguments of a constructed/unbound generic type.
/// </summary>
public virtual IEnumerable<Type> ThisGenericArguments
{
get
{
yield break;
}
}
public virtual IEnumerable<Type> GenericArguments
{
get
{
if (ContainingType is not null)
{
foreach (var t in ContainingType.GenericArguments)
yield return t;
}
foreach (var t in ThisGenericArguments)
yield return t;
}
}
public virtual Type SourceDeclaration => this;
public static void WritePrimitiveTypeId(TextWriter trapFile, string name)
{
trapFile.Write(PrimitiveTypePrefix);
trapFile.Write(name);
}
private static readonly Dictionary<string, PrimitiveTypeCode> primitiveTypeCodeMapping = new Dictionary<string, PrimitiveTypeCode>
{
{"Boolean", PrimitiveTypeCode.Boolean},
{"Object", PrimitiveTypeCode.Object},
{"Byte", PrimitiveTypeCode.Byte},
{"SByte", PrimitiveTypeCode.SByte},
{"Int16", PrimitiveTypeCode.Int16},
{"UInt16", PrimitiveTypeCode.UInt16},
{"Int32", PrimitiveTypeCode.Int32},
{"UInt32", PrimitiveTypeCode.UInt32},
{"Int64", PrimitiveTypeCode.Int64},
{"UInt64", PrimitiveTypeCode.UInt64},
{"Single", PrimitiveTypeCode.Single},
{"Double", PrimitiveTypeCode.Double},
{"String", PrimitiveTypeCode.String},
{"Void", PrimitiveTypeCode.Void},
{"IntPtr", PrimitiveTypeCode.IntPtr},
{"UIntPtr", PrimitiveTypeCode.UIntPtr},
{"Char", PrimitiveTypeCode.Char},
{"TypedReference", PrimitiveTypeCode.TypedReference}
};
/// <summary>
/// Gets the primitive type corresponding to this type, if possible.
/// </summary>
/// <param name="t">The resulting primitive type, or null.</param>
/// <returns>True if this type is a primitive type.</returns>
public bool TryGetPrimitiveType([NotNullWhen(true)] out PrimitiveType? t)
{
if (TryGetPrimitiveTypeCode(out var code))
{
t = Context.Create(code);
return true;
}
t = null;
return false;
}
private bool TryGetPrimitiveTypeCode(out PrimitiveTypeCode code)
{
if (ContainingType is null &&
ContainingNamespace?.Name == Context.SystemNamespace.Name &&
primitiveTypeCodeMapping.TryGetValue(Name, out code))
{
return true;
}
code = default;
return false;
}
protected internal bool IsPrimitiveType => TryGetPrimitiveTypeCode(out _);
public sealed override IEnumerable<Type> MethodParameters => Enumerable.Empty<Type>();
public static Type DecodeType(IGenericContext gc, TypeSpecificationHandle handle) =>
gc.Context.MdReader.GetTypeSpecification(handle).DecodeSignature(gc.Context.TypeSignatureDecoder, gc);
}
}

Просмотреть файл

@ -1,11 +0,0 @@
using System;
namespace Semmle.Extraction.CIL.Entities
{
[Flags]
public enum TypeAnnotation
{
None = 0,
Ref = 32
}
}

Просмотреть файл

@ -1,17 +0,0 @@
using System.Collections.Generic;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Base class for all type containers (namespaces, types, methods).
/// </summary>
internal abstract class TypeContainer : LabelledEntity, IGenericContext
{
protected TypeContainer(Context cx) : base(cx)
{
}
public abstract IEnumerable<Type> MethodParameters { get; }
public abstract IEnumerable<Type> TypeParameters { get; }
}
}

Просмотреть файл

@ -1,263 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A type defined in the current assembly.
/// </summary>
internal sealed class TypeDefinitionType : Type
{
private readonly TypeDefinitionHandle handle;
private readonly TypeDefinition td;
private readonly Lazy<IEnumerable<TypeTypeParameter>> typeParams;
private readonly Type? declType;
private readonly NamedTypeIdWriter idWriter;
public TypeDefinitionType(Context cx, TypeDefinitionHandle handle) : base(cx)
{
idWriter = new NamedTypeIdWriter(this);
td = cx.MdReader.GetTypeDefinition(handle);
this.handle = handle;
declType =
td.GetDeclaringType().IsNil ? null :
(Type)cx.Create(td.GetDeclaringType());
// Lazy because should happen during population.
typeParams = new Lazy<IEnumerable<TypeTypeParameter>>(MakeTypeParameters);
}
public override bool Equals(object? obj)
{
return obj is TypeDefinitionType t && handle.Equals(t.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
idWriter.WriteId(trapFile, inContext);
}
public override string Name => GenericsHelper.GetNonGenericName(td.Name, Context.MdReader);
public override Namespace ContainingNamespace => Context.Create(td.NamespaceDefinition);
public override Type? ContainingType => declType;
public override CilTypeKind Kind => CilTypeKind.ValueOrRefType;
public override Type Construct(IEnumerable<Type> typeArguments)
{
if (TotalTypeParametersCount != typeArguments.Count())
throw new InternalError("Mismatched type arguments");
return Context.Populate(new ConstructedType(Context, this, typeArguments));
}
public override void WriteAssemblyPrefix(TextWriter trapFile)
{
var ct = ContainingType;
if (ct is null)
Context.WriteAssemblyPrefix(trapFile);
else if (IsPrimitiveType)
trapFile.Write(Type.PrimitiveTypePrefix);
else
ct.WriteAssemblyPrefix(trapFile);
}
private IEnumerable<TypeTypeParameter> MakeTypeParameters()
{
if (ThisTypeParameterCount == 0)
return Enumerable.Empty<TypeTypeParameter>();
var newTypeParams = new TypeTypeParameter[ThisTypeParameterCount];
var genericParams = td.GetGenericParameters();
var toSkip = genericParams.Count - newTypeParams.Length;
// Two-phase population because type parameters can be mutually dependent
for (var i = 0; i < newTypeParams.Length; ++i)
newTypeParams[i] = Context.Populate(new TypeTypeParameter(this, i));
for (var i = 0; i < newTypeParams.Length; ++i)
newTypeParams[i].PopulateHandle(genericParams[i + toSkip]);
return newTypeParams;
}
public override int ThisTypeParameterCount
{
get
{
var containingType = td.GetDeclaringType();
var parentTypeParameters = containingType.IsNil
? 0
: Context.MdReader.GetTypeDefinition(containingType).GetGenericParameters().Count;
return td.GetGenericParameters().Count - parentTypeParameters;
}
}
public override IEnumerable<Type> TypeParameters => GenericsHelper.GetAllTypeParameters(declType, typeParams!.Value);
public override IEnumerable<Type> ThisGenericArguments => typeParams.Value;
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.metadata_handle(this, Context.Assembly, MetadataTokens.GetToken(handle));
foreach (var c in base.Contents) yield return c;
MakeTypeParameters();
foreach (var f in td.GetFields())
{
// Populate field if needed
yield return Context.CreateGeneric(this, f);
}
foreach (var prop in td.GetProperties())
{
yield return new Property(this, this, prop);
}
foreach (var @event in td.GetEvents())
{
yield return new Event(Context, this, @event);
}
foreach (var a in Attribute.Populate(Context, this, td.GetCustomAttributes()))
yield return a;
foreach (var impl in td.GetMethodImplementations().Select(i => Context.MdReader.GetMethodImplementation(i)))
{
var m = (Method)Context.CreateGeneric(this, impl.MethodBody);
var decl = (Method)Context.CreateGeneric(this, impl.MethodDeclaration);
yield return m;
yield return decl;
yield return Tuples.cil_implements(m, decl);
}
if (td.Attributes.HasFlag(TypeAttributes.Abstract))
yield return Tuples.cil_abstract(this);
if (td.Attributes.HasFlag(TypeAttributes.Interface))
yield return Tuples.cil_interface(this);
else
yield return Tuples.cil_class(this);
if (td.Attributes.HasFlag(TypeAttributes.Public))
yield return Tuples.cil_public(this);
if (td.Attributes.HasFlag(TypeAttributes.Sealed))
yield return Tuples.cil_sealed(this);
if (td.Attributes.HasFlag(TypeAttributes.HasSecurity))
yield return Tuples.cil_security(this);
// Base types
if (!td.BaseType.IsNil)
{
var @base = (Type)Context.CreateGeneric(this, td.BaseType);
yield return @base;
yield return Tuples.cil_base_class(this, @base);
if (IsSystemEnum(td.BaseType) &&
GetUnderlyingEnumType() is var underlying &&
underlying.HasValue)
{
var underlyingType = Context.Create(underlying.Value);
yield return underlyingType;
yield return Tuples.cil_enum_underlying_type(this, underlyingType);
}
}
foreach (var @interface in td.GetInterfaceImplementations().Select(i => Context.MdReader.GetInterfaceImplementation(i)))
{
var t = (Type)Context.CreateGeneric(this, @interface.Interface);
yield return t;
yield return Tuples.cil_base_interface(this, t);
}
// Only type definitions have locations.
yield return Tuples.cil_type_location(this, Context.Assembly);
}
}
private bool IsSystemEnum(EntityHandle baseType)
{
return baseType.Kind switch
{
HandleKind.TypeReference => IsSystemEnum((TypeReferenceHandle)baseType),
HandleKind.TypeDefinition => IsSystemEnum((TypeDefinitionHandle)baseType),
_ => false,
};
}
private bool IsSystemEnum(TypeReferenceHandle baseType)
{
var baseTypeReference = Context.MdReader.GetTypeReference(baseType);
return IsSystemEnum(baseTypeReference.Name, baseTypeReference.Namespace);
}
private bool IsSystemEnum(TypeDefinitionHandle baseType)
{
var baseTypeDefinition = Context.MdReader.GetTypeDefinition(baseType);
return IsSystemEnum(baseTypeDefinition.Name, baseTypeDefinition.Namespace);
}
private bool IsSystemEnum(StringHandle typeName, StringHandle namespaceName)
{
return Context.MdReader.StringComparer.Equals(typeName, "Enum") &&
!namespaceName.IsNil &&
Context.MdReader.StringComparer.Equals(namespaceName, "System");
}
internal PrimitiveTypeCode? GetUnderlyingEnumType()
{
foreach (var handle in td.GetFields())
{
var field = Context.MdReader.GetFieldDefinition(handle);
if (field.Attributes.HasFlag(FieldAttributes.Static))
{
continue;
}
var blob = Context.MdReader.GetBlobReader(field.Signature);
if (blob.ReadSignatureHeader().Kind != SignatureKind.Field)
{
break;
}
return (PrimitiveTypeCode)blob.ReadByte();
}
return null;
}
internal override Method LookupMethod(StringHandle name, BlobHandle signature)
{
foreach (var h in td.GetMethods())
{
var md = Context.MdReader.GetMethodDefinition(h);
if (md.Name == name && md.Signature == signature)
{
return (Method)Context.Create(h);
}
}
throw new InternalError("Couldn't locate method in type");
}
}
}

Просмотреть файл

@ -1,57 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
internal abstract class TypeParameter : Type
{
protected readonly IGenericContext gc;
protected TypeParameter(IGenericContext gc) : base(gc.Context)
{
this.gc = gc;
}
public override Namespace? ContainingNamespace => null;
public override Type? ContainingType => null;
public override int ThisTypeParameterCount => 0;
public override CilTypeKind Kind => CilTypeKind.TypeParameter;
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new InternalError("Attempt to construct a type parameter");
public IEnumerable<IExtractionProduct> PopulateHandle(GenericParameterHandle parameterHandle)
{
if (!parameterHandle.IsNil)
{
var tp = Context.MdReader.GetGenericParameter(parameterHandle);
if (tp.Attributes.HasFlag(GenericParameterAttributes.Contravariant))
yield return Tuples.cil_typeparam_contravariant(this);
if (tp.Attributes.HasFlag(GenericParameterAttributes.Covariant))
yield return Tuples.cil_typeparam_covariant(this);
if (tp.Attributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint))
yield return Tuples.cil_typeparam_new(this);
if (tp.Attributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint))
yield return Tuples.cil_typeparam_class(this);
if (tp.Attributes.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint))
yield return Tuples.cil_typeparam_struct(this);
foreach (var constraint in tp.GetConstraints().Select(h => Context.MdReader.GetGenericParameterConstraint(h)))
{
var t = (Type)Context.CreateGeneric(this.gc, constraint.Type);
yield return t;
yield return Tuples.cil_typeparam_constraint(this, t);
}
}
}
}
}

Просмотреть файл

@ -1,104 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A type reference, to a type in a referenced assembly.
/// </summary>
internal sealed class TypeReferenceType : Type
{
private readonly TypeReferenceHandle handle;
private readonly TypeReference tr;
private readonly Lazy<TypeTypeParameter[]> typeParams;
private readonly NamedTypeIdWriter idWriter;
public TypeReferenceType(Context cx, TypeReferenceHandle handle) : base(cx)
{
this.idWriter = new NamedTypeIdWriter(this);
this.handle = handle;
this.tr = cx.MdReader.GetTypeReference(handle);
this.typeParams = new Lazy<TypeTypeParameter[]>(GenericsHelper.MakeTypeParameters(this, ThisTypeParameterCount));
}
public override bool Equals(object? obj)
{
return obj is TypeReferenceType t && handle.Equals(t.handle);
}
public override int GetHashCode()
{
return handle.GetHashCode();
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var tp in typeParams.Value)
yield return tp;
foreach (var c in base.Contents)
yield return c;
}
}
public override string Name => GenericsHelper.GetNonGenericName(tr.Name, Context.MdReader);
public override Namespace ContainingNamespace => Context.CreateNamespace(tr.Namespace);
public override Type? ContainingType
{
get
{
return tr.ResolutionScope.Kind == HandleKind.TypeReference
? (Type)Context.Create((TypeReferenceHandle)tr.ResolutionScope)
: null;
}
}
public override CilTypeKind Kind => CilTypeKind.ValueOrRefType;
public override void WriteAssemblyPrefix(TextWriter trapFile)
{
switch (tr.ResolutionScope.Kind)
{
case HandleKind.TypeReference:
ContainingType!.WriteAssemblyPrefix(trapFile);
break;
case HandleKind.AssemblyReference:
var assemblyDef = Context.MdReader.GetAssemblyReference((AssemblyReferenceHandle)tr.ResolutionScope);
trapFile.Write(Context.GetString(assemblyDef.Name));
trapFile.Write('_');
trapFile.Write(assemblyDef.Version.ToString());
trapFile.Write(Entities.Type.AssemblyTypeNameSeparator);
break;
default:
Context.WriteAssemblyPrefix(trapFile);
break;
}
}
public override int ThisTypeParameterCount => GenericsHelper.GetGenericTypeParameterCount(tr.Name, Context.MdReader);
public override IEnumerable<Type> TypeParameters => GenericsHelper.GetAllTypeParameters(ContainingType, typeParams!.Value);
public override IEnumerable<Type> ThisGenericArguments => typeParams.Value;
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
idWriter.WriteId(trapFile, inContext);
}
public override Type Construct(IEnumerable<Type> typeArguments)
{
if (TotalTypeParametersCount != typeArguments.Count())
throw new InternalError("Mismatched type arguments");
return Context.Populate(new ConstructedType(Context, this, typeArguments));
}
}
}

Просмотреть файл

@ -1,60 +0,0 @@
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Decodes a type signature and produces a Type, for use by DecodeSignature() and friends.
/// </summary>
internal class TypeSignatureDecoder : ISignatureTypeProvider<Type, IGenericContext>
{
private readonly Context cx;
public TypeSignatureDecoder(Context cx)
{
this.cx = cx;
}
Type IConstructedTypeProvider<Type>.GetArrayType(Type elementType, ArrayShape shape) =>
cx.Populate(new ArrayType(cx, elementType, shape.Rank));
Type IConstructedTypeProvider<Type>.GetByReferenceType(Type elementType) =>
new ByRefType(cx, elementType);
Type ISignatureTypeProvider<Type, IGenericContext>.GetFunctionPointerType(MethodSignature<Type> signature) =>
cx.Populate(new FunctionPointerType(cx, signature));
Type IConstructedTypeProvider<Type>.GetGenericInstantiation(Type genericType, ImmutableArray<Type> typeArguments) =>
genericType.Construct(typeArguments);
Type ISignatureTypeProvider<Type, IGenericContext>.GetGenericMethodParameter(IGenericContext genericContext, int index) =>
genericContext.MethodParameters.ElementAt(index);
Type ISignatureTypeProvider<Type, IGenericContext>.GetGenericTypeParameter(IGenericContext genericContext, int index) =>
genericContext.TypeParameters.ElementAt(index);
Type ISignatureTypeProvider<Type, IGenericContext>.GetModifiedType(Type modifier, Type unmodifiedType, bool isRequired) =>
new ModifiedType(cx, unmodifiedType, modifier, isRequired);
Type ISignatureTypeProvider<Type, IGenericContext>.GetPinnedType(Type elementType) => elementType;
Type IConstructedTypeProvider<Type>.GetPointerType(Type elementType) =>
cx.Populate(new PointerType(cx, elementType));
Type ISimpleTypeProvider<Type>.GetPrimitiveType(PrimitiveTypeCode typeCode) => cx.Create(typeCode);
Type ISZArrayTypeProvider<Type>.GetSZArrayType(Type elementType) =>
cx.Populate(new ArrayType(cx, elementType));
Type ISimpleTypeProvider<Type>.GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) =>
(Type)cx.Create(handle);
Type ISimpleTypeProvider<Type>.GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) =>
(Type)cx.Create(handle);
Type ISignatureTypeProvider<Type, IGenericContext>.GetTypeFromSpecification(MetadataReader reader, IGenericContext genericContext, TypeSpecificationHandle handle, byte rawTypeKind) =>
throw new NotImplementedException();
}
}

Просмотреть файл

@ -1,48 +0,0 @@
using System.Collections.Generic;
using System.Linq;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class TypeTypeParameter : TypeParameter
{
private readonly Type type;
private readonly int index;
public TypeTypeParameter(Type t, int i) : base(t)
{
index = i;
type = t;
}
public override bool Equals(object? obj)
{
return obj is TypeTypeParameter tp && type.Equals(tp.type) && index == tp.index;
}
public override int GetHashCode()
{
return type.GetHashCode() * 13 + index;
}
public override void WriteId(EscapingTextWriter trapFile, bool inContext)
{
type.WriteId(trapFile, inContext);
trapFile.Write('!');
trapFile.Write(index);
}
public override TypeContainer Parent => type;
public override string Name => "!" + index;
public override IEnumerable<Type> TypeParameters => Enumerable.Empty<Type>();
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.cil_type(this, Name, Kind, type, SourceDeclaration);
yield return Tuples.cil_type_parameter(type, index, this);
}
}
}
}

Просмотреть файл

@ -1,6 +0,0 @@
namespace Semmle.Extraction.CIL
{
internal interface ICustomModifierReceiver
{
}
}

Просмотреть файл

@ -1,33 +0,0 @@
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL
{
public static class IdUtils
{
public static string Id(this PrimitiveTypeCode typeCode)
{
switch (typeCode)
{
case PrimitiveTypeCode.Boolean: return "Boolean";
case PrimitiveTypeCode.Byte: return "Byte";
case PrimitiveTypeCode.Char: return "Char";
case PrimitiveTypeCode.Double: return "Double";
case PrimitiveTypeCode.Int16: return "Int16";
case PrimitiveTypeCode.Int32: return "Int32";
case PrimitiveTypeCode.Int64: return "Int64";
case PrimitiveTypeCode.IntPtr: return "IntPtr";
case PrimitiveTypeCode.Object: return "Object";
case PrimitiveTypeCode.SByte: return "SByte";
case PrimitiveTypeCode.Single: return "Single";
case PrimitiveTypeCode.String: return "String";
case PrimitiveTypeCode.UInt16: return "UInt16";
case PrimitiveTypeCode.UInt32: return "UInt32";
case PrimitiveTypeCode.UInt64: return "UInt64";
case PrimitiveTypeCode.UIntPtr: return "UIntPtr";
case PrimitiveTypeCode.Void: return "Void";
case PrimitiveTypeCode.TypedReference: return "TypedReference";
default: throw new InternalError($"Unhandled type code {typeCode}");
}
}
}
}

Просмотреть файл

@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
namespace Semmle.Extraction.PDB
{
/// <summary>
/// Wrapper for reading PDB files.
/// This is needed because there are different libraries for dealing with
/// different types of PDB file, even though they share the same file extension.
/// </summary>
public interface IPdb : IDisposable
{
/// <summary>
/// Gets all source files in this PDB.
/// </summary>
IEnumerable<ISourceFile> SourceFiles { get; }
/// <summary>
/// Look up a method from a given handle.
/// </summary>
/// <param name="methodHandle">The handle to query.</param>
/// <returns>The method information, or null if the method does not have debug information.</returns>
Method? GetMethod(MethodDebugInformationHandle methodHandle);
}
}

Просмотреть файл

@ -1,20 +0,0 @@
namespace Semmle.Extraction.PDB
{
/// <summary>
/// A source file reference in a PDB file.
/// </summary>
public interface ISourceFile
{
string Path { get; }
/// <summary>
/// The contents of the file.
/// This property is needed in case the contents
/// of the file are embedded in the PDB instead of being on the filesystem.
///
/// null if the contents are unavailable.
/// E.g. if the PDB file exists but the corresponding source files are missing.
/// </summary>
string? Contents { get; }
}
}

Просмотреть файл

@ -1,63 +0,0 @@
namespace Semmle.Extraction.PDB
{
/// <summary>
/// A location in source code.
/// </summary>
public sealed class Location
{
/// <summary>
/// The file containing the code.
/// </summary>
public ISourceFile File { get; }
/// <summary>
/// The start line of text within the source file.
/// </summary>
public int StartLine { get; }
/// <summary>
/// The start column of text within the source file.
/// </summary>
public int StartColumn { get; }
/// <summary>
/// The end line of text within the source file.
/// </summary>
public int EndLine { get; }
/// <summary>
/// The end column of text within the source file.
/// </summary>
public int EndColumn { get; }
public override string ToString()
{
return string.Format("({0},{1})-({2},{3})", StartLine, StartColumn, EndLine, EndColumn);
}
public override bool Equals(object? obj)
{
return obj is Location otherLocation &&
File.Equals(otherLocation.File) &&
StartLine == otherLocation.StartLine &&
StartColumn == otherLocation.StartColumn &&
EndLine == otherLocation.EndLine &&
EndColumn == otherLocation.EndColumn;
}
public override int GetHashCode()
{
var h1 = StartLine + 37 * (StartColumn + 51 * (EndLine + 97 * EndColumn));
return File.GetHashCode() + 17 * h1;
}
public Location(ISourceFile file, int startLine, int startCol, int endLine, int endCol)
{
File = file;
StartLine = startLine;
StartColumn = startCol;
EndLine = endLine;
EndColumn = endCol;
}
}
}

Просмотреть файл

@ -1,37 +0,0 @@
using System;
using System.Reflection;
using Microsoft.DiaSymReader;
#pragma warning disable IDE0060, CA1822
namespace Semmle.Extraction.PDB
{
/// <summary>
/// This is not used but is seemingly needed in order to use DiaSymReader.
/// </summary>
internal class MdProvider : ISymReaderMetadataProvider
{
public MdProvider()
{
}
public object? GetMetadataImport() => null;
public unsafe bool TryGetStandaloneSignature(int standaloneSignatureToken, out byte* signature, out int length) =>
throw new NotImplementedException();
public bool TryGetTypeDefinitionInfo(int typeDefinitionToken, out string namespaceName, out string typeName, out TypeAttributes attributes, out int baseTypeToken) =>
throw new NotImplementedException();
public bool TryGetTypeDefinitionInfo(int typeDefinitionToken, out string namespaceName, out string typeName, out TypeAttributes attributes) =>
throw new NotImplementedException();
public bool TryGetTypeReferenceInfo(int typeReferenceToken, out string namespaceName, out string typeName, out int resolutionScopeToken) =>
throw new NotImplementedException();
public bool TryGetTypeReferenceInfo(int typeReferenceToken, out string namespaceName, out string typeName) =>
throw new NotImplementedException();
}
}
#pragma warning restore

Просмотреть файл

@ -1,99 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
namespace Semmle.Extraction.PDB
{
/// <summary>
/// A reader of PDB information using System.Reflection.Metadata.
/// This is cross platform, and the future of PDB.
///
/// PDB information can be in a separate PDB file, or embedded in the DLL.
/// </summary>
internal sealed class MetadataPdbReader : IPdb
{
private class SourceFile : ISourceFile
{
public SourceFile(MetadataReader reader, DocumentHandle handle)
{
var doc = reader.GetDocument(handle);
Path = reader.GetString(doc.Name);
}
public string Path { get; private set; }
public string? Contents => File.Exists(Path) ? File.ReadAllText(Path, System.Text.Encoding.Default) : null;
}
// Turns out to be very important to keep the MetadataReaderProvider live
// or the reader will crash.
private readonly MetadataReaderProvider provider;
private readonly MetadataReader reader;
public MetadataPdbReader(MetadataReaderProvider provider)
{
this.provider = provider;
reader = provider.GetMetadataReader();
}
public IEnumerable<ISourceFile> SourceFiles => reader.Documents.Select(handle => new SourceFile(reader, handle));
public Method? GetMethod(MethodDebugInformationHandle handle)
{
var debugInfo = reader.GetMethodDebugInformation(handle);
var sequencePoints = debugInfo.GetSequencePoints()
.Where(p => !p.Document.IsNil && !p.IsHidden)
.Select(p => new SequencePoint(p.Offset, new Location(
new SourceFile(reader, p.Document), p.StartLine, p.StartColumn, p.EndLine, p.EndColumn)))
.Where(p => p.Location.File.Path is not null)
.ToArray();
return sequencePoints.Any() ? new Method(sequencePoints) : null;
}
public static MetadataPdbReader? CreateFromAssembly(string assemblyPath, PEReader peReader)
{
var provider = peReader
.ReadDebugDirectory()
.Where(d => d.Type == DebugDirectoryEntryType.EmbeddedPortablePdb)
.Select(dirEntry => peReader.ReadEmbeddedPortablePdbDebugDirectoryData(dirEntry))
.FirstOrDefault();
if (provider is not null)
{
return new MetadataPdbReader(provider);
}
try
{
if (peReader.TryOpenAssociatedPortablePdb(
assemblyPath,
s => new FileStream(s, FileMode.Open, FileAccess.Read, FileShare.Read),
out provider,
out _))
{
return new MetadataPdbReader(provider!);
}
}
catch (BadImageFormatException)
{
// Something is wrong with the file.
}
catch (FileNotFoundException)
{
// The PDB file was not found.
}
return null;
}
public void Dispose()
{
provider.Dispose();
}
}
}

Просмотреть файл

@ -1,17 +0,0 @@
using System.Collections.Generic;
using System.Linq;
namespace Semmle.Extraction.PDB
{
public class Method
{
public IEnumerable<SequencePoint> SequencePoints { get; }
public Method(IEnumerable<SequencePoint> sequencePoints)
{
SequencePoints = sequencePoints;
}
public Location Location => SequencePoints.First().Location;
}
}

Просмотреть файл

@ -1,116 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using Microsoft.DiaSymReader;
namespace Semmle.Extraction.PDB
{
/// <summary>
/// A PDB reader using Microsoft.DiaSymReader.Native.
/// This is an unmanaged Windows DLL, which therefore only works on Windows.
/// </summary>
internal sealed class NativePdbReader : IPdb
{
private sealed class Document : ISourceFile
{
private readonly ISymUnmanagedDocument document;
public Document(ISymUnmanagedDocument doc)
{
document = doc;
contents = new Lazy<string?>(() =>
{
if (document.HasEmbeddedSource(out var isEmbedded) == 0 && isEmbedded)
{
var rawContents = document.GetEmbeddedSource().ToArray();
return System.Text.Encoding.Default.GetString(rawContents);
}
return File.Exists(Path)
? File.ReadAllText(Path)
: null;
});
}
public override bool Equals(object? obj)
{
return obj is Document otherDoc && Path.Equals(otherDoc.Path);
}
public override int GetHashCode() => Path.GetHashCode();
public string Path => document.GetName();
public override string ToString() => Path;
private readonly Lazy<string?> contents;
public string? Contents => contents.Value;
}
public IEnumerable<ISourceFile> SourceFiles => reader.GetDocuments().Select(d => new Document(d));
public Method? GetMethod(MethodDebugInformationHandle h)
{
var methodToken = MetadataTokens.GetToken(h.ToDefinitionHandle());
var method = reader.GetMethod(methodToken);
if (method is not null)
{
if (method.GetSequencePointCount(out var count) != 0 || count == 0)
return null;
var s = method.GetSequencePoints()
.Where(sp => !sp.IsHidden)
.Select(sp => new SequencePoint(sp.Offset, new Location(
new Document(sp.Document), sp.StartLine, sp.StartColumn, sp.EndLine, sp.EndColumn)))
.ToArray();
return s.Any() ? new Method(s) : null;
}
return null;
}
private NativePdbReader(string path)
{
pdbStream = new FileStream(path, FileMode.Open);
var metadataProvider = new MdProvider();
reader = SymUnmanagedReaderFactory.CreateReader<ISymUnmanagedReader5>(pdbStream, metadataProvider);
}
private readonly ISymUnmanagedReader5 reader;
private readonly FileStream pdbStream;
public static NativePdbReader? CreateFromAssembly(PEReader peReader)
{
// The Native PDB reader uses an unmanaged Windows DLL
// so only works on Windows.
if (!Semmle.Util.Win32.IsWindows())
return null;
var debugDirectory = peReader.ReadDebugDirectory();
var path = debugDirectory
.Where(d => d.Type == DebugDirectoryEntryType.CodeView)
.Select(peReader.ReadCodeViewDebugDirectoryData)
.Select(cv => cv.Path)
.FirstOrDefault(File.Exists);
if (path is not null)
{
return new NativePdbReader(path);
}
return null;
}
public void Dispose()
{
pdbStream.Dispose();
}
}
}

Просмотреть файл

@ -1,19 +0,0 @@
using System.Reflection.PortableExecutable;
namespace Semmle.Extraction.PDB
{
internal static class PdbReader
{
/// <summary>
/// Returns the PDB information associated with an assembly.
/// </summary>
/// <param name="assemblyPath">The path to the assembly.</param>
/// <param name="peReader">The PE reader for the assembly.</param>
/// <returns>A PdbReader, or null if no PDB information is available.</returns>
public static IPdb? Create(string assemblyPath, PEReader peReader)
{
return (IPdb?)MetadataPdbReader.CreateFromAssembly(assemblyPath, peReader) ??
NativePdbReader.CreateFromAssembly(peReader);
}
}
}

Просмотреть файл

@ -1,30 +0,0 @@
namespace Semmle.Extraction.PDB
{
/// <summary>
/// A sequencepoint is a marker in the source code where you can put a breakpoint, and
/// maps instructions to source code.
/// </summary>
public struct SequencePoint
{
/// <summary>
/// The byte-offset of the instruction.
/// </summary>
public int Offset { get; }
/// <summary>
/// The source location of the instruction.
/// </summary>
public Location Location { get; }
public override string ToString()
{
return string.Format("{0} = {1}", Offset, Location);
}
public SequencePoint(int offset, Location location)
{
Offset = offset;
Location = location;
}
}
}

Просмотреть файл

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Semmle.Extraction.CIL")]
[assembly: AssemblyDescription("Semme CIL extractor.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Semmle.Extraction.CIL")]
[assembly: AssemblyCopyright("Copyright © Semmle 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("a23d9ec2-8aae-43da-97cb-579f640b89cd")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -1,34 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AssemblyName>Semmle.Extraction.CIL</AssemblyName>
<RootNamespace>Semmle.Extraction.CIL</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>DEBUG;DEBUG_LABELS</DefineConstants>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Semmle.Extraction\Semmle.Extraction.csproj" />
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.DiaSymReader" Version="2.0.0" />
<PackageReference Include="Microsoft.DiaSymReader.Native" Version="1.7.0" />
<PackageReference Include="Microsoft.DiaSymReader.PortablePdb" Version="1.6.0"><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>

Просмотреть файл

@ -1,227 +0,0 @@
using Semmle.Extraction.CIL.Entities;
namespace Semmle.Extraction.CIL
{
internal static class Tuples
{
internal static Tuple assemblies(Assembly assembly, File file, string identifier, string name, string version) =>
new Tuple("assemblies", assembly, file, identifier, name, version);
internal static Tuple cil_abstract(IMember method) =>
new Tuple("cil_abstract", method);
internal static Tuple cil_adder(Event member, Method method) =>
new Tuple("cil_adder", member, method);
internal static Tuple cil_access(Instruction i, IExtractedEntity m) =>
new Tuple("cil_access", i, m);
internal static Tuple cil_attribute(Attribute attribute, IExtractedEntity @object, Method constructor) =>
new Tuple("cil_attribute", attribute, @object, constructor);
internal static Tuple cil_attribute_named_argument(Attribute attribute, string name, string value) =>
new Tuple("cil_attribute_named_argument", attribute, name, value);
internal static Tuple cil_attribute_positional_argument(Attribute attribute, int index, string value) =>
new Tuple("cil_attribute_positional_argument", attribute, index, value);
internal static Tuple cil_array_type(ArrayType array, Type element, int rank) =>
new Tuple("cil_array_type", array, element, rank);
internal static Tuple cil_base_class(Type t, Type @base) =>
new Tuple("cil_base_class", t, @base);
internal static Tuple cil_enum_underlying_type(Type t, PrimitiveType underlying) =>
new Tuple("cil_enum_underlying_type", t, underlying);
internal static Tuple cil_base_interface(Type t, Type @base) =>
new Tuple("cil_base_interface", t, @base);
internal static Tuple cil_class(TypeDefinitionType type) =>
new Tuple("cil_class", type);
internal static Tuple cil_event(Event e, Type parent, string name, Type type) =>
new Tuple("cil_event", e, parent, name, type);
internal static Tuple cil_field(Field field, Type parent, string name, Type fieldType) =>
new Tuple("cil_field", field, parent, name, fieldType);
internal static Tuple cil_getter(Property member, Method method) =>
new Tuple("cil_getter", member, method);
internal static Tuple cil_handler(ExceptionRegion region, MethodImplementation method, int index, int kind,
Instruction region_start,
Instruction region_end,
Instruction handler_start) =>
new Tuple("cil_handler", region, method, index, kind, region_start, region_end, handler_start);
internal static Tuple cil_handler_filter(ExceptionRegion region, Instruction filter_start) =>
new Tuple("cil_handler_filter", region, filter_start);
internal static Tuple cil_handler_type(ExceptionRegion region, Type t) =>
new Tuple("cil_handler_type", region, t);
internal static Tuple cil_implements(Method derived, Method declaration) =>
new Tuple("cil_implements", derived, declaration);
internal static Tuple cil_instruction(Instruction instruction, int opcode, int index, MethodImplementation parent) =>
new Tuple("cil_instruction", instruction, opcode, index, parent);
internal static Tuple cil_instruction_location(Instruction i, PdbSourceLocation loc) =>
new Tuple("cil_instruction_location", i, loc);
internal static Tuple cil_interface(TypeDefinitionType type) =>
new Tuple("cil_interface", type);
internal static Tuple cil_internal(DefinitionField field) =>
new Tuple("cil_internal", field);
internal static Tuple cil_jump(Instruction from, Instruction to) =>
new Tuple("cil_jump", from, to);
internal static Tuple cil_local_variable(LocalVariable l, MethodImplementation m, int i, Type t) =>
new Tuple("cil_local_variable", l, m, i, t);
internal static Tuple cil_method(Method method, string name, Type declType, Type returnType) =>
new Tuple("cil_method", method, name, declType, returnType);
internal static Tuple cil_function_pointer_return_type(FunctionPointerType fnptr, Type returnType) =>
new Tuple("cil_function_pointer_return_type", fnptr, returnType);
internal static Tuple cil_function_pointer_calling_conventions(FunctionPointerType fnptr, System.Reflection.Metadata.SignatureCallingConvention callingConvention) =>
new Tuple("cil_function_pointer_calling_conventions", fnptr, (int)callingConvention);
internal static Tuple cil_method_implementation(MethodImplementation impl, Method method, Assembly assembly) =>
new Tuple("cil_method_implementation", impl, method, assembly);
internal static Tuple cil_method_location(Method m, ILocation a) =>
new Tuple("cil_method_location", m, a);
internal static Tuple cil_method_source_declaration(Method method, Method sourceDecl) =>
new Tuple("cil_method_source_declaration", method, sourceDecl);
internal static Tuple cil_method_stack_size(MethodImplementation method, int stackSize) =>
new Tuple("cil_method_stack_size", method, stackSize);
internal static Tuple cil_newslot(Method method) =>
new Tuple("cil_newslot", method);
internal static Tuple cil_parameter(Parameter p, IParameterizable m, int i, Type t) =>
new Tuple("cil_parameter", p, m, i, t);
internal static Tuple cil_parameter_in(Parameter p) =>
new Tuple("cil_parameter_in", p);
internal static Tuple cil_parameter_out(Parameter p) =>
new Tuple("cil_parameter_out", p);
internal static Tuple cil_pointer_type(PointerType t, Type pointee) =>
new Tuple("cil_pointer_type", t, pointee);
internal static Tuple cil_private(IMember modifiable) =>
new Tuple("cil_private", modifiable);
internal static Tuple cil_protected(IMember modifiable) =>
new Tuple("cil_protected", modifiable);
internal static Tuple cil_property(Property p, Type parent, string name, Type propType) =>
new Tuple("cil_property", p, parent, name, propType);
internal static Tuple cil_public(IMember modifiable) =>
new Tuple("cil_public", modifiable);
internal static Tuple cil_raiser(Event member, Method method) =>
new Tuple("cil_raiser", member, method);
internal static Tuple cil_requiresecobject(Method method) =>
new Tuple("cil_requiresecobject", method);
internal static Tuple cil_remover(Event member, Method method) =>
new Tuple("cil_remover", member, method);
internal static Tuple cil_sealed(IMember modifiable) =>
new Tuple("cil_sealed", modifiable);
internal static Tuple cil_security(IMember method) =>
new Tuple("cil_security", method);
internal static Tuple cil_setter(Property member, Method method) =>
new Tuple("cil_setter", member, method);
internal static Tuple cil_specialname(Method method) =>
new Tuple("cil_specialname", method);
internal static Tuple cil_static(IMember modifiable) =>
new Tuple("cil_static", modifiable);
internal static Tuple cil_switch(Instruction from, int index, Instruction to) =>
new Tuple("cil_switch", from, index, to);
internal static Tuple cil_type(Type t, string name, CilTypeKind kind, TypeContainer parent, Type sourceDecl) =>
new Tuple("cil_type", t, name, (int)kind, parent, sourceDecl);
internal static Tuple cil_type_argument(TypeContainer constructedTypeOrMethod, int index, Type argument) =>
new Tuple("cil_type_argument", constructedTypeOrMethod, index, argument);
internal static Tuple cil_type_location(Type t, Assembly a) =>
new Tuple("cil_type_location", t, a);
internal static Tuple cil_type_parameter(TypeContainer unboundTypeOrMethod, int index, TypeParameter parameter) =>
new Tuple("cil_type_parameter", unboundTypeOrMethod, index, parameter);
internal static Tuple cil_typeparam_covariant(TypeParameter p) =>
new Tuple("cil_typeparam_covariant", p);
internal static Tuple cil_typeparam_contravariant(TypeParameter p) =>
new Tuple("cil_typeparam_contravariant", p);
internal static Tuple cil_typeparam_class(TypeParameter p) =>
new Tuple("cil_typeparam_class", p);
internal static Tuple cil_typeparam_constraint(TypeParameter p, Type constraint) =>
new Tuple("cil_typeparam_constraint", p, constraint);
internal static Tuple cil_typeparam_new(TypeParameter p) =>
new Tuple("cil_typeparam_new", p);
internal static Tuple cil_typeparam_struct(TypeParameter p) =>
new Tuple("cil_typeparam_struct", p);
internal static Tuple cil_value(Instruction i, string value) =>
new Tuple("cil_value", i, value);
internal static Tuple cil_virtual(Method method) =>
new Tuple("cil_virtual", method);
internal static Tuple cil_custom_modifiers(ICustomModifierReceiver receiver, Type modifier, bool isRequired) =>
new Tuple("cil_custom_modifiers", receiver, modifier, isRequired ? 1 : 0);
internal static Tuple cil_type_annotation(IExtractedEntity receiver, TypeAnnotation annotation) =>
new Tuple("cil_type_annotation", receiver, (int)annotation);
internal static Tuple containerparent(Folder parent, IFileOrFolder child) =>
new Tuple("containerparent", parent, child);
internal static Tuple files(File file, string fullName) =>
new Tuple("files", file, fullName);
internal static Tuple file_extraction_mode(File file, ExtractorMode mode) =>
new Tuple("file_extraction_mode", file, mode);
internal static Tuple folders(Folder folder, string path) =>
new Tuple("folders", folder, path);
internal static Tuple locations_default(PdbSourceLocation label, File file, int startLine, int startCol, int endLine, int endCol) =>
new Tuple("locations_default", label, file, startLine, startCol, endLine, endCol);
internal static Tuple metadata_handle(IExtractedEntity entity, Assembly assembly, int handleValue) =>
new Tuple("metadata_handle", entity, assembly, handleValue);
internal static Tuple namespaces(Namespace ns, string name) =>
new Tuple("namespaces", ns, name);
internal static Tuple parent_namespace(TypeContainer child, Namespace parent) =>
new Tuple("parent_namespace", child, parent);
}
}

Просмотреть файл

@ -58,7 +58,6 @@ namespace Semmle.Extraction.CSharp.Standalone
output.WriteLine("Additional options:\n");
output.WriteLine(" --threads:nnn Specify number of threads (default=CPU cores)");
output.WriteLine(" --verbose Produce more output");
output.WriteLine(" --pdb Cross-reference information from PDBs where available");
}
private Options()

Просмотреть файл

@ -66,9 +66,6 @@ namespace Semmle.Extraction.CSharp
{
foreach (var assembly in compilation.References.OfType<PortableExecutableReference>())
{
// CIL first - it takes longer.
if (options.CIL)
extractionTasks.Add(() => DoExtractCIL(assembly));
extractionTasks.Add(() => DoAnalyseReferenceAssembly(assembly));
}
}
@ -177,17 +174,6 @@ namespace Semmle.Extraction.CSharp
}
}
private void DoExtractCIL(PortableExecutableReference r)
{
var currentTaskId = IncrementTaskCount();
ReportProgressTaskStarted(currentTaskId, r.FilePath);
var stopwatch = new Stopwatch();
stopwatch.Start();
CIL.Analyser.ExtractCIL(r.FilePath!, Logger, options, out var trapFile, out var extracted);
stopwatch.Stop();
ReportProgressTaskDone(currentTaskId, r.FilePath, trapFile, stopwatch.Elapsed, extracted ? AnalysisAction.Extracted : AnalysisAction.UpToDate);
}
private void DoExtractTree(SyntaxTree tree)
{
try

Просмотреть файл

@ -9,7 +9,6 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Semmle.Extraction.CIL\Semmle.Extraction.CIL.csproj" />
<ProjectReference Include="..\Semmle.Extraction\Semmle.Extraction.csproj" />
<ProjectReference Include="..\Semmle.Extraction.CSharp.Util\Semmle.Extraction.CSharp.Util.csproj" />
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />

Просмотреть файл

@ -22,14 +22,12 @@ namespace Semmle.Extraction.Tests
{
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.Cache);
Assert.False(options.CIL);
Assert.Null(options.Framework);
Assert.Null(options.CompilerName);
Assert.Empty(options.CompilerArguments);
Assert.True(options.Threads >= 1);
Assert.Equal(Verbosity.Info, options.LegacyVerbosity);
Assert.False(options.Console);
Assert.False(options.PDB);
Assert.False(options.Fast);
Assert.Equal(TrapWriter.CompressionMode.Brotli, options.TrapCompression);
}
@ -48,25 +46,6 @@ namespace Semmle.Extraction.Tests
Assert.False(options.Cache);
}
[Fact]
public void CIL()
{
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.False(options.CIL);
Environment.SetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_OPTION_CIL", "false");
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.False(options.CIL);
Environment.SetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_OPTION_CIL", "true");
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.True(options.CIL);
Environment.SetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_OPTION_CIL", null);
options = CSharp.Options.CreateWithEnvironment(Array.Empty<string>());
Assert.False(options.CIL);
}
[Fact]
public void CompilerArguments()
{
@ -141,13 +120,6 @@ namespace Semmle.Extraction.Tests
Assert.True(options.Console);
}
[Fact]
public void PDB()
{
options = CSharp.Options.CreateWithEnvironment(new string[] { "--pdb" });
Assert.True(options.PDB);
}
[Fact]
public void Compiler()
{

Просмотреть файл

@ -55,21 +55,11 @@ namespace Semmle.Extraction
/// </summary>
public bool Console { get; private set; } = false;
/// <summary>
/// Holds if CIL should be extracted.
/// </summary>
public bool CIL { get; private set; } = false;
/// <summary>
/// Holds if assemblies shouldn't be extracted twice.
/// </summary>
public bool Cache { get; private set; } = true;
/// <summary>
/// Whether to extract PDB information.
/// </summary>
public bool PDB { get; private set; } = false;
/// <summary>
/// Whether "fast extraction mode" has been enabled.
/// </summary>
@ -102,9 +92,6 @@ namespace Semmle.Extraction
return true;
}
return false;
case "cil":
CIL = Boolean.Parse(value);
return true;
default:
return false;
}
@ -128,12 +115,7 @@ namespace Semmle.Extraction
case "cache":
Cache = value;
return true;
case "pdb":
PDB = value;
CIL = true;
return true;
case "fast":
CIL = !value;
Fast = value;
return true;
case "qltest":

Просмотреть файл

@ -40,7 +40,7 @@ namespace Semmle.Util
public static class OptionsExtensions
{
private static readonly string[] ExtractorOptions = new[] { "trap_compression", "cil" };
private static readonly string[] ExtractorOptions = ["trap_compression"];
private static List<string> GetExtractorOptions()
{
var extractorOptions = new List<string>();

Просмотреть файл

@ -0,0 +1,4 @@
---
category: breaking
---
* The CIL extractor has been deleted and the corresponding extractor option `cil` has been removed. It is no longer possible to do CIL extraction.

Просмотреть файл

@ -1,5 +0,0 @@
using System;
class Test
{
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,47 +0,0 @@
import semmle.code.cil.Attribute
import semmle.code.cil.Declaration
deprecated private predicate isOsSpecific(Declaration d) {
d.getFullyQualifiedName()
.matches("%" +
[
"libobjc", "libproc", "libc", "Interop.OSReleaseFile", "Interop.Sys",
"System.Runtime.InteropServices.ObjectiveC.ObjectiveCMarshal",
"System.Diagnostics.Tracing.XplatEventLogger", "System.Threading.AutoreleasePool",
"System.CLRConfig", "System.Diagnostics.Tracing.EventSource.<WriteEventString>",
"System.IO.FileSystem.<TryCloneFile>"
] + "%")
}
deprecated query predicate attrNoArg(string dec, string attr) {
exists(Declaration d, Attribute a |
not isOsSpecific(d) and
a.getDeclaration() = d and
not exists(a.getAnArgument())
|
dec = d.toStringWithTypes() and
attr = a.toStringWithTypes()
)
}
deprecated query predicate attrArgNamed(string dec, string attr, string name, string value) {
exists(Declaration d, Attribute a |
a.getDeclaration() = d and
not isOsSpecific(d) and
a.getNamedArgument(name) = value
|
dec = d.toStringWithTypes() and
attr = a.toStringWithTypes()
)
}
deprecated query predicate attrArgPositional(string dec, string attr, int index, string value) {
exists(Declaration d, Attribute a |
a.getDeclaration() = d and
not isOsSpecific(d) and
a.getArgument(index) = value
|
dec = d.toStringWithTypes() and
attr = a.toStringWithTypes()
)
}

Просмотреть файл

@ -1 +0,0 @@
semmle-extractor-options: --cil

Просмотреть файл

@ -1,14 +0,0 @@
tooManyHandles
tooManyMatchingHandles
missingCil
csharpLocationViolation
matchingObjectMethods
| Equals(object) | System.Boolean System.Object.Equals(System.Object) |
| Equals(object, object) | System.Boolean System.Object.Equals(System.Object,System.Object) |
| GetHashCode() | System.Int32 System.Object.GetHashCode() |
| GetType() | System.Type System.Object.GetType() |
| MemberwiseClone() | System.Object System.Object.MemberwiseClone() |
| Object() | System.Void System.Object..ctor() |
| ReferenceEquals(object, object) | System.Boolean System.Object.ReferenceEquals(System.Object,System.Object) |
| ToString() | System.String System.Object.ToString() |
| ~Object() | System.Void System.Object.Finalize() |

Просмотреть файл

@ -1,68 +0,0 @@
import csharp
import cil
import dotnet
import semmle.code.csharp.commons.QualifiedName
deprecated class MetadataEntity extends DotNet::NamedElement, @metadata_entity {
int getHandle() { metadata_handle(this, _, result) }
predicate hasHandle() { exists(this.getHandle()) }
Assembly getAssembly() { metadata_handle(this, result, _) }
}
deprecated query predicate tooManyHandles(string s) {
exists(MetadataEntity e, Assembly a, string qualifier, string name |
strictcount(int handle | metadata_handle(e, a, handle)) > 1 and
e.hasFullyQualifiedName(qualifier, name) and
s = getQualifiedName(qualifier, name)
)
}
deprecated private class UniqueMetadataEntity extends MetadataEntity {
UniqueMetadataEntity() {
// Tuple types such as `(,)` and `ValueTuple`2` share the same handle
not this instanceof TupleType and
not exists(string name |
this.hasFullyQualifiedName("System", name) and
name.matches("System.ValueTuple%")
)
}
}
deprecated query predicate tooManyMatchingHandles(string s) {
exists(UniqueMetadataEntity e, Assembly a, int handle, string qualifier, string name |
metadata_handle(e, a, handle) and
strictcount(UniqueMetadataEntity e2 | metadata_handle(e2, a, handle)) > 2 and
e.hasFullyQualifiedName(qualifier, name) and
s = getQualifiedName(qualifier, name)
)
}
deprecated query predicate missingCil(Element e) {
(
e instanceof Callable
or
e instanceof Type
or
e instanceof Field
) and
e.fromLibrary() and
e.(MetadataEntity).hasHandle() and
not exists(CIL::Element ce | ce.(MetadataEntity).matchesHandle(e))
}
deprecated query predicate csharpLocationViolation(Element e) {
e.fromLibrary() and
e.(MetadataEntity).hasHandle() and
not e.getALocation() = e.(MetadataEntity).getAssembly()
}
deprecated query predicate matchingObjectMethods(string s1, string s2) {
exists(Callable m1, CIL::Method m2 |
m1.getDeclaringType().hasFullyQualifiedName("System", "Object") and
m1.(DotNet::Callable).matchesHandle(m2) and
s1 = m1.toStringWithTypes() and
s2 = m2.toStringWithTypes()
)
}

Просмотреть файл

@ -1,8 +0,0 @@
using System;
class Test
{
static void Main(string[] args)
{
}
}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -1,6 +0,0 @@
import cil
import semmle.code.cil.ConsistencyChecks
deprecated query predicate consistencyViolation(ConsistencyViolation v, string message) {
message = v.getMessage()
}

Просмотреть файл

@ -1 +0,0 @@
semmle-extractor-options: --cil

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше