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;
|
||||
}
|
||||
|
||||
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;
|
||||
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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue