Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add PDB support for PersistedAssemblyBuilder #100706

Merged
merged 12 commits into from
Apr 16, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -4316,4 +4316,7 @@
<data name="WasmThreads_BlockingWaitNotSupportedOnJSInterop" xml:space="preserve">
<value>Blocking wait is not supported on the JS interop threads.</value>
</data>
<data name="NotSupported_EmitDebugInfo" xml:space="preserve">
<value>Emitting debug info is not supported for this member.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Diagnostics.SymbolStore;

namespace System.Reflection.Emit
{
Expand Down Expand Up @@ -200,6 +201,66 @@ public virtual LocalBuilder DeclareLocal(Type localType)
[CLSCompliant(false)]
public void Emit(OpCode opcode, sbyte arg) => Emit(opcode, (byte)arg);

/// <summary>
/// Marks a sequence point in the Microsoft intermediate language (MSIL) stream.
/// </summary>
/// <param name="document">The document for which the sequence point is being defined.</param>
/// <param name="startLine">The line where the sequence point begins.</param>
/// <param name="startColumn">The column in the line where the sequence point begins.</param>
/// <param name="endLine">The line where the sequence point ends.</param>
/// <param name="endColumn">The column in the line where the sequence point ends.</param>
/// <exception cref="ArgumentNullException"><paramref name="document"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="document"/> is not valid.</exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="startLine"/> is not within range [0, 0x20000000) or
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did these max values come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the runtime doc

The values of non-hidden sequence point must satisfy the following constraints
* IL Offset is within range [0, 0x20000000)
* IL Offset of a sequence point is lesser than IL Offset of the subsequent sequence point.
* Start Line is within range [0, 0x20000000) and not equal to 0xfeefee.
* End Line is within range [0, 0x20000000) and not equal to 0xfeefee.
* Start Column is within range [0, 0x10000)
* End Column is within range [0, 0x10000)
* End Line is greater or equal to Start Line.
* If Start Line is equal to End Line then End Column is greater than Start Column.

/// <paramref name="endLine"/> is not within range [0, 0x20000000) or lower than <paramref name="startLine"/> or
/// <paramref name="startColumn"/> is not within range [0, 0x10000) or
/// <paramref name="endLine"/> is not within range [0, 0x10000) or
/// <paramref name="startLine"/> equal to <paramref name="endLine"/> and it is not hidden sequence point and <paramref name="endLine"/> lower than or equal to <paramref name="startLine"/>.
/// </exception>
/// <exception cref="NotSupportedException">Emitting debug info is not supported.</exception>"
public void MarkSequencePoint(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn)
{
ArgumentNullException.ThrowIfNull(document);

if (startLine < 0 || startLine >= 0x20000000)
{
throw new ArgumentOutOfRangeException(nameof(startLine));
}

if (endLine < 0 || endLine >= 0x20000000 || startLine > endLine)
{
throw new ArgumentOutOfRangeException(nameof(endLine));
}

if (startColumn < 0 || startColumn >= 0x10000)
{
throw new ArgumentOutOfRangeException(nameof(startColumn));
}

if (endColumn < 0 || endColumn >= 0x10000 ||
(startLine == endLine && startLine != 0xfeefee && startColumn >= endColumn))
AaronRobinsonMSFT marked this conversation as resolved.
Show resolved Hide resolved
{
throw new ArgumentOutOfRangeException(nameof(endColumn));
}

MarkSequencePointCore(document, startLine, startColumn, endLine, endColumn);
}

/// <summary>
/// When overridden in a derived class, marks a sequence point in the Microsoft intermediate language (MSIL) stream.
/// </summary>
/// <param name="document">The document for which the sequence point is being defined.</param>
/// <param name="startLine">The line where the sequence point begins.</param>
/// <param name="startColumn">The column in the line where the sequence point begins.</param>
/// <param name="endLine">The line where the sequence point ends.</param>
/// <param name="endColumn">The column in the line where the sequence point ends.</param>
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
/// <exception cref="ArgumentException"><paramref name="document"/> is not valid.</exception>
/// <exception cref="NotSupportedException">Emitting debug info is not supported.</exception>"
/// <remarks>The parameters validated in the caller: <see cref="MarkSequencePoint"/>.</remarks>
protected virtual void MarkSequencePointCore(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) =>
throw new NotSupportedException(SR.NotSupported_EmitDebugInfo);

#endregion

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,27 @@ public abstract class LocalBuilder : LocalVariableInfo
/// This constructor is invoked by derived classes.
/// </remarks>
protected LocalBuilder() { }

/// <summary>
/// Sets the name of this local variable.
/// </summary>
/// <param name="name">The name of the local variable</param>
/// <exception cref="ArgumentNullException">The <paramref name="name"/> is null.</exception>
/// <exception cref="InvalidOperationException">The containing type has been created with CreateType() or
/// containing type doesn't support symbol writing.</exception>"
public void SetLocalSymInfo(string name)
{
ArgumentNullException.ThrowIfNull(name);

SetLocalSymInfoCore(name);
}

/// <summary>
/// When overridden in a derived class, sets the name of this local variable.
/// </summary>
/// <param name="name">The name of the local variable.</param>
/// <exception cref="NotSupportedException">Emitting debug info is not supported.</exception>"
/// <exception cref="InvalidOperationException">The containing type has been created with CreateType().</exception>"
protected virtual void SetLocalSymInfoCore(string name) => throw new NotSupportedException(SR.NotSupported_EmitDebugInfo);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.SymbolStore;
using System.Runtime.InteropServices;

namespace System.Reflection.Emit
Expand All @@ -24,6 +26,45 @@ public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type under
return DefineEnumCore(name, visibility, underlyingType);
}

/// <summary>
/// Defines a document for source.
/// </summary>
/// <param name="url">The URL for the document.</param>
/// <param name="language">The GUID that identifies the document language. This can be Empty</param>
/// <param name="languageVendor">The GUID that identifies the document language vendor. This is not used.</param>
/// <param name="documentType">The GUID that identifies the document language vendor. This is not used.</param>
/// <returns>The defined document.</returns>
/// <exception cref="ArgumentNullException"><paramref name="url"/> is <see langword="null"/>.</exception>
/// <exception cref="InvalidOperationException">This method is called on a dynamic module that is not a persisted module.</exception>
[EditorBrowsable(EditorBrowsableState.Never)]
public ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType) =>
DefineDocument(url, language);

/// <summary>
/// Defines a document for source.
/// </summary>
/// <param name="url">The URL for the document.</param>
/// <param name="language">The GUID that identifies the document language. This is optional</param>
/// <returns>The defined document.</returns>
/// <exception cref="ArgumentNullException"><paramref name="url"/> is <see langword="null"/>.</exception>
/// <exception cref="InvalidOperationException">This method is called on a dynamic module that is not a persisted module.</exception>
public ISymbolDocumentWriter DefineDocument(string url, Guid language = default)
{
ArgumentException.ThrowIfNullOrEmpty(url);

return DefineDocumentCore(url, language);
}

/// <summary>
/// When override in a derived class, defines a document for source.
/// </summary>
/// <param name="url">The URL for the document.</param>
/// <param name="language">The GUID that identifies the document language. This is optional</param>
/// <returns>The defined document.</returns>
/// <exception cref="InvalidOperationException">This method is called on a dynamic module that is not a debug module.</exception>
protected virtual ISymbolDocumentWriter DefineDocumentCore(string url, Guid language = default) =>
throw new InvalidOperationException(SR.InvalidOperation_NotADebugModule);

protected abstract EnumBuilder DefineEnumCore(string name, TypeAttributes visibility, Type underlyingType);

public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type? returnType, Type[]? parameterTypes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public virtual void EmitWriteLine(string value) { }
public abstract void EndExceptionBlock();
public abstract void EndScope();
public abstract void MarkLabel(System.Reflection.Emit.Label loc);
public void MarkSequencePoint(System.Diagnostics.SymbolStore.ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) { throw null; }
protected virtual void MarkSequencePointCore(System.Diagnostics.SymbolStore.ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) { throw null; }
public virtual void ThrowException([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] System.Type excType) { }
public abstract void UsingNamespace(string usingNamespace);
}
Expand All @@ -73,6 +75,8 @@ protected LocalBuilder() { }
public override bool IsPinned { get { throw null; } }
public override int LocalIndex { get { throw null; } }
public override System.Type LocalType { get { throw null; } }
public void SetLocalSymInfo(string name) { throw null; }
protected virtual void SetLocalSymInfoCore(string name) { throw null; }
}
public abstract partial class ParameterBuilder
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
<ProjectReference Include="..\..\System.Runtime.InteropServices\ref\System.Runtime.InteropServices.csproj" />
<ProjectReference Include="..\..\System.Reflection.Primitives\ref\System.Reflection.Primitives.csproj" />
<ProjectReference Include="..\..\System.Diagnostics.StackTrace\ref\System.Diagnostics.StackTrace.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,10 @@ protected ModuleBuilder() { }
public override string ScopeName { get { throw null; } }
public void CreateGlobalFunctions() { }
protected abstract void CreateGlobalFunctionsCore();
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public System.Diagnostics.SymbolStore.ISymbolDocumentWriter DefineDocument(string url, Guid language, Guid languageVendor, Guid documentType) { throw null; }
public System.Diagnostics.SymbolStore.ISymbolDocumentWriter DefineDocument(string url, System.Guid language = default) { throw null; }
protected virtual System.Diagnostics.SymbolStore.ISymbolDocumentWriter DefineDocumentCore(string url, System.Guid language = default) { throw null; }
public System.Reflection.Emit.EnumBuilder DefineEnum(string name, System.Reflection.TypeAttributes visibility, System.Type underlyingType) { throw null; }
protected abstract System.Reflection.Emit.EnumBuilder DefineEnumCore(string name, System.Reflection.TypeAttributes visibility, System.Type underlyingType);
public System.Reflection.Emit.MethodBuilder DefineGlobalMethod(string name, System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type? returnType, System.Type[]? parameterTypes) { throw null; }
Expand Down Expand Up @@ -479,9 +483,11 @@ public PersistedAssemblyBuilder(System.Reflection.AssemblyName name, System.Refl
public override System.Reflection.Module ManifestModule { get { throw null; } }
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Defining a dynamic assembly requires dynamic code.")]
protected override System.Reflection.Emit.ModuleBuilder DefineDynamicModuleCore(string name) { throw null; }
protected override System.Reflection.Emit.ModuleBuilder? GetDynamicModuleCore(string name) { throw null; }
[System.CLSCompliantAttribute(false)]
public System.Reflection.Metadata.Ecma335.MetadataBuilder GenerateMetadata(out System.Reflection.Metadata.BlobBuilder ilStream, out System.Reflection.Metadata.BlobBuilder mappedFieldData) { throw null; }
[System.CLSCompliantAttribute(false)]
public System.Reflection.Metadata.Ecma335.MetadataBuilder GenerateMetadata(out System.Reflection.Metadata.BlobBuilder ilStream, out System.Reflection.Metadata.BlobBuilder mappedFieldData, out System.Reflection.Metadata.Ecma335.MetadataBuilder pdbBuilder) { throw null; }
protected override System.Reflection.Emit.ModuleBuilder? GetDynamicModuleCore(string name) { throw null; }
public override System.Reflection.AssemblyName GetName(bool copiedName) { throw null; }
public void Save(string assemblyFileName) { throw null; }
public void Save(System.IO.Stream stream) { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
<ProjectReference Include="..\..\System.Reflection.Primitives\ref\System.Reflection.Primitives.csproj" />
<ProjectReference Include="..\..\System.Reflection.Emit.ILGeneration\ref\System.Reflection.Emit.ILGeneration.csproj" />
<ProjectReference Include="..\..\System.Reflection.Metadata\ref\System.Reflection.Metadata.csproj" />
<ProjectReference Include="..\..\System.Diagnostics.StackTrace\ref\System.Diagnostics.StackTrace.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -297,4 +297,10 @@
<data name="NotSupported_SymbolMethod" xml:space="preserve">
<value>Not supported in an array method of a type definition that is not complete.</value>
</data>
<data name="InvalidOperation_InvalidDocument" xml:space="preserve">
<value>Invalid source document.</value>
</data>
<data name="InvalidOperation_UnmatchingSymScope" xml:space="preserve">
<value>Unmatching symbol scope.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
<Compile Include="System\Reflection\Emit\MethodBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\ModuleBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\ParameterBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\Pdb\SequencePoint.cs" />
<Compile Include="System\Reflection\Emit\Pdb\SymbolDocumentWriter.cs" />
<Compile Include="System\Reflection\Emit\PersistedAssemblyBuilder.cs" />
<Compile Include="System\Reflection\Emit\PropertyBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\PseudoCustomAttributesData.cs" />
Expand Down
Loading
Loading