зеркало из https://github.com/microsoft/BPerf.git
Fix pdb issue
This commit is contained in:
Родитель
4b093aa8e7
Коммит
1bf3928eb5
|
@ -767,7 +767,7 @@ namespace Microsoft.BPerf.StackInformation.Etw
|
|||
string methodName = ReadWideNullTerminatedString(ref data);
|
||||
string methodSignature = ReadWideNullTerminatedString(ref data);
|
||||
|
||||
var methodInfo = new ManagedMethodInfo(methodToken, methodId, moduleId, methodStartAddress, methodStartAddress + methodSize, methodNamespace + "." + methodName + methodSignature);
|
||||
var methodInfo = new ManagedMethodInfo(methodToken, methodId, moduleId, methodStartAddress, methodStartAddress + methodSize, methodNamespace + "." + methodName + methodSignature.Substring(methodSignature.IndexOf('(')));
|
||||
|
||||
uint pid = eventRecord->ProcessId;
|
||||
if (!this.MethodLoadMap.TryGetValue(pid, out List<ManagedMethodInfo> methodList))
|
||||
|
|
|
@ -232,7 +232,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
client.DefaultRequestHeaders.Add("Authorization", authorizationHeader);
|
||||
}
|
||||
|
||||
var result = client.GetStringAsync(urlPath).Result;
|
||||
var result = await client.GetStringAsync(urlPath);
|
||||
|
||||
var lines = result.Split('\n');
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.BPerf.Dia2Lib" Version="1.0.1" />
|
||||
<PackageReference Include="Microsoft.BPerf.Dia2Lib" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -27,6 +27,20 @@
|
|||
<ProjectReference Include="..\Microsoft.Diagnostics.Tracing.Stacks\Microsoft.Diagnostics.Tracing.Stacks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="amd64\" />
|
||||
<Folder Include="x86\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="amd64\msdia140.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="x86\msdia140.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\SourceLink.targets" />
|
||||
|
||||
</Project>
|
|
@ -20,7 +20,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
{
|
||||
foreach (var sourceServer in this.sourceServers)
|
||||
{
|
||||
if (sourceServer.UrlPrefix.StartsWith(url))
|
||||
if (url.StartsWith(sourceServer.UrlPrefix))
|
||||
{
|
||||
return sourceServer.AuthorizationHeader;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,6 @@ namespace Microsoft.BPerf.StackViewer
|
|||
var etlDir = Path.GetFullPath(Environment.ExpandEnvironmentVariables(app.ApplicationServices.GetService<IOptions<StackViewerSettings>>().Value.TemporaryDataFileDownloadLocation));
|
||||
app.ApplicationServices.GetService<IOptions<StackViewerSettings>>().Value.TemporaryDataFileDownloadLocation = etlDir;
|
||||
Directory.CreateDirectory(etlDir);
|
||||
Directory.SetCurrentDirectory(etlDir);
|
||||
|
||||
loggerFactory.AddConsole();
|
||||
app.UseStaticFiles();
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</div>
|
||||
</nav>
|
||||
|
||||
<div style="margin-left: 1px">
|
||||
<div style="margin-left: 1px; margin-top: 60px;">
|
||||
|
||||
<form action="/ui/stackviewer/summary" method="get" class="form-inline">
|
||||
<input type="hidden" name="Filename" value="@this.Model.Filename">
|
||||
|
@ -57,7 +57,8 @@
|
|||
<button type="submit" class="btn btn-primary">Update</button>
|
||||
</div>
|
||||
</form>
|
||||
<hr/>
|
||||
|
||||
<br />
|
||||
|
||||
@this.RenderBody()
|
||||
</div>
|
||||
|
|
|
@ -10,16 +10,16 @@
|
|||
<table class="table table-bordered table-hover" id="calltree">
|
||||
<thead class="thead-inverse">
|
||||
<tr>
|
||||
<td><a href="/Content/documentation.html#Name">Name</a></td>
|
||||
<td><a href="/Content/documentation.html#Source">Source</a></td>
|
||||
<td><a href="/Content/documentation.html#IncMetricP">Inclusive Metric %</a></td>
|
||||
<td><a href="/Content/documentation.html#IncMetricC">Inclusive Count</a></td>
|
||||
<td><a href="/Content/documentation.html#ExcMetricP">Exclusive Metric %</a></td>
|
||||
<td><a href="/Content/documentation.html#ExcMetricC">Exclusive Count</a></td>
|
||||
<td><a href="/Content/documentation.html#FoldCount">Fold Count</a></td>
|
||||
<td><a href="/Content/documentation.html#Histogram">When</a></td>
|
||||
<td><a href="/Content/documentation.html#First">First</a></td>
|
||||
<td><a href="/Content/documentation.html#Last">Last</a></td>
|
||||
<td>Name</td>
|
||||
<td>Source</td>
|
||||
<td>Inclusive Metric %</td>
|
||||
<td>Inclusive Count</td>
|
||||
<td>Exclusive Metric %</td>
|
||||
<td>Exclusive Count</td>
|
||||
<td>Fold Count</td>
|
||||
<td>When</td>
|
||||
<td>First</td>
|
||||
<td>Last</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
|
@ -12,15 +12,15 @@
|
|||
<table class="table table-bordered table-hover" id="hotspots">
|
||||
<thead class="thead-inverse">
|
||||
<tr>
|
||||
<td><a href="/Content/documentation.html#Name">Name</a></td>
|
||||
<td><a href="/Content/documentation.html#ExcMetricP">Exclusive Metric %</a></td>
|
||||
<td><a href="/Content/documentation.html#ExcMetricC">Exclusive Count</a></td>
|
||||
<td><a href="/Content/documentation.html#IncMetricP">Inclusive Metric %</a></td>
|
||||
<td><a href="/Content/documentation.html#IncMetricC">Inclusive Count</a></td>
|
||||
<td><a href="/Content/documentation.html#FoldCount">Fold Count</a></td>
|
||||
<td><a href="/Content/documentation.html#Histogram">When</a></td>
|
||||
<td><a href="/Content/documentation.html#First">First</a></td>
|
||||
<td><a href="/Content/documentation.html#Last">Last</a></td>
|
||||
<td>Name</td>
|
||||
<td>Exclusive Metric %</td>
|
||||
<td>Exclusive Count</td>
|
||||
<td>Inclusive Metric %</td>
|
||||
<td>Inclusive Count</td>
|
||||
<td>Fold Count</td>
|
||||
<td>When</td>
|
||||
<td>First</td>
|
||||
<td>Last</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
Двоичный файл не отображается.
|
@ -12,7 +12,7 @@
|
|||
{
|
||||
"Url": "https://microsoft.artifacts.visualstudio.com/defaultcollection/_apis/symbol/symsrv",
|
||||
"Priority": 1,
|
||||
"AuthorizationHeader": "Basic Omh5Y3Z2czcyaHVtaDc0cmRlamo1aTRoZGxhcjN5Z3lzNWFjNmt6bGJzd3picW4yaDJxZ2E="
|
||||
"AuthorizationHeader": "FIXME"
|
||||
},
|
||||
{
|
||||
"Url": "http://msdl.microsoft.com/download/symbols",
|
||||
|
@ -21,15 +21,15 @@
|
|||
{
|
||||
"Url": "https://msasg.artifacts.visualstudio.com/defaultcollection/_apis/symbol/symsrv",
|
||||
"Priority": 3,
|
||||
"AuthorizationHeader": "Basic Omh5Y3Z2czcyaHVtaDc0cmRlamo1aTRoZGxhcjN5Z3lzNWFjNmt6bGJzd3picW4yaDJxZ2E="
|
||||
"AuthorizationHeader": "FIXME"
|
||||
}
|
||||
]
|
||||
},
|
||||
"SourceServerAuthorizationInformation": {
|
||||
"SourceServers": [
|
||||
{
|
||||
"UrlPrefix": "https://msasg.visualstudio.com/Bing_UX/_git/snrcode",
|
||||
"AuthorizationHeader": "Basic Omh5Y3Z2czcyaHVtaDc0cmRlamo1aTRoZGxhcjN5Z3lzNWFjNmt6bGJzd3picW4yaDJxZ2E="
|
||||
"UrlPrefix": "http://src.bperf.io",
|
||||
"AuthorizationHeader": "FIXME"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
table.treetable { font-family: Courier; font-size: 12px; }
|
||||
#hotspots { font-family: Courier; font-size: 12px; }
|
||||
#hotspots { font-family: Courier; font-size: 12px; line-height: 1; }
|
||||
|
||||
table.treetable span.indenter {
|
||||
display: inline-block;
|
||||
|
@ -79,4 +79,4 @@ table.treetable tr.expanded.accept td span.indenter a {
|
|||
|
||||
#sourcenotice { font-family: Calibri;font-weight: bold;padding: 4px; color: #008b8b}
|
||||
|
||||
#calltree { display: none}
|
||||
#calltree { display: none; line-height: 1; }
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Dia2Lib;
|
||||
|
||||
internal static class DiaLoader
|
||||
{
|
||||
private static readonly Guid ClassFactoryGuid = new Guid("00000001-0000-0000-C000-000000000046");
|
||||
|
||||
private static readonly Guid IDiaDataSourceGuid = new Guid("65A23C15-BAB3-45DA-8639-F06DE86B9EA8");
|
||||
|
||||
private static bool loadedNativeDll;
|
||||
|
||||
[ComImport]
|
||||
[ComVisible(false)]
|
||||
[Guid("00000001-0000-0000-C000-000000000046")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
private interface IClassFactory
|
||||
{
|
||||
void CreateInstance([MarshalAs(UnmanagedType.Interface)] object aggregator, ref Guid refiid, [MarshalAs(UnmanagedType.Interface)] out object createdObject);
|
||||
|
||||
void LockServer(bool incrementRefCount);
|
||||
}
|
||||
|
||||
public static IDiaDataSource3 GetDiaSourceObject()
|
||||
{
|
||||
if (!loadedNativeDll)
|
||||
{
|
||||
LoadLibrary(System.IO.Path.GetFullPath(IntPtr.Size == 8 ? @"amd64\msdia140.dll" : @"x86\msdia140.dll"));
|
||||
loadedNativeDll = true;
|
||||
}
|
||||
|
||||
var diaSourceClassGuid = new Guid("{e6756135-1e65-4d17-8576-610761398c3c}");
|
||||
var comClassFactory = (IClassFactory)DllGetClassObject(diaSourceClassGuid, ClassFactoryGuid);
|
||||
|
||||
Guid dataDataSourceGuid = IDiaDataSourceGuid;
|
||||
comClassFactory.CreateInstance(null, ref dataDataSourceGuid, out object comObject);
|
||||
return comObject as IDiaDataSource3;
|
||||
}
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
[DllImport("msdia140.dll", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
|
||||
private static extern object DllGetClassObject([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr LoadLibrary(string filePath);
|
||||
}
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
internal delegate IntPtr Allocator(IntPtr size);
|
||||
|
||||
internal sealed class NativePdbReader : IDisposable
|
||||
{
|
||||
private const string LibraryPath = @"C:\Microsoft.BPerf.WindowsPdbReader.Native\x64\Debug\Microsoft.BPerf.WindowsPdbReader.Native.dll";
|
||||
|
||||
private static readonly IntPtr AllocationPointer = Marshal.GetFunctionPointerForDelegate<Allocator>(Marshal.AllocHGlobal);
|
||||
|
||||
private readonly IntPtr reader;
|
||||
|
||||
private readonly bool signatureAndAgeValid;
|
||||
|
||||
public NativePdbReader(string filename, Guid incomingGuid, uint incomingAge)
|
||||
{
|
||||
this.reader = CreatePdbSymbolReader(filename);
|
||||
this.signatureAndAgeValid = ValidateSignature(this.reader, ref incomingGuid, incomingAge);
|
||||
}
|
||||
|
||||
public NativePdbReader(string filename)
|
||||
: this(filename, Guid.Empty, 0)
|
||||
{
|
||||
this.signatureAndAgeValid = true;
|
||||
}
|
||||
|
||||
~NativePdbReader()
|
||||
{
|
||||
this.ReleaseUnmanagedResources();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.ReleaseUnmanagedResources();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public bool IsValid()
|
||||
{
|
||||
return this.signatureAndAgeValid && IsReaderValid(this.reader);
|
||||
}
|
||||
|
||||
public bool FindNameForRVA(uint rva, out string name)
|
||||
{
|
||||
var retVal = FindNameForRVA(this.reader, rva, AllocationPointer, out var namePtr, out uint size);
|
||||
|
||||
try
|
||||
{
|
||||
name = namePtr == IntPtr.Zero ? string.Empty : Marshal.PtrToStringAnsi(namePtr, (int)size);
|
||||
return retVal;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (namePtr != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(namePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool FindLineNumberForManagedMethod(uint methodToken, uint iloffset, out LineColumnInformation lineColumnInformation)
|
||||
{
|
||||
var retVal = FindLineNumberForManagedMethod(this.reader, methodToken, iloffset, AllocationPointer, out var namePtr, out var size, out var lineStart, out var lineEnd, out var columnStart, out var columnEnd);
|
||||
try
|
||||
{
|
||||
var name = namePtr == IntPtr.Zero ? string.Empty : Marshal.PtrToStringAnsi(namePtr, (int)size);
|
||||
lineColumnInformation = new LineColumnInformation(name, lineStart, lineEnd, columnStart, columnEnd);
|
||||
return retVal;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (namePtr != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(namePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool FindLineNumberForNativeMethod(uint rva, out LineColumnInformation lineColumnInformation)
|
||||
{
|
||||
var retVal = FindLineNumberForNativeMethod(this.reader, rva, AllocationPointer, out var namePtr, out var size, out var lineStart, out var lineEnd, out var columnStart, out var columnEnd);
|
||||
try
|
||||
{
|
||||
var name = namePtr == IntPtr.Zero ? string.Empty : Marshal.PtrToStringAnsi(namePtr, (int)size);
|
||||
lineColumnInformation = new LineColumnInformation(name, lineStart, lineEnd, columnStart, columnEnd);
|
||||
return retVal;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (namePtr != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(namePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetSourceLinkData(out string sourcelink)
|
||||
{
|
||||
var retVal = GetSourceLinkData(this.reader, out var dataPtr, out var size);
|
||||
try
|
||||
{
|
||||
sourcelink = dataPtr == IntPtr.Zero ? string.Empty : Marshal.PtrToStringAnsi(dataPtr, (int)size);
|
||||
return retVal;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (dataPtr != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(dataPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetSrcSrvData(out string srcsrv)
|
||||
{
|
||||
var retVal = GetSrcSrvData(this.reader, out var dataPtr, out var size);
|
||||
try
|
||||
{
|
||||
srcsrv = dataPtr == IntPtr.Zero ? string.Empty : Marshal.PtrToStringAnsi(dataPtr, (int)size);
|
||||
return retVal;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (dataPtr != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(dataPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(LibraryPath)]
|
||||
private static extern IntPtr CreatePdbSymbolReader(string filename);
|
||||
|
||||
[DllImport(LibraryPath)]
|
||||
private static extern void DeletePdbSymbolReader(IntPtr reader);
|
||||
|
||||
[DllImport(LibraryPath)]
|
||||
private static extern bool IsReaderValid(IntPtr reader);
|
||||
|
||||
[DllImport(LibraryPath)]
|
||||
private static extern bool ValidateSignature(IntPtr reader, ref Guid signature, uint age);
|
||||
|
||||
[DllImport(LibraryPath)]
|
||||
private static extern bool FindNameForRVA(IntPtr reader, uint rva, IntPtr allocator, out IntPtr outPtr, out uint size);
|
||||
|
||||
[DllImport(LibraryPath)]
|
||||
private static extern bool FindLineNumberForManagedMethod(IntPtr reader, uint methodToken, uint iloffset, IntPtr allocator, out IntPtr namePtr, out uint size, out uint lineStart, out uint lineEnd, out ushort columnStart, out ushort columnEnd);
|
||||
|
||||
[DllImport(LibraryPath)]
|
||||
private static extern bool FindLineNumberForNativeMethod(IntPtr reader, uint rva, IntPtr allocator, out IntPtr namePtr, out uint size, out uint lineStart, out uint lineEnd, out ushort columnStart, out ushort columnEnd);
|
||||
|
||||
[DllImport(LibraryPath)]
|
||||
private static extern bool GetSrcSrvData(IntPtr reader, out IntPtr data, out uint size);
|
||||
|
||||
[DllImport(LibraryPath)]
|
||||
private static extern bool GetSourceLinkData(IntPtr reader, out IntPtr data, out uint size);
|
||||
|
||||
private void ReleaseUnmanagedResources()
|
||||
{
|
||||
if (this.reader != IntPtr.Zero)
|
||||
{
|
||||
DeletePdbSymbolReader(this.reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -213,17 +213,20 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
return true;
|
||||
}
|
||||
|
||||
private static bool IsValidPdb(string pdbPath, Guid signature, uint age)
|
||||
private static bool IsValidPdb(string pdbPath, Guid incomingSignature, uint incomingAge)
|
||||
{
|
||||
if (File.Exists(pdbPath))
|
||||
try
|
||||
{
|
||||
using (var reader = new NativePdbReader(pdbPath, signature, age))
|
||||
{
|
||||
return reader.IsValid();
|
||||
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||
var local = incomingSignature;
|
||||
dataSource.loadAndValidateDataFromPdb(pdbPath, ref local, 0x53445352, incomingAge);
|
||||
}
|
||||
catch (System.Runtime.InteropServices.COMException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsValidPortablePdb(string pdbPath, Guid signature)
|
||||
|
|
|
@ -143,17 +143,20 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
return dbgId;
|
||||
}
|
||||
|
||||
private static bool IsValidPdb(string pdbPath, Guid signature, uint age)
|
||||
private static bool IsValidPdb(string pdbPath, Guid incomingSignature, uint incomingAge)
|
||||
{
|
||||
if (File.Exists(pdbPath))
|
||||
try
|
||||
{
|
||||
using (var reader = new NativePdbReader(pdbPath, signature, age))
|
||||
{
|
||||
return reader.IsValid();
|
||||
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||
var local = incomingSignature;
|
||||
dataSource.loadAndValidateDataFromPdb(pdbPath, ref local, 0x53445352, incomingAge);
|
||||
}
|
||||
catch (COMException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsValidPortablePdb(string pdbPath, Guid signature)
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Dia2Lib;
|
||||
using Microsoft.BPerf.PdbSymbolReader.Interfaces;
|
||||
using Microsoft.BPerf.SymbolicInformation.Interfaces;
|
||||
|
||||
|
@ -28,69 +29,133 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
|
||||
public SourceLocation FindSourceLocation(uint rva)
|
||||
{
|
||||
LineColumnInformation lineColumnInformation;
|
||||
string sourceLink;
|
||||
string srcSrv;
|
||||
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||
dataSource.loadDataFromPdb(this.pdbPath);
|
||||
dataSource.openSession(out var session);
|
||||
|
||||
using (var reader = new NativePdbReader(this.pdbPath))
|
||||
{
|
||||
reader.GetSourceLinkData(out sourceLink);
|
||||
reader.GetSrcSrvData(out srcSrv);
|
||||
|
||||
// TODO: FIXME
|
||||
if (!reader.FindLineNumberForNativeMethod(rva, out lineColumnInformation))
|
||||
session.findLinesByRVA(rva, 0, out var sourceLocs);
|
||||
sourceLocs.Next(1, out var sourceLoc, out var fetchCount);
|
||||
if (fetchCount == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
dataSource.getStreamSize("srcsrv", out var srcSrvLen);
|
||||
dataSource.getStreamSize("sourcelink", out var sourceLinkLen);
|
||||
|
||||
var sourceIndexKind = SourceKind.None;
|
||||
|
||||
if (!string.IsNullOrEmpty(srcSrv))
|
||||
{
|
||||
sourceIndexKind = SourceKind.SrcSrv;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(srcSrv))
|
||||
string streamName = string.Empty;
|
||||
uint len = 0;
|
||||
|
||||
if (sourceLinkLen > 0)
|
||||
{
|
||||
len = sourceLinkLen;
|
||||
streamName = "sourcelink";
|
||||
sourceIndexKind = SourceKind.SourceLink;
|
||||
}
|
||||
else if (srcSrvLen > 0)
|
||||
{
|
||||
len = srcSrvLen;
|
||||
streamName = "srcsrv";
|
||||
sourceIndexKind = SourceKind.SrcSrv;
|
||||
}
|
||||
|
||||
var sourceFile = new SourceFile(lineColumnInformation.Filename, sourceIndexKind, sourceIndexKind == SourceKind.SourceLink ? sourceLink : srcSrv); // we should support embedded
|
||||
string srcSrvString = null;
|
||||
if (len > 0)
|
||||
{
|
||||
var buffer = new byte[len];
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* bufferPtr = buffer)
|
||||
{
|
||||
dataSource.getStreamRawData(streamName, len, out *bufferPtr);
|
||||
srcSrvString = Encoding.UTF8.GetString(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new SourceLocation(sourceFile, (int)lineColumnInformation.LineStart);
|
||||
var sourceFile = new SourceFile(sourceLoc.sourceFile.fileName, sourceIndexKind, srcSrvString); // we should support embedded
|
||||
var lineNum = (int)sourceLoc.lineNumber;
|
||||
|
||||
return new SourceLocation(sourceFile, lineNum);
|
||||
}
|
||||
|
||||
public SourceLocation FindSourceLocation(uint methodToken, int offset)
|
||||
{
|
||||
LineColumnInformation lineColumnInformation;
|
||||
string sourceLink;
|
||||
string srcSrv;
|
||||
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||
dataSource.loadDataFromPdb(this.pdbPath);
|
||||
dataSource.openSession(out var session);
|
||||
|
||||
using (var reader = new NativePdbReader(this.pdbPath))
|
||||
{
|
||||
reader.GetSourceLinkData(out sourceLink);
|
||||
reader.GetSrcSrvData(out srcSrv);
|
||||
|
||||
if (!reader.FindLineNumberForManagedMethod(methodToken, (uint)offset, out lineColumnInformation))
|
||||
session.findSymbolByToken(methodToken, SymTagEnum.SymTagFunction, out var methodSym);
|
||||
if (methodSym == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
session.findLinesByRVA(methodSym.relativeVirtualAddress + (uint)offset, 256, out var sourceLocs);
|
||||
sourceLocs.Next(1, out var sourceLoc, out uint fetchCount);
|
||||
if (fetchCount == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
dataSource.getStreamSize("srcsrv", out var srcSrvLen);
|
||||
dataSource.getStreamSize("sourcelink", out var sourceLinkLen);
|
||||
|
||||
var sourceIndexKind = SourceKind.None;
|
||||
|
||||
if (!string.IsNullOrEmpty(srcSrv))
|
||||
{
|
||||
sourceIndexKind = SourceKind.SrcSrv;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(srcSrv))
|
||||
string streamName = string.Empty;
|
||||
uint len = 0;
|
||||
|
||||
if (sourceLinkLen > 0)
|
||||
{
|
||||
len = sourceLinkLen;
|
||||
streamName = "sourcelink";
|
||||
sourceIndexKind = SourceKind.SourceLink;
|
||||
}
|
||||
else if (srcSrvLen > 0)
|
||||
{
|
||||
len = srcSrvLen;
|
||||
streamName = "srcsrv";
|
||||
sourceIndexKind = SourceKind.SrcSrv;
|
||||
}
|
||||
|
||||
var sourceFile = new SourceFile(lineColumnInformation.Filename, sourceIndexKind, sourceIndexKind == SourceKind.SourceLink ? sourceLink : srcSrv); // we should support embedded
|
||||
string srcSrvString = null;
|
||||
if (len > 0)
|
||||
{
|
||||
var buffer = new byte[len];
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* bufferPtr = buffer)
|
||||
{
|
||||
dataSource.getStreamRawData(streamName, len, out *bufferPtr);
|
||||
srcSrvString = Encoding.UTF8.GetString(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new SourceLocation(sourceFile, (int)lineColumnInformation.LineStart);
|
||||
var sourceFile = new SourceFile(sourceLoc.sourceFile.fileName, sourceIndexKind, srcSrvString); // we should support embedded
|
||||
|
||||
int lineNum;
|
||||
|
||||
while (true)
|
||||
{
|
||||
lineNum = (int)sourceLoc.lineNumber;
|
||||
if (lineNum != 0xFEEFEE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
lineNum = 0;
|
||||
sourceLocs.Next(1, out sourceLoc, out fetchCount);
|
||||
if (fetchCount == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new SourceLocation(sourceFile, lineNum);
|
||||
}
|
||||
|
||||
public void AddInstructionPointersForProcess(uint pid, ulong imageBase, HashSet<ulong> instructionPointers)
|
||||
|
@ -124,13 +189,53 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
return;
|
||||
}
|
||||
|
||||
using (var reader = new NativePdbReader(this.pdbPath))
|
||||
{
|
||||
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||
dataSource.loadDataFromPdb(this.pdbPath);
|
||||
dataSource.openSession(out var session);
|
||||
session.getSymbolsByAddr(out var symbolsByAddr);
|
||||
|
||||
foreach (var rva in rvasToLookup)
|
||||
{
|
||||
ulong eip = rva + imageBase;
|
||||
this.AddEntry(session, symbolsByAddr, rva + imageBase, rva);
|
||||
}
|
||||
|
||||
if (!reader.FindNameForRVA(rva, out var functionName))
|
||||
symbolsByAddr = null;
|
||||
session = null;
|
||||
dataSource = null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasAnyInstructionPointersForProcess(uint pid)
|
||||
{
|
||||
return this.processIdsProcessed.Contains(pid);
|
||||
}
|
||||
|
||||
private void AddEntry(IDiaSession session, IDiaEnumSymbolsByAddr symbolsByAddr, ulong eip, uint rva)
|
||||
{
|
||||
session.findSymbolByRVA(rva, SymTagEnum.SymTagPublicSymbol, out var symbol);
|
||||
if (symbol == null)
|
||||
{
|
||||
session.findSymbolByRVA(rva, SymTagEnum.SymTagFunction, out symbol);
|
||||
if (symbol == null)
|
||||
{
|
||||
symbol = symbolsByAddr.symbolByRVA(rva);
|
||||
}
|
||||
}
|
||||
|
||||
string functionName;
|
||||
if (symbol != null)
|
||||
{
|
||||
symbol.get_undecoratedNameEx(0x1000, out var unmangled);
|
||||
if (!string.IsNullOrEmpty(unmangled))
|
||||
{
|
||||
functionName = unmangled;
|
||||
}
|
||||
else
|
||||
{
|
||||
functionName = !string.IsNullOrEmpty(symbol.name) ? symbol.name : eip.ToString("x");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
functionName = eip.ToString("x");
|
||||
}
|
||||
|
@ -139,11 +244,3 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasAnyInstructionPointersForProcess(uint pid)
|
||||
{
|
||||
return this.processIdsProcessed.Contains(pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче