diff options
Diffstat (limited to 'src/ToolBox/SOS/NETCore')
-rw-r--r-- | src/ToolBox/SOS/NETCore/SymbolReader.cs | 97 | ||||
-rw-r--r-- | src/ToolBox/SOS/NETCore/project.json | 2 |
2 files changed, 84 insertions, 15 deletions
diff --git a/src/ToolBox/SOS/NETCore/SymbolReader.cs b/src/ToolBox/SOS/NETCore/SymbolReader.cs index f4a3ce30d8..492f7cbd1f 100644 --- a/src/ToolBox/SOS/NETCore/SymbolReader.cs +++ b/src/ToolBox/SOS/NETCore/SymbolReader.cs @@ -28,13 +28,16 @@ namespace SOS { public IntPtr points; public int size; + public IntPtr locals; + public int localsSize; + } /// <summary> /// Read memory callback /// </summary> /// <returns>number of bytes read or 0 for error</returns> - internal unsafe delegate int ReadMemoryDelegate(IntPtr address, byte* buffer, int count); + internal unsafe delegate int ReadMemoryDelegate(ulong address, byte* buffer, int count); private sealed class OpenedReader : IDisposable { @@ -58,7 +61,7 @@ namespace SOS /// </summary> private class TargetStream : Stream { - readonly IntPtr _address; + readonly ulong _address; readonly ReadMemoryDelegate _readMemory; public override long Position { get; set; } @@ -67,7 +70,7 @@ namespace SOS public override bool CanRead { get { return true; } } public override bool CanWrite { get { return false; } } - public TargetStream(IntPtr address, int size, ReadMemoryDelegate readMemory) + public TargetStream(ulong address, int size, ReadMemoryDelegate readMemory) : base() { _address = address; @@ -86,7 +89,7 @@ namespace SOS { fixed (byte* p = &buffer[offset]) { - int read = _readMemory(new IntPtr(_address.ToInt64() + Position), p, count); + int read = _readMemory(_address + (ulong)Position, p, count); Position += read; return read; } @@ -126,6 +129,19 @@ namespace SOS } /// <summary> + /// Quick fix for Path.GetFileName which incorrectly handles Windows-style paths on Linux + /// </summary> + /// <param name="pathName"> File path to be processed </param> + /// <returns>Last component of path</returns> + private static string GetFileName(string pathName) + { + int pos = pathName.LastIndexOfAny(new char[] { '/', '\\'}); + if (pos < 0) + return pathName; + return pathName.Substring(pos + 1); + } + + /// <summary> /// Checks availability of debugging information for given assembly. /// </summary> /// <param name="assemblyPath"> @@ -141,18 +157,18 @@ namespace SOS /// <param name="inMemoryPdbAddress">in memory PDB address or zero</param> /// <param name="inMemoryPdbSize">in memory PDB size</param> /// <returns>Symbol reader handle or zero if error</returns> - internal static IntPtr LoadSymbolsForModule(string assemblyPath, bool isFileLayout, IntPtr loadedPeAddress, int loadedPeSize, - IntPtr inMemoryPdbAddress, int inMemoryPdbSize, ReadMemoryDelegate readMemory) + internal static IntPtr LoadSymbolsForModule(string assemblyPath, bool isFileLayout, ulong loadedPeAddress, int loadedPeSize, + ulong inMemoryPdbAddress, int inMemoryPdbSize, ReadMemoryDelegate readMemory) { try { TargetStream peStream = null; - if (assemblyPath == null && loadedPeAddress != IntPtr.Zero) + if (assemblyPath == null && loadedPeAddress != 0) { peStream = new TargetStream(loadedPeAddress, loadedPeSize, readMemory); } TargetStream pdbStream = null; - if (inMemoryPdbAddress != IntPtr.Zero) + if (inMemoryPdbAddress != 0) { pdbStream = new TargetStream(inMemoryPdbAddress, inMemoryPdbSize, readMemory); } @@ -207,7 +223,7 @@ namespace SOS try { - string fileName = Path.GetFileName(filePath); + string fileName = GetFileName(filePath); foreach (MethodDebugInformationHandle methodDebugInformationHandle in reader.MethodDebugInformation) { MethodDebugInformation methodDebugInfo = reader.GetMethodDebugInformation(methodDebugInformationHandle); @@ -215,7 +231,7 @@ namespace SOS foreach (SequencePoint point in sequencePoints) { string sourceName = reader.GetString(reader.GetDocument(point.Document).Name); - if (point.StartLine == lineNumber && Path.GetFileName(sourceName) == fileName) + if (point.StartLine == lineNumber && GetFileName(sourceName) == fileName) { methodToken = MetadataTokens.GetToken(methodDebugInformationHandle.ToDefinitionHandle()); ilOffset = point.Offset; @@ -378,7 +394,48 @@ namespace SOS } return false; } + internal static bool GetLocalsInfoForMethod(string assemblyPath, int methodToken, out List<string> locals) + { + locals = null; + + OpenedReader openedReader = GetReader(assemblyPath, isFileLayout: true, peStream: null, pdbStream: null); + if (openedReader == null) + return false; + + using (openedReader) + { + try + { + Handle handle = MetadataTokens.Handle(methodToken); + if (handle.Kind != HandleKind.MethodDefinition) + return false; + + locals = new List<string>(); + MethodDebugInformationHandle methodDebugHandle = + ((MethodDefinitionHandle)handle).ToDebugInformationHandle(); + LocalScopeHandleCollection localScopes = openedReader.Reader.GetLocalScopes(methodDebugHandle); + foreach (LocalScopeHandle scopeHandle in localScopes) + { + LocalScope scope = openedReader.Reader.GetLocalScope(scopeHandle); + LocalVariableHandleCollection localVars = scope.GetLocalVariables(); + foreach (LocalVariableHandle varHandle in localVars) + { + LocalVariable localVar = openedReader.Reader.GetLocalVariable(varHandle); + if (localVar.Attributes == LocalVariableAttributes.DebuggerHidden) + continue; + locals.Add(openedReader.Reader.GetString(localVar.Name)); + } + } + } + catch + { + return false; + } + } + return true; + + } /// <summary> /// Returns source name, line numbers and IL offsets for given method token. /// </summary> @@ -392,11 +449,17 @@ namespace SOS try { List<DebugInfo> points = null; + List<string> locals = null; if (!GetDebugInfoForMethod(assemblyPath, methodToken, out points)) { return false; } + + if (!GetLocalsInfoForMethod(assemblyPath, methodToken, out locals)) + { + return false; + } var structSize = Marshal.SizeOf<DebugInfo>(); debugInfo.size = points.Count; @@ -407,6 +470,14 @@ namespace SOS Marshal.StructureToPtr(info, ptr, false); ptr = (IntPtr)(ptr.ToInt64() + structSize); } + debugInfo.localsSize = locals.Count; + debugInfo.locals = Marshal.AllocHGlobal(debugInfo.localsSize * Marshal.SizeOf<IntPtr>()); + IntPtr ptrLocals = debugInfo.locals; + foreach (string s in locals) + { + Marshal.WriteIntPtr(ptrLocals, Marshal.StringToHGlobalUni(s)); + ptrLocals += Marshal.SizeOf<IntPtr>(); + } return true; } catch @@ -446,12 +517,10 @@ namespace SOS foreach (SequencePoint point in sequencePoints) { - if (point.StartLine == 0 || point.StartLine == SequencePoint.HiddenLine) - continue; DebugInfo debugInfo = new DebugInfo(); debugInfo.lineNumber = point.StartLine; - debugInfo.fileName = openedReader.Reader.GetString(openedReader.Reader.GetDocument(point.Document).Name); + debugInfo.fileName = GetFileName(openedReader.Reader.GetString(openedReader.Reader.GetDocument(point.Document).Name)); debugInfo.ilOffset = point.Offset; points.Add(debugInfo); } @@ -609,7 +678,7 @@ namespace SOS { try { - pdbPath = Path.Combine(Path.GetDirectoryName(assemblyPath), Path.GetFileName(pdbPath)); + pdbPath = Path.Combine(Path.GetDirectoryName(assemblyPath), GetFileName(pdbPath)); } catch { diff --git a/src/ToolBox/SOS/NETCore/project.json b/src/ToolBox/SOS/NETCore/project.json index e9e4f0999f..7a3cf4fe1d 100644 --- a/src/ToolBox/SOS/NETCore/project.json +++ b/src/ToolBox/SOS/NETCore/project.json @@ -3,7 +3,7 @@ "Microsoft.NETCore.Platforms": "1.0.1", "System.IO.FileSystem": "4.0.1", "System.Runtime.InteropServices": "4.1.0", - "System.Reflection.Metadata": "1.4.1-beta-24417-02" + "System.Reflection.Metadata": "1.4.1" }, "frameworks": { "netcoreapp1.0": {} |