dotnet / sourcelink

Source Link enables a great source debugging experience for your users, by adding source control metadata to your built assets
MIT License
1.26k stars 122 forks source link

Can sourcelink support debugging through internal code and abstract implementations? #1221

Open MichaCo opened 7 months ago

MichaCo commented 7 months ago

Is there a way to enable/support debugging and stepping through internal code in sourcelink?

As an example, the actual implementation of the shared array pool is in an internal class. F12 into SharedArrayPool does nothing though.

image

Debugging and stepping into ArrayPool<byte>.Shared.Rent(1000); also does not work and the debugger just steps over Rent(..) as this is an abstract method.

Thanks

MichaCo commented 7 months ago

Never mind, I had "Enable Just My Code" on in VS, without that debugging into those code paths kinda works. I can debug into the Rent implementation. Anything which goes one step further down into the next level of internal implementations does not work though, e.g.

F12 into Utilities.SelectBucketIndex shows an error message and doesn't work image

Although the code is in the same library: https://github.com/dotnet/runtime/blob/4468342c374c7889742c7392c8a1713161bd24ff/src/libraries/System.Private.CoreLib/src/System/Buffers/Utilities.cs#L13

KalleOlaviNiemitalo commented 7 months ago

This seems more a debugger issue. Source Link lets the debugger know how to download the source files referenced by the PDB, but it does not comment on how the debugger should parse the files. For that, the debugger should use the other information in the portable PDB.

I get the impression that, if the debugger supports the programming language of the source files, then it could use the PDB for F12 to find the source code of a method definition:

  1. Parse the source code to figure out what the caller method is. This might be complicated by C# #line directives, though.
  2. Use the MethodDebugInformation table to locate the approximate IL offset of the call.
  3. Use the LocalScope and ImportScope tables to collect any assemblies, namespaces, or extension methods visible from there (including global import).
  4. Combine those with metadata from the referenced assemblies, to figure out which method is called.
  5. Use the MethodDebugInformation table to locate the source code of the called method.

However, F12 finding the source code of a type definition looks harder, because types do not have sequence points, and the specification of the CustomDebugInformation table doesn't mention anything that could be used for navigating from a TypeDef to a Document.