dotnet / diagnostics

This repository contains the source code for various .NET Core runtime diagnostic tools and documents.
MIT License
1.18k stars 354 forks source link

dotnet-dump does not always put PDB info regions into cordumps #708

Closed leculver closed 4 years ago

leculver commented 4 years ago

@mikem8361: We had a bug report in ClrMD where PDB information couldn't be obtained from coredumps generated through dotnet-dump. This is https://github.com/microsoft/clrmd/issues/434.

The underlying issue is that the sections containing PDB info are not placed into coredumps. This may not be a bug...I mostly wanted you all to investigate and decide which of these you want to to be true...either of the following are acceptable resolutions to this issue, as long as it's intentional:

  1. The region of memory containing PDB info is always placed in coredumps, so we should fix dotnet-dump in v.next to ensure we always place the region into the dump.
  2. The region of memory containing PDB info is not guaranteed to be placed into coredumps, so we expect the user must have a copy of the PEImage locally (or on the symbol server) to get file/line information in diagnostic scenarios.

This code in ClrMD 2.0 should be a good test of whether it works:

using DataTarget dt = DataTarget.LoadCoreDump("/path/to/dmp");
using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();

foreach (ClrModule module in runtime.EnumerateModules())
    if (module.Pdb == null)
        Console.WriteLine($"No PDB information for ClrModule {module.FileName}");
mikem8361 commented 4 years ago

Can I get a sample core dump or a simple repro (app to collect)?

leculver commented 4 years ago

I will share coredumps offline, but I would imagine you need a repro to test this. Here's full repro steps.

Program:

using System;
using System.Linq;
using Microsoft.Diagnostics.Runtime;

class Program
{
    public static void Main(string[] args)
    {
        using DataTarget dt = DataTarget.LoadCoreDump(args[0]);
        using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();

        foreach (ClrModule module in runtime.EnumerateModules())
            if (module.Pdb == null)
                Console.WriteLine($"No PDB information for ClrModule {module.FileName}");
    }
}

Full repro steps from scratch:

git clone https://github.com/microsoft/clrmd.git
cd clrmd
./build.sh
cd ..
mkdir TestPdb
cd TestPdb
dotnet add reference ../clrmd/src/Microsoft.Diagnostics.Runtime/Microsoft.Diagnostics.Runtime.csproj
cat > Program.cs [paste the program above]
dotnet build
dotnet run ../clrmd/src/TestTargets/bin/x64/Types_wks.dmp

Output will be:

No PDB information for ClrModule /home/leculver/clrmd/src/TestTargets/bin/x64/Types.dll
No PDB information for ClrModule /home/leculver/clrmd/src/TestTargets/bin/x64/SharedLibrary.dll
leculver commented 4 years ago

Note that "./build.sh" above is what's generating the coredumps. See clrmd/src/TestTargets/TestTargets.proj.

mikem8361 commented 4 years ago

This turns out that the PDB/debug directory info is in the core dump, but the Types.dll and ShardLibrary.dll assemblies are "file" layout and the rest of the assemblies are "loaded" layout. This means the "isVirtual" parameter to the PEImage constructor in the DesktopModule.Pdb property needs to be false for Types.dll, etc and "true" for all the other assemblies. I don't know how to figure out the layout (yet). There are SOS DAC api's to get the layout but I need to investigate.

mikem8361 commented 4 years ago

@leculver there is also a bug here where "data.ImageBase" should be passed to GetModuleSize instead of "address". This is causing the "Size" property to always be zero.

leculver commented 4 years ago

Ahh much appreciated for the investigation! I'm going to go ahead and close this since I think this is all resolved. I think NextTurn is wrapping this up in https://github.com/microsoft/clrmd/pull/442, and I'll take care of the ImageBase/Size issue today.