Skip to content

Commit

Permalink
Generate debug info even if managed debug info not present (#87251)
Browse files Browse the repository at this point in the history
The names/types of parameters are available even without a PDB in .NET - surface them to the native debugger.

We could also surface fake information about locals because the type information is there (just no names/compiler generated bit), but it's unclear if that would be an improvement.
  • Loading branch information
MichalStrehovsky authored Jun 9, 2023
1 parent 9bcf523 commit aaffd8b
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1343,12 +1343,11 @@ private static void ProbeScopeForLocals(List<ILLocalVariable> variables, ISymUnm
// and names for all of them. This assumes a CSC-like compiler that doesn't re-use
// local slots in the same method across scopes.
//
public override IEnumerable<ILLocalVariable>? GetLocalVariableNamesForMethod(int methodToken)
public override IEnumerable<ILLocalVariable> GetLocalVariableNamesForMethod(int methodToken)
{
ISymUnmanagedMethod? symbolMethod;
if (_symUnmanagedReader.GetMethod(methodToken, out symbolMethod) < 0 || symbolMethod is null)
return null;
Debug.Assert(symbolMethod is not null);
return Array.Empty<ILLocalVariable>();

ISymUnmanagedScope rootScope;
ThrowExceptionForHR(symbolMethod.GetRootScope(out rootScope));
Expand Down
32 changes: 20 additions & 12 deletions src/coreclr/tools/Common/TypeSystem/IL/EcmaMethodIL.Symbols.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,21 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;

using Internal.TypeSystem.Ecma;

using Debug = System.Diagnostics.Debug;

namespace Internal.IL
{
// Pluggable file that adds PDB handling functionality to EcmaMethodIL
public partial class EcmaMethodIL
{
public override MethodDebugInformation GetDebugInfo()
{
if (_method.Module.PdbReader != null)
{
return new EcmaMethodDebugInformation(_method);
}

return MethodDebugInformation.None;
return new EcmaMethodDebugInformation(_method);
}
}

Expand All @@ -34,20 +28,34 @@ public sealed class EcmaMethodDebugInformation : MethodDebugInformation

public EcmaMethodDebugInformation(EcmaMethod method)
{
Debug.Assert(method.Module.PdbReader != null);
_method = method;
}

public override bool IsStateMachineMoveNextMethod => _method.Module.PdbReader.GetStateMachineKickoffMethod(MetadataTokens.GetToken(_method.Handle)) != 0;
public override bool IsStateMachineMoveNextMethod
{
get
{
PdbSymbolReader reader = _method.Module.PdbReader;
return reader != null
? reader.GetStateMachineKickoffMethod(MetadataTokens.GetToken(_method.Handle)) != 0
: false;
}
}

public override IEnumerable<ILSequencePoint> GetSequencePoints()
{
return _method.Module.PdbReader.GetSequencePointsForMethod(MetadataTokens.GetToken(_method.Handle));
PdbSymbolReader reader = _method.Module.PdbReader;
return reader != null
? reader.GetSequencePointsForMethod(MetadataTokens.GetToken(_method.Handle))
: Array.Empty<ILSequencePoint>();
}

public override IEnumerable<ILLocalVariable> GetLocalVariables()
{
return _method.Module.PdbReader.GetLocalVariableNamesForMethod(MetadataTokens.GetToken(_method.Handle));
PdbSymbolReader reader = _method.Module.PdbReader;
return reader != null
? reader.GetLocalVariableNamesForMethod(MetadataTokens.GetToken(_method.Handle))
: Array.Empty<ILLocalVariable>();
}

public override IEnumerable<string> GetParameterNames()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,12 @@ public static void EmitObject(string objectFilePath, IReadOnlyCollection<Depende
// Emit the last CFI to close the frame.
objectWriter.EmitCFICodes(nodeContents.Data.Length);

if (objectWriter.HasFunctionDebugInfo())
// Generate debug info if we have sequence points, or on Windows, we can also
// generate even if no sequence points.
bool generateDebugInfo = objectWriter.HasFunctionDebugInfo();
generateDebugInfo |= factory.Target.IsWindows && objectWriter.HasModuleDebugInfo();

if (generateDebugInfo)
{
objectWriter.EmitDebugVarInfo(node);
objectWriter.EmitDebugEHClauseInfo(node);
Expand Down

0 comments on commit aaffd8b

Please sign in to comment.