Skip to content
代码片段 群组 项目
未验证 提交 ec104294 编辑于 作者: Ryan Rowse's avatar Ryan Rowse 提交者: GitHub
浏览文件

Remove PortablePdbReader except trace cleanup (#19957)


* Remove PortablePdbReader except trace cleanup

Co-authored-by: default avatarRowse <ryan.rowse@jbtc.com>
上级 56d50e67
No related branches found
No related tags found
无相关合并请求
// 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 ...@@ -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; error = default;
var stackTrace = new System.Diagnostics.StackTrace(exception, needFileInfo); return frames;
var stackFrames = stackTrace.GetFrames(); }
if (stackFrames == null) List<Exception> exceptions = 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();
for (var i = 0; i < stackFrames.Length; i++) // Always show last stackFrame
if (!ShowInStackTrace(method) && i < stackFrames.Length - 1)
{ {
var frame = stackFrames[i]; continue;
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) var stackFrame = new StackFrameInfo
{ {
error = new AggregateException(exceptions); StackFrame = frame,
return frames; FilePath = frame.GetFileName(),
} LineNumber = frame.GetFileLineNumber(),
MethodDisplayInfo = GetMethodDisplayString(frame.GetMethod()),
};
error = default; frames.Add(stackFrame);
}
if (exceptions != null)
{
error = new AggregateException(exceptions);
return frames; return frames;
} }
error = default;
return frames;
} }
internal static MethodDisplayInfo GetMethodDisplayString(MethodBase method) internal static MethodDisplayInfo GetMethodDisplayString(MethodBase method)
......
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册