This commit is contained in:
Nick Guerrera 2018-07-03 11:01:33 -07:00
Родитель 399c407883 48fa19848b
Коммит 3321ae7f03
14 изменённых файлов: 256 добавлений и 34 удалений

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

@ -3220,14 +3220,14 @@ namespace Microsoft.Cci.Immutable {
/// True if the return value is passed by reference (using a managed pointer).
/// </summary>
public bool ReturnValueIsByRef {
get { return this.UnspecializedVersion.AcceptsExtraArguments; }
get { return this.UnspecializedVersion.ReturnValueIsByRef; }
}
/// <summary>
/// True if the return value has one or more custom modifiers associated with it.
/// </summary>
public bool ReturnValueIsModified {
get { return this.UnspecializedVersion.AcceptsExtraArguments; }
get { return this.UnspecializedVersion.ReturnValueIsModified; }
}
/// <summary>

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

@ -2269,6 +2269,13 @@ namespace Microsoft.Cci {
foreach (ITypeReference baseClass in type.BaseClasses) {
if (TypeHelper.TypesAreEquivalent(baseClass, type.PlatformType.SystemAttribute, true)) return true;
}
// If the type isn't directly derived from Attribute, its parent may be
foreach (ITypeReference baseClass in type.BaseClasses) {
ITypeDefinition baseDef = baseClass.ResolvedType;
if (baseDef != null && IsAttributeType(baseDef)) return true;
}
return false;
}

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

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Diagnostics.Contracts;
using Microsoft.Cci.MetadataReader.PEFileFlags;
namespace Microsoft.Cci {
@ -983,6 +984,10 @@ namespace Microsoft.Cci {
get { return 0; }
}
public COR20Flags COR20Flags {
get { return default(COR20Flags); }
}
public bool ILOnly {
get { return false; }
}
@ -3085,6 +3090,10 @@ namespace Microsoft.Cci {
get { return 0; }
}
public COR20Flags COR20Flags {
get { return default(COR20Flags); }
}
public bool ILOnly {
get { return false; }
}

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

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Text;
using System.Globalization;
using Microsoft.Cci.MetadataReader.PEFileFlags;
namespace Microsoft.Cci {
/// <summary>
@ -214,6 +215,10 @@ namespace Microsoft.Cci {
throw new NotImplementedException();
}
public COR20Flags COR20Flags {
get { throw new NotImplementedException(); }
}
public bool ILOnly {
get { throw new NotImplementedException(); }
}
@ -743,6 +748,10 @@ namespace Microsoft.Cci {
/// </summary>
M32R = 0x9041,
/// <summary>
/// ARM64 Little-Endian
/// </summary>
ARM64 = 0xAA64,
/// <summary>
/// CEE
/// </summary>
CEE = 0xC0EE,
@ -843,6 +852,11 @@ namespace Microsoft.Cci {
/// </summary>
IEnumerable<ITypeMemberReference> GetTypeMemberReferences();
/// <summary>
/// Gets the set of COR flags applied to the module.
/// </summary>
COR20Flags COR20Flags { get; }
/// <summary>
/// True if the module contains only IL and is processor independent.
/// </summary>
@ -902,7 +916,7 @@ namespace Microsoft.Cci {
/// <summary>
/// A globally unique persistent identifier for this module.
/// </summary>
System.Guid PersistentIdentifier { get; }
System.Guid PersistentIdentifier { get; }
/// <summary>
/// If set, the module is platform independent but prefers to be loaded in a 32-bit process for performance reasons.
@ -1089,6 +1103,10 @@ namespace Microsoft.Cci {
throw new NotImplementedException();
}
public COR20Flags COR20Flags {
get { throw new NotImplementedException(); }
}
public bool ILOnly {
get { throw new NotImplementedException(); }
}

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

@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.Cci.MetadataReader.PEFileFlags;
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
@ -765,6 +766,7 @@ namespace Microsoft.Cci.MutableCodeModel {
this.genericMethodInstances = new List<IGenericMethodInstanceReference>(genericMethodInstances);
else
this.genericMethodInstances = null;
this.cor20Flags = module.COR20Flags;
this.ilOnly = module.ILOnly;
this.strongNameSigned = module.StrongNameSigned;
this.prefers32bits = module.Prefers32bits;
@ -937,6 +939,12 @@ namespace Microsoft.Cci.MutableCodeModel {
}
List<IGenericMethodInstanceReference>/*?*/ genericMethodInstances;
public COR20Flags COR20Flags {
get { return this.cor20Flags; }
set { this.cor20Flags = value; }
}
COR20Flags cor20Flags;
/// <summary>
/// True if the module contains only IL and is processor independent.
/// </summary>

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

@ -1540,6 +1540,31 @@ namespace Microsoft.Cci {
}
#endregion
/// <summary>
/// An object that can retrieve the source link information embedded in a PDB file.
/// For example, a PDB reader that can read the source link information
/// </summary>
[ContractClass(typeof(ISourceLinkProviderContract))]
public interface ISourceLinkProvider {
/// <summary>
/// Return the source link data as a byte array or null if there is no source link information embedded
/// </summary>
IEnumerable<byte> GetSourceLinkData();
}
#region ISourceLinkProvider contract binding
[ContractClassFor(typeof(ISourceLinkProvider))]
abstract class ISourceLinkProviderContract : ISourceLinkProvider {
#region ISourceLinkProvider Members
public IEnumerable<byte> GetSourceLinkData() {
throw new NotImplementedException();
}
#endregion
}
#endregion
/// <summary>
/// A range of CLR IL operations that comprise a lexical scope, specified as an IL offset and a length.
/// </summary>

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

@ -70,7 +70,10 @@
<Reference Include="System.IO" />
<Reference Include="System.Reflection.Metadata" />
<Reference Include="System.Runtime" />
<Reference Include="Microsoft.DiaSymReader.Converter" />
<ReferencePath Include="$(SupportAssemblyPath)\Microsoft.DiaSymReader.dll" />
<Reference Include="Microsoft.DiaSymReader.Converter">
<Aliases>DiaSymReaderPdbConverter</Aliases>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$(EnablePortablePdb)' == 'true'">
<Content Include="$(PortablePdbConverterPath)\Microsoft.DiaSymReader.Converter.dll" />

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

@ -9,6 +9,12 @@ using System.IO;
namespace Microsoft.Cci.Pdb {
internal class PdbFile {
/// <summary>
/// GUID of the Basic source language.
/// </summary>
private static readonly Guid BasicLanguageGuid = new Guid(974311608, -15764, 4560, 180, 66, 0, 160, 36, 74, 29, 210);
private PdbFile() // This class can't be instantiated.
{
}
@ -220,6 +226,11 @@ namespace Microsoft.Cci.Pdb {
bits.ReadUInt32(out file.linsiz); // Size of payload.
PdbSource src = (PdbSource)checks[(int)file.index];
if (src.language.Equals(BasicLanguageGuid))
{
func.AdjustVisualBasicScopes();
}
PdbLines tmp = new PdbLines(src, file.count);
func.lines[block++] = tmp;
PdbLine[] lines = tmp.lines;
@ -349,7 +360,7 @@ namespace Microsoft.Cci.Pdb {
internal static PdbInfo LoadFunctions(Stream read) {
PdbInfo pdbInfo = new PdbInfo();
pdbInfo.TokenToSourceMapping = new Dictionary<uint, PdbTokenLine>();
BitAccess bits = new BitAccess(64 * 1024);
PdbFileHeader head = new PdbFileHeader(read, bits);
@ -378,6 +389,14 @@ namespace Microsoft.Cci.Pdb {
pdbInfo.SourceServerData = bits.ReadBString(bytes.Length);
}
int sourceLinkStream;
if (nameIndex.TryGetValue("SOURCELINK", out sourceLinkStream)) {
DataStream dataStream = dir.streams[sourceLinkStream];
pdbInfo.SourceLinkData = new byte[dataStream.contentSize];
dataStream.Read(reader, bits);
bits.ReadBytes(pdbInfo.SourceLinkData);
}
dir.streams[3].Read(reader, bits);
LoadDbiStream(bits, out modules, out header, true);

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

@ -1,6 +1,8 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
extern alias DiaSymReaderPdbConverter;
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
@ -11,8 +13,8 @@ using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using Microsoft.DiaSymReader.PortablePdb;
using Microsoft.DiaSymReader.Tools;
using DiaSymReaderPdbConverter::Microsoft.DiaSymReader.PortablePdb;
using DiaSymReaderPdbConverter::Microsoft.DiaSymReader.Tools;
namespace Microsoft.Cci.Pdb {
/// <summary>
@ -43,13 +45,13 @@ namespace Microsoft.Cci.Pdb {
{
// Load associated portable PDB
PdbWriterForCci cciWriter = new PdbWriterForCci();
new PdbConverter().ConvertPortableToWindows<int>(
new PdbConverter().ConvertPortableToWindows(
peReader,
pdbReaderProvider.GetMetadataReader(),
cciWriter,
PdbConversionOptions.SuppressSourceLinkConversion);
PdbInfo pdbInfo = new PdbInfo()
{
Functions = cciWriter.Functions,
@ -57,9 +59,10 @@ namespace Microsoft.Cci.Pdb {
Age = cciWriter.Age,
Guid = cciWriter.Guid,
// Ignored for portable PDBs to avoid bringing in a dependency on Newtonsoft.Json
SourceServerData = null
SourceServerData = null,
SourceLinkData = cciWriter.SourceLinkData
};
return pdbInfo;
}
}
@ -86,7 +89,7 @@ namespace Microsoft.Cci.Pdb {
/// The basic idea of the portable PDB conversion is that we let the converter run
/// and use this PdbWriterForCci class to construct the CCI-expected data structures.
/// </summary>
class PdbWriterForCci : Microsoft.DiaSymReader.PdbWriter<int>
class PdbWriterForCci : Microsoft.DiaSymReader.SymUnmanagedWriter
{
/// <summary>
/// List of functions exposed by the PDB.
@ -108,6 +111,11 @@ namespace Microsoft.Cci.Pdb {
/// </summary>
public Guid Guid { get; private set; }
/// <summary>
/// Raw source link data
/// </summary>
public byte[] SourceLinkData { get; private set; }
/// <summary>
/// List of previously defined PdbSource documents
/// </summary>
@ -158,7 +166,7 @@ namespace Microsoft.Cci.Pdb {
/// Define an indexed document to be subsequently referred to by sequence points.
/// </summary>
/// <returns>Document index that the converter will subsequently pass to DefineSequencePoints</returns>
public override int DefineDocument(string name, Guid language, Guid vendor, Guid type, Guid algorithmId, byte[] checksum)
public override int DefineDocument(string name, Guid language, Guid vendor, Guid type, Guid algorithmId, byte[] checksum, byte[] source)
{
int documentIndex = _sourceDocuments.Count;
_sourceDocuments.Add(new PdbSource(
@ -267,7 +275,7 @@ namespace Microsoft.Cci.Pdb {
public override void CloseMethod()
{
Contract.Assert(_currentMethod != null);
List<PdbLines> documentLineSets = new List<PdbLines>();
foreach (KeyValuePair<int, List<PdbLine>> tokenLinePair in _linesForCurrentMethod)
{
@ -332,7 +340,7 @@ namespace Microsoft.Cci.Pdb {
/// <param name="name">Variable name</param>
/// <param name="attributes">Variable properties</param>
/// <param name="localSignatureToken">Signature token representing the variable type</param>
public override void DefineLocalVariable(int index, string name, LocalVariableAttributes attributes, int localSignatureToken)
public override void DefineLocalVariable(int index, string name, int attributes, int localSignatureToken)
{
Contract.Assert(_currentScope != null);
@ -351,7 +359,7 @@ namespace Microsoft.Cci.Pdb {
/// <param name="name">Constant name</param>
/// <param name="value">Constant value</param>
/// <param name="constantSignatureToken">Signature token representing the constant type</param>
public override void DefineLocalConstant(string name, object value, int constantSignatureToken)
public override bool DefineLocalConstant(string name, object value, int constantSignatureToken)
{
Contract.Assert(_currentScope != null);
@ -361,9 +369,13 @@ namespace Microsoft.Cci.Pdb {
name: name,
token: (uint)constantSignatureToken,
value: value);
_currentScope.AddConstant(pdbConstant);
return true;
}
return false;
}
/// <summary>
@ -412,6 +424,77 @@ namespace Microsoft.Cci.Pdb {
}
public override void SetSourceLinkData(byte[] sourceLinkData)
{
SourceLinkData = sourceLinkData;
}
public override void Dispose()
{
// NO-OP for CCI
}
/// <summary>
/// Gets the current PDB signature.
/// </summary>
public override void GetSignature(out Guid guid, out uint stamp, out int age)
{
guid = Guid;
age = Age;
stamp = 0;
}
/// <summary>
/// Gets the raw data blobs that comprise the written PDB content so far.
/// </summary>
public override IEnumerable<ArraySegment<byte>> GetUnderlyingData()
{
// NO-OP for CCI
return null;
}
public override int DocumentTableCapacity
{
get => _sourceDocuments.Capacity;
set
{
if (value > _sourceDocuments.Count)
{
_sourceDocuments.Capacity = value;
}
}
}
/// <summary>
/// Opens a map of tokens to source spans.
/// </summary>
public override void OpenTokensToSourceSpansMap()
{
// NO-OP for CCI
}
/// <summary>
/// Maps specified token to a source span.
/// </summary>
public override void MapTokenToSourceSpan(int token, int documentIndex, int startLine, int startColumn, int endLine, int endColumn)
{
// NO-OP for CCI
}
/// <summary>
/// Closes map of tokens to source spans previously opened using <see cref="M:Microsoft.DiaSymReader.SymUnmanagedWriter.OpenTokensToSourceSpansMap" />.
/// </summary>
public override void CloseTokensToSourceSpansMap()
{
// NO-OP for CCI
}
/// <summary>
/// Writes the PDB data to specified stream. Once called no more changes to the data can be made using this writer.
/// May be called multiple times. Always writes the same data.
/// </summary>
/// <param name="stream">Stream to write PDB data to.</param>
public override void WriteTo(Stream stream)
{
// NO-OP for CCI
}
@ -430,27 +513,27 @@ namespace Microsoft.Cci.Pdb {
/// Starting IL offset for the scope gets initialized in the constructor.
/// </summary>
private readonly uint _startOffset;
/// <summary>
/// Lazily constructed list of child scopes.
/// </summary>
private List<PdbScope> _childScopes;
/// <summary>
/// Lazily constructed list of per-scope constants.
/// </summary>
private List<PdbConstant> _constants;
/// <summary>
/// Lazily constructed list of 'using' namespaces within the scope.
/// </summary>
private List<string> _usedNamespaces;
/// <summary>
/// Lazily constructed list of slots (local variables).
/// </summary>
private List<PdbSlot> _slots;
/// <summary>
/// Constructor stores the starting IL offset for the scope.
/// </summary>
@ -461,7 +544,7 @@ namespace Microsoft.Cci.Pdb {
_constants = new List<PdbConstant>();
_slots = new List<PdbSlot>();
}
/// <summary>
/// Finalize construction of the PdbScope and return the complete PdbScope object.
/// </summary>
@ -478,7 +561,7 @@ namespace Microsoft.Cci.Pdb {
scope.scopes = _childScopes.ToArray();
return scope;
}
/// <summary>
/// Add a scope to the list of immediate child scopes of this scope.
/// </summary>
@ -487,7 +570,7 @@ namespace Microsoft.Cci.Pdb {
{
_childScopes.Add(childScope);
}
/// <summary>
/// Add a slot (local variable) to the list of slots for this scope.
/// </summary>
@ -496,7 +579,7 @@ namespace Microsoft.Cci.Pdb {
{
_slots.Add(slot);
}
/// <summary>
/// Add a constant to the list of constants available within this scope.
/// </summary>
@ -505,7 +588,7 @@ namespace Microsoft.Cci.Pdb {
{
_constants.Add(pdbConstant);
}
/// <summary>
/// Add a used namespace to the list of namespaces used by this scope.
/// </summary>

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

@ -38,6 +38,13 @@ namespace Microsoft.Cci.Pdb {
internal List<ILocalScope>/*?*/ iteratorScopes;
internal PdbSynchronizationInformation/*?*/ synchronizationInformation;
/// <summary>
/// Flag saying whether the method has been identified as a product of VB compilation using
/// the legacy Windows PDB symbol format, in which case scope ends need to be shifted by 1
/// due to different semantics of scope limits in VB and C# compilers.
/// </summary>
private bool visualBasicScopesAdjusted = false;
private static string StripNamespace(string module) {
int li = module.LastIndexOf('.');
if (li > 0) {
@ -46,6 +53,36 @@ namespace Microsoft.Cci.Pdb {
return module;
}
/// <summary>
/// When the Windows PDB reader identifies a PdbFunction as having 'Basic' as its source language,
/// it calls this method which adjusts all scopes by adding 1 to their lengths to compensate
/// for different behavior of VB vs. the C# compiler w.r.t. emission of scope info.
/// </summary>
internal void AdjustVisualBasicScopes()
{
if (!visualBasicScopesAdjusted)
{
visualBasicScopesAdjusted = true;
// Don't adjust root scope as that one is correct
foreach (PdbScope scope in scopes)
{
AdjustVisualBasicScopes(scope.scopes);
}
}
}
/// <summary>
/// Recursively update the entire scope tree by adding 1 to the length of each scope.
/// </summary>
private void AdjustVisualBasicScopes(PdbScope[] scopes)
{
foreach (PdbScope scope in scopes)
{
scope.length++;
AdjustVisualBasicScopes(scope.scopes);
}
}
internal static PdbFunction[] LoadManagedFunctions(/*string module,*/
BitAccess bits, uint limit,

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

@ -36,5 +36,10 @@ namespace Microsoft.Cci {
/// GUID of the PDB file is used to match the PDB against the PE binary.
/// </summary>
public Guid Guid;
/// <summary>
/// Source link data information.
/// </summary>
public byte[] SourceLinkData;
}
}

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

@ -16,7 +16,7 @@ namespace Microsoft.Cci {
/// <summary>
/// An object that can map offsets in an IL stream to source locations and block scopes.
/// </summary>
public class PdbReader : ISourceLocationProvider, ILocalScopeProvider, IDisposable {
public class PdbReader : ISourceLocationProvider, ILocalScopeProvider, ISourceLinkProvider, IDisposable {
IMetadataHost host;
Dictionary<uint, PdbFunction> pdbFunctionMap = new Dictionary<uint, PdbFunction>();
@ -121,6 +121,10 @@ namespace Microsoft.Cci {
.Distinct();
}
public IEnumerable<byte> GetSourceLinkData() {
return pdbInfo.SourceLinkData;
}
/// <summary>
/// Return zero or more locations in primary source documents that correspond to one or more of the given derived (non primary) document locations.
/// </summary>
@ -274,7 +278,7 @@ namespace Microsoft.Cci {
}
/// <summary>
///
///
/// </summary>
/// <param name="localDefinition"></param>
/// <param name="isCompilerGenerated"></param>
@ -416,7 +420,7 @@ namespace Microsoft.Cci {
if (pdbLocalScope == null) yield break;
foreach (PdbSlot slot in pdbLocalScope.pdbScope.slots) {
if ((slot.flags & 1) != 0) continue;
if (slot.slot == 0 && slot.name.StartsWith("$VB"))
if (slot.slot == 0 && slot.name.StartsWith("$VB"))
yield return new PdbLocalVariable(slot, this.host, pdbLocalScope.methodBody.MethodDefinition);
uint index = 0;
foreach (ILocalDefinition localDefinition in pdbLocalScope.methodBody.LocalVariables) {
@ -727,7 +731,7 @@ namespace Microsoft.Cci.Pdb {
internal sealed class PdbSourceDocument : PrimarySourceDocument {
/// <summary>
/// Allocates an object that represents a source document, such as file, which is parsed according to the rules of a particular langauge,
/// Allocates an object that represents a source document, such as file, which is parsed according to the rules of a particular langauge,
/// such as C#, to produce an object model.
/// </summary>
/// <param name="name">The name of the document. Used to identify the document in user interaction.</param>
@ -739,7 +743,7 @@ namespace Microsoft.Cci.Pdb {
}
/// <summary>
/// Allocates an object that represents a source document, such as file, which is parsed according to the rules of a particular langauge,
/// Allocates an object that represents a source document, such as file, which is parsed according to the rules of a particular langauge,
/// such as C#, to produce an object model.
/// </summary>
/// <param name="name">The name of the document. Used to identify the document in user interaction.</param>

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

@ -435,6 +435,10 @@ namespace Microsoft.Cci.MetadataReader.ObjectModelImplementation {
get { return this.PEFileToObjectModel.PEFileReader.FileAlignment; }
}
COR20Flags IModule.COR20Flags {
get { return this.Cor20Flags; }
}
bool IModule.ILOnly {
get { return (this.Cor20Flags & COR20Flags.ILOnly) == COR20Flags.ILOnly; }
}

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

@ -147,7 +147,7 @@ namespace Microsoft.Cci.MetadataReader.PEFileFlags {
MemWrite = 0x80000000, // Section is writeable.
}
internal enum COR20Flags : uint {
public enum COR20Flags : uint {
ILOnly = 0x00000001,
Bit32Required = 0x00000002,
ILLibrary = 0x00000004,