Remove PortablePdbReader except trace cleanup (#19957)
* Remove PortablePdbReader except trace cleanup Co-authored-by: Rowse <ryan.rowse@jbtc.com>
This commit is contained in:
parent
56d50e677b
commit
ec10429430
|
|
@ -1,135 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Reflection.Metadata;
|
|
||||||
using System.Reflection.Metadata.Ecma335;
|
|
||||||
using System.Reflection.PortableExecutable;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.StackTrace.Sources
|
|
||||||
{
|
|
||||||
internal class PortablePdbReader : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Dictionary<string, MetadataReaderProvider> _cache =
|
|
||||||
new Dictionary<string, MetadataReaderProvider>(StringComparer.Ordinal);
|
|
||||||
|
|
||||||
public void PopulateStackFrame(StackFrameInfo frameInfo, MethodBase method, int IlOffset)
|
|
||||||
{
|
|
||||||
if (method.Module.Assembly.IsDynamic)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var metadataReader = GetMetadataReader(method.Module.Assembly.Location);
|
|
||||||
|
|
||||||
if (metadataReader == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var methodToken = MetadataTokens.Handle(method.MetadataToken);
|
|
||||||
|
|
||||||
Debug.Assert(methodToken.Kind == HandleKind.MethodDefinition);
|
|
||||||
|
|
||||||
var handle = ((MethodDefinitionHandle)methodToken).ToDebugInformationHandle();
|
|
||||||
|
|
||||||
if (!handle.IsNil)
|
|
||||||
{
|
|
||||||
var methodDebugInfo = metadataReader.GetMethodDebugInformation(handle);
|
|
||||||
var sequencePoints = methodDebugInfo.GetSequencePoints();
|
|
||||||
SequencePoint? bestPointSoFar = null;
|
|
||||||
|
|
||||||
foreach (var point in sequencePoints)
|
|
||||||
{
|
|
||||||
if (point.Offset > IlOffset)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (point.StartLine != SequencePoint.HiddenLine)
|
|
||||||
{
|
|
||||||
bestPointSoFar = point;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bestPointSoFar.HasValue)
|
|
||||||
{
|
|
||||||
frameInfo.LineNumber = bestPointSoFar.Value.StartLine;
|
|
||||||
frameInfo.FilePath = metadataReader.GetString(metadataReader.GetDocument(bestPointSoFar.Value.Document).Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MetadataReader GetMetadataReader(string assemblyPath)
|
|
||||||
{
|
|
||||||
MetadataReaderProvider provider = null;
|
|
||||||
if (!_cache.TryGetValue(assemblyPath, out provider))
|
|
||||||
{
|
|
||||||
var pdbPath = GetPdbPath(assemblyPath);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(pdbPath) && File.Exists(pdbPath) && IsPortable(pdbPath))
|
|
||||||
{
|
|
||||||
var pdbStream = File.OpenRead(pdbPath);
|
|
||||||
provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
_cache[assemblyPath] = provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
return provider?.GetMetadataReader();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetPdbPath(string assemblyPath)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(assemblyPath))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (File.Exists(assemblyPath))
|
|
||||||
{
|
|
||||||
var peStream = File.OpenRead(assemblyPath);
|
|
||||||
|
|
||||||
using (var peReader = new PEReader(peStream))
|
|
||||||
{
|
|
||||||
foreach (var entry in peReader.ReadDebugDirectory())
|
|
||||||
{
|
|
||||||
if (entry.Type == DebugDirectoryEntryType.CodeView)
|
|
||||||
{
|
|
||||||
var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry);
|
|
||||||
var peDirectory = Path.GetDirectoryName(assemblyPath);
|
|
||||||
return Path.Combine(peDirectory, Path.GetFileName(codeViewData.Path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsPortable(string pdbPath)
|
|
||||||
{
|
|
||||||
using (var pdbStream = File.OpenRead(pdbPath))
|
|
||||||
{
|
|
||||||
return pdbStream.ReadByte() == 'B' &&
|
|
||||||
pdbStream.ReadByte() == 'S' &&
|
|
||||||
pdbStream.ReadByte() == 'J' &&
|
|
||||||
pdbStream.ReadByte() == 'B';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
foreach (var entry in _cache)
|
|
||||||
{
|
|
||||||
entry.Value?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_cache.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -25,70 +25,48 @@ namespace Microsoft.Extensions.StackTrace.Sources
|
||||||
return frames;
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var portablePdbReader = new PortablePdbReader())
|
var needFileInfo = true;
|
||||||
|
var stackTrace = new System.Diagnostics.StackTrace(exception, needFileInfo);
|
||||||
|
var stackFrames = stackTrace.GetFrames();
|
||||||
|
|
||||||
|
if (stackFrames == null)
|
||||||
{
|
{
|
||||||
var needFileInfo = true;
|
|
||||||
var stackTrace = new System.Diagnostics.StackTrace(exception, needFileInfo);
|
|
||||||
var stackFrames = stackTrace.GetFrames();
|
|
||||||
|
|
||||||
if (stackFrames == null)
|
|
||||||
{
|
|
||||||
error = default;
|
|
||||||
return frames;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Exception> exceptions = null;
|
|
||||||
|
|
||||||
for (var i = 0; i < stackFrames.Length; i++)
|
|
||||||
{
|
|
||||||
var frame = stackFrames[i];
|
|
||||||
var method = frame.GetMethod();
|
|
||||||
|
|
||||||
// Always show last stackFrame
|
|
||||||
if (!ShowInStackTrace(method) && i < stackFrames.Length - 1)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var stackFrame = new StackFrameInfo
|
|
||||||
{
|
|
||||||
StackFrame = frame,
|
|
||||||
FilePath = frame.GetFileName(),
|
|
||||||
LineNumber = frame.GetFileLineNumber(),
|
|
||||||
MethodDisplayInfo = GetMethodDisplayString(frame.GetMethod()),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(stackFrame.FilePath))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// .NET Framework and older versions of mono don't support portable PDBs
|
|
||||||
// so we read it manually to get file name and line information
|
|
||||||
portablePdbReader.PopulateStackFrame(stackFrame, method, frame.GetILOffset());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (exceptions is null)
|
|
||||||
{
|
|
||||||
exceptions = new List<Exception>();
|
|
||||||
}
|
|
||||||
|
|
||||||
exceptions.Add(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
frames.Add(stackFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exceptions != null)
|
|
||||||
{
|
|
||||||
error = new AggregateException(exceptions);
|
|
||||||
return frames;
|
|
||||||
}
|
|
||||||
|
|
||||||
error = default;
|
error = default;
|
||||||
return frames;
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Exception> exceptions = null;
|
||||||
|
|
||||||
|
for (var i = 0; i < stackFrames.Length; i++)
|
||||||
|
{
|
||||||
|
var frame = stackFrames[i];
|
||||||
|
var method = frame.GetMethod();
|
||||||
|
|
||||||
|
// Always show last stackFrame
|
||||||
|
if (!ShowInStackTrace(method) && i < stackFrames.Length - 1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var stackFrame = new StackFrameInfo
|
||||||
|
{
|
||||||
|
StackFrame = frame,
|
||||||
|
FilePath = frame.GetFileName(),
|
||||||
|
LineNumber = frame.GetFileLineNumber(),
|
||||||
|
MethodDisplayInfo = GetMethodDisplayString(frame.GetMethod()),
|
||||||
|
};
|
||||||
|
|
||||||
|
frames.Add(stackFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exceptions != null)
|
||||||
|
{
|
||||||
|
error = new AggregateException(exceptions);
|
||||||
|
return frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = default;
|
||||||
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static MethodDisplayInfo GetMethodDisplayString(MethodBase method)
|
internal static MethodDisplayInfo GetMethodDisplayString(MethodBase method)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue