Skip to content

Commit

Permalink
Alternative method of getting IL to source mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
mattwarren committed Apr 17, 2015
1 parent ffc33d9 commit 16519ff
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 17 deletions.
24 changes: 11 additions & 13 deletions Microsoft.Diagnostics.Runtime/CLRMD/ClrMemDiag/Desktop/modules.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions;
using Address = System.UInt64;
using System.Text;
using System.Collections;
using System.IO;
using System.Reflection;
using Microsoft.Diagnostics.Runtime;
using System.Runtime.InteropServices;
using Microsoft.Diagnostics.Runtime.Utilities;
using Dia2Lib;

namespace Microsoft.Diagnostics.Runtime.Desktop
{
abstract class DesktopBaseModule : ClrModule
public abstract class DesktopBaseModule : ClrModule
{
internal abstract Address GetDomainModule(ClrAppDomain appDomain);

Expand All @@ -28,7 +23,7 @@ internal virtual IMetadata GetMetadataImport()
public int Revision { get; set; }
}

class DesktopModule : DesktopBaseModule
public class DesktopModule : DesktopBaseModule
{
bool m_reflection, m_isPE;
string m_name, m_assemblyName;
Expand All @@ -45,7 +40,6 @@ class DesktopModule : DesktopBaseModule
SymbolModule m_symbols;
PEFile m_peFile;


public override SourceLocation GetSourceInformation(ClrMethod method, int ilOffset)
{
if (method == null)
Expand All @@ -65,6 +59,14 @@ public override SourceLocation GetSourceInformation(uint token, int ilOffset)
return m_symbols.SourceLocationForManagedCode(token, ilOffset);
}

public IList<ILOffsetSourceLocation> GetSourceLocationsForMethod(uint token)
{
if (m_symbols == null)
return null;

return m_symbols.SourceLocationsForMethod(token);
}

public override bool IsPdbLoaded { get { return m_symbols != null; } }

public override bool IsMatchingPdb(string pdbPath)
Expand All @@ -90,7 +92,6 @@ public override void LoadPdb(string path)
m_symbols = new SymbolModule(m_runtime.DataTarget.SymbolReader, path);
}


public override object PdbInterface
{
get
Expand Down Expand Up @@ -124,8 +125,7 @@ public override string TryDownloadPdb(ISymbolNotification notification)
return reader.FindSymbolFilePath(pdbName, pdbGuid, rev, notification);
}


public DesktopModule(DesktopRuntimeBase runtime, ulong address, IModuleData data, string name, string assemblyName, ulong size)
internal DesktopModule(DesktopRuntimeBase runtime, ulong address, IModuleData data, string name, string assemblyName, ulong size)
{
Revision = runtime.Revision;
m_imageBase = data.ImageBase;
Expand Down Expand Up @@ -176,8 +176,6 @@ public override IEnumerable<ClrType> EnumerateTypes()

m_typesLoaded = true;
}


}

public override string AssemblyName
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel; // For Win32Excption;
using System.Diagnostics;
Expand Down Expand Up @@ -1128,7 +1129,6 @@ public IDiaSession Session
}
}


/// <summary>
/// Finds a (method) symbolic name for a given relative virtual address of some code.
/// Returns an empty string if a name could not be found.
Expand Down Expand Up @@ -1158,7 +1158,7 @@ public string FindNameForRva(uint rva)
// TODO FIX NOW, should not need to do this hand-unmangling.
if (ret.Contains("@"))
{
// TODO relativel inefficient.
// TODO relatively inefficient.
string unmangled = null;
symbol.get_undecoratedNameEx(0x1000, out unmangled);
if (unmangled != null)
Expand Down Expand Up @@ -1209,6 +1209,7 @@ public SourceLocation SourceLocationForRva(uint rva)
var sourceLocation = new SourceLocation(sourceLoc);
return sourceLocation;
}

/// <summary>
/// Managed code is shipped as IL, so RVA to NATIVE mapping can't be placed in the PDB. Instead
/// what is placed in the PDB is a mapping from a method's meta-data token and IL offset to source
Expand Down Expand Up @@ -1270,12 +1271,45 @@ public SourceLocation SourceLocationForManagedCode(uint methodMetaDataToken, int
var sourceLocation = new SourceLocation(sourceLoc);
return sourceLocation;
}

/// <summary>
/// Get the full list of SourceLocations (with corresponding ILOffset) for the given method
/// Based on the commented out code from "SourceLocationForManagedCode(uint methodMetaDataToken, int ilOffset)"
/// </summary>
public IList<ILOffsetSourceLocation> SourceLocationsForMethod(uint methodMetaDataToken)
{
//m_reader.m_log.WriteLine("SourceLocationForManagedCode: Looking up method token {0:x}", methodMetaDataToken);

IDiaSymbol methodSym;
m_session.findSymbolByToken(methodMetaDataToken, SymTagEnum.SymTagFunction, out methodSym);
if (methodSym == null)
{
m_reader.m_log.WriteLine("SourceLocationForManagedCode: No symbol for token {0:x}", methodMetaDataToken);
return null;
}

IDiaEnumLineNumbers sourceLocs;
IList<ILOffsetSourceLocation> sourceLocations = new List<ILOffsetSourceLocation>();
m_session.findLinesByRVA(methodSym.relativeVirtualAddress, 256, out sourceLocs);
for (int i = 0; ; i++)
{
IDiaLineNumber sourceLoc;
uint fetchCount;
sourceLocs.Next(1, out sourceLoc, out fetchCount);
if (fetchCount == 0)
break;
uint ilOffset = sourceLoc.relativeVirtualAddress - methodSym.relativeVirtualAddress;
sourceLocations.Add(new ILOffsetSourceLocation(ilOffset, new SourceLocation(sourceLoc)));
}

return sourceLocations;
}

/// <summary>
/// Returns a list of all source files referenced in the PDB
/// </summary>
public IEnumerable<SourceFile> AllSourceFiles()
{

IDiaEnumTables tables;
m_session.getEnumTables(out tables);

Expand Down Expand Up @@ -1308,6 +1342,7 @@ public IEnumerable<SourceFile> AllSourceFiles()
/// The a unique identifier that is used to relate the DLL and its PDB.
/// </summary>
public Guid PdbGuid { get { return m_session.globalScope.guid; } }

/// <summary>
/// Along with the PdbGuid, there is a small integer
/// call the age is also used to find the PDB (it represents the differnet
Expand Down
20 changes: 20 additions & 0 deletions Microsoft.Diagnostics.Runtime/CLRMD/ClrMemDiag/public.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1538,6 +1538,24 @@ internal SourceLocation(IDiaLineNumber source)
#endregion
}

/// <summary>
/// Contains the mapping of IL Offset -> Source Location
/// </summary>
public class ILOffsetSourceLocation
{
private readonly uint ilOffset;
public uint ILOffset { get { return ilOffset; } }

private readonly SourceLocation sourceLocation;
public SourceLocation SourceLocation { get { return sourceLocation; } }

internal ILOffsetSourceLocation(uint ilOffset, SourceLocation sourceLocation)
{
this.ilOffset = ilOffset;
this.sourceLocation = sourceLocation;
}
}

/// <summary>
/// Defines the state of the thread from the runtime's perspective.
/// </summary>
Expand Down Expand Up @@ -2841,7 +2859,9 @@ internal SymbolReader SymbolReader
get
{
if (m_symbolReader == null)
{
m_symbolReader = new SymbolReader(TextWriter.Null, m_symPath);
}

return m_symbolReader;
}
Expand Down
39 changes: 38 additions & 1 deletion Microsoft.Diagnostics.Runtime/CLRMD/MachineCode/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ static void Main(string[] args)
File.ReadAllLines(
@"C:\Users\warma11\Documents\Visual Studio 2013\Projects\JITterOptimisations\JITterOptimisations\Program.cs");

PrintILToNativeOffsets(method, startAddress, lines);
PrintILToNativeOffsetAlternative(method, lines);

// This doesn't seem to work as expected, using alternative method (above)
//PrintILToNativeOffsets(method, startAddress, lines);

// This is what we expect it to be
//--- c:\Users\warma11\Documents\Visual Studio 2013\Projects\JITterOptimisations\JITterOptimisations\Program.cs
Expand Down Expand Up @@ -131,6 +134,40 @@ static void Main(string[] args)
}
}

private static void PrintILToNativeOffsetAlternative(ClrMethod method, string[] lines)
{
DesktopModule module = (DesktopModule) @method.Type.Module;
if (!module.IsPdbLoaded)
{
// Have to load the Pdb, if it's not already loaded!!
string val = module.TryDownloadPdb(null);
if (val != null)
module.LoadPdb(val);
}

foreach (var location in module.GetSourceLocationsForMethod(@method.MetadataToken))
{
ILOffsetSourceLocation ILLocation = location;
var ilMaps = @method.ILOffsetMap.Where(il => il.ILOffset == ILLocation.ILOffset);
Console.WriteLine("{0:X8} -> {1}:{2}",
location.ILOffset,
Path.GetFileName(location.SourceLocation.FilePath),
location.SourceLocation.LineNumber);
Console.WriteLine(" " + String.Join("\n ",
ilMaps.Select(
ilMap =>
String.Format("[{0:X8}-{1:X8} ({2:X8}-{3:X8})] ILOffset: {4:X2}",
ilMap.StartAddress - @method.NativeCode,
ilMap.EndAddress - @method.NativeCode,
ilMap.StartAddress, ilMap.EndAddress, ilMap.ILOffset))));
var indent = 7;
Console.WriteLine("{0,6}:{1}", location.SourceLocation.LineNumber, lines[location.SourceLocation.LineNumber - 1]);
Console.WriteLine(new string(' ', location.SourceLocation.ColStart - 1 + indent) +
new string('*', location.SourceLocation.ColEnd - location.SourceLocation.ColStart));
}
Console.WriteLine();
}

private static void PrintILToNativeOffsets(ClrMethod method, ulong startAddress, string[] lines)
{
Console.WriteLine("IL -> Native Offsets:");
Expand Down

0 comments on commit 16519ff

Please sign in to comment.