зеркало из 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 methodName = ReadWideNullTerminatedString(ref data);
|
||||||
string methodSignature = 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;
|
uint pid = eventRecord->ProcessId;
|
||||||
if (!this.MethodLoadMap.TryGetValue(pid, out List<ManagedMethodInfo> methodList))
|
if (!this.MethodLoadMap.TryGetValue(pid, out List<ManagedMethodInfo> methodList))
|
||||||
|
|
|
@ -232,7 +232,7 @@ namespace Microsoft.BPerf.StackViewer
|
||||||
client.DefaultRequestHeaders.Add("Authorization", authorizationHeader);
|
client.DefaultRequestHeaders.Add("Authorization", authorizationHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = client.GetStringAsync(urlPath).Result;
|
var result = await client.GetStringAsync(urlPath);
|
||||||
|
|
||||||
var lines = result.Split('\n');
|
var lines = result.Split('\n');
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2" />
|
<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>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -27,6 +27,20 @@
|
||||||
<ProjectReference Include="..\Microsoft.Diagnostics.Tracing.Stacks\Microsoft.Diagnostics.Tracing.Stacks.csproj" />
|
<ProjectReference Include="..\Microsoft.Diagnostics.Tracing.Stacks\Microsoft.Diagnostics.Tracing.Stacks.csproj" />
|
||||||
</ItemGroup>
|
</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" />
|
<Import Project="..\SourceLink.targets" />
|
||||||
|
|
||||||
</Project>
|
</Project>
|
|
@ -20,7 +20,7 @@ namespace Microsoft.BPerf.StackViewer
|
||||||
{
|
{
|
||||||
foreach (var sourceServer in this.sourceServers)
|
foreach (var sourceServer in this.sourceServers)
|
||||||
{
|
{
|
||||||
if (sourceServer.UrlPrefix.StartsWith(url))
|
if (url.StartsWith(sourceServer.UrlPrefix))
|
||||||
{
|
{
|
||||||
return sourceServer.AuthorizationHeader;
|
return sourceServer.AuthorizationHeader;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,6 @@ namespace Microsoft.BPerf.StackViewer
|
||||||
var etlDir = Path.GetFullPath(Environment.ExpandEnvironmentVariables(app.ApplicationServices.GetService<IOptions<StackViewerSettings>>().Value.TemporaryDataFileDownloadLocation));
|
var etlDir = Path.GetFullPath(Environment.ExpandEnvironmentVariables(app.ApplicationServices.GetService<IOptions<StackViewerSettings>>().Value.TemporaryDataFileDownloadLocation));
|
||||||
app.ApplicationServices.GetService<IOptions<StackViewerSettings>>().Value.TemporaryDataFileDownloadLocation = etlDir;
|
app.ApplicationServices.GetService<IOptions<StackViewerSettings>>().Value.TemporaryDataFileDownloadLocation = etlDir;
|
||||||
Directory.CreateDirectory(etlDir);
|
Directory.CreateDirectory(etlDir);
|
||||||
Directory.SetCurrentDirectory(etlDir);
|
|
||||||
|
|
||||||
loggerFactory.AddConsole();
|
loggerFactory.AddConsole();
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div style="margin-left: 1px">
|
<div style="margin-left: 1px; margin-top: 60px;">
|
||||||
|
|
||||||
<form action="/ui/stackviewer/summary" method="get" class="form-inline">
|
<form action="/ui/stackviewer/summary" method="get" class="form-inline">
|
||||||
<input type="hidden" name="Filename" value="@this.Model.Filename">
|
<input type="hidden" name="Filename" value="@this.Model.Filename">
|
||||||
|
@ -57,7 +57,8 @@
|
||||||
<button type="submit" class="btn btn-primary">Update</button>
|
<button type="submit" class="btn btn-primary">Update</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<hr/>
|
|
||||||
|
<br />
|
||||||
|
|
||||||
@this.RenderBody()
|
@this.RenderBody()
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,16 +10,16 @@
|
||||||
<table class="table table-bordered table-hover" id="calltree">
|
<table class="table table-bordered table-hover" id="calltree">
|
||||||
<thead class="thead-inverse">
|
<thead class="thead-inverse">
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="/Content/documentation.html#Name">Name</a></td>
|
<td>Name</td>
|
||||||
<td><a href="/Content/documentation.html#Source">Source</a></td>
|
<td>Source</td>
|
||||||
<td><a href="/Content/documentation.html#IncMetricP">Inclusive Metric %</a></td>
|
<td>Inclusive Metric %</td>
|
||||||
<td><a href="/Content/documentation.html#IncMetricC">Inclusive Count</a></td>
|
<td>Inclusive Count</td>
|
||||||
<td><a href="/Content/documentation.html#ExcMetricP">Exclusive Metric %</a></td>
|
<td>Exclusive Metric %</td>
|
||||||
<td><a href="/Content/documentation.html#ExcMetricC">Exclusive Count</a></td>
|
<td>Exclusive Count</td>
|
||||||
<td><a href="/Content/documentation.html#FoldCount">Fold Count</a></td>
|
<td>Fold Count</td>
|
||||||
<td><a href="/Content/documentation.html#Histogram">When</a></td>
|
<td>When</td>
|
||||||
<td><a href="/Content/documentation.html#First">First</a></td>
|
<td>First</td>
|
||||||
<td><a href="/Content/documentation.html#Last">Last</a></td>
|
<td>Last</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
|
@ -12,15 +12,15 @@
|
||||||
<table class="table table-bordered table-hover" id="hotspots">
|
<table class="table table-bordered table-hover" id="hotspots">
|
||||||
<thead class="thead-inverse">
|
<thead class="thead-inverse">
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="/Content/documentation.html#Name">Name</a></td>
|
<td>Name</td>
|
||||||
<td><a href="/Content/documentation.html#ExcMetricP">Exclusive Metric %</a></td>
|
<td>Exclusive Metric %</td>
|
||||||
<td><a href="/Content/documentation.html#ExcMetricC">Exclusive Count</a></td>
|
<td>Exclusive Count</td>
|
||||||
<td><a href="/Content/documentation.html#IncMetricP">Inclusive Metric %</a></td>
|
<td>Inclusive Metric %</td>
|
||||||
<td><a href="/Content/documentation.html#IncMetricC">Inclusive Count</a></td>
|
<td>Inclusive Count</td>
|
||||||
<td><a href="/Content/documentation.html#FoldCount">Fold Count</a></td>
|
<td>Fold Count</td>
|
||||||
<td><a href="/Content/documentation.html#Histogram">When</a></td>
|
<td>When</td>
|
||||||
<td><a href="/Content/documentation.html#First">First</a></td>
|
<td>First</td>
|
||||||
<td><a href="/Content/documentation.html#Last">Last</a></td>
|
<td>Last</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
Двоичный файл не отображается.
|
@ -12,7 +12,7 @@
|
||||||
{
|
{
|
||||||
"Url": "https://microsoft.artifacts.visualstudio.com/defaultcollection/_apis/symbol/symsrv",
|
"Url": "https://microsoft.artifacts.visualstudio.com/defaultcollection/_apis/symbol/symsrv",
|
||||||
"Priority": 1,
|
"Priority": 1,
|
||||||
"AuthorizationHeader": "Basic Omh5Y3Z2czcyaHVtaDc0cmRlamo1aTRoZGxhcjN5Z3lzNWFjNmt6bGJzd3picW4yaDJxZ2E="
|
"AuthorizationHeader": "FIXME"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Url": "http://msdl.microsoft.com/download/symbols",
|
"Url": "http://msdl.microsoft.com/download/symbols",
|
||||||
|
@ -21,15 +21,15 @@
|
||||||
{
|
{
|
||||||
"Url": "https://msasg.artifacts.visualstudio.com/defaultcollection/_apis/symbol/symsrv",
|
"Url": "https://msasg.artifacts.visualstudio.com/defaultcollection/_apis/symbol/symsrv",
|
||||||
"Priority": 3,
|
"Priority": 3,
|
||||||
"AuthorizationHeader": "Basic Omh5Y3Z2czcyaHVtaDc0cmRlamo1aTRoZGxhcjN5Z3lzNWFjNmt6bGJzd3picW4yaDJxZ2E="
|
"AuthorizationHeader": "FIXME"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"SourceServerAuthorizationInformation": {
|
"SourceServerAuthorizationInformation": {
|
||||||
"SourceServers": [
|
"SourceServers": [
|
||||||
{
|
{
|
||||||
"UrlPrefix": "https://msasg.visualstudio.com/Bing_UX/_git/snrcode",
|
"UrlPrefix": "http://src.bperf.io",
|
||||||
"AuthorizationHeader": "Basic Omh5Y3Z2czcyaHVtaDc0cmRlamo1aTRoZGxhcjN5Z3lzNWFjNmt6bGJzd3picW4yaDJxZ2E="
|
"AuthorizationHeader": "FIXME"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
table.treetable { font-family: Courier; font-size: 12px; }
|
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 {
|
table.treetable span.indenter {
|
||||||
display: inline-block;
|
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}
|
#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;
|
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))
|
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||||
{
|
var local = incomingSignature;
|
||||||
return reader.IsValid();
|
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)
|
private static bool IsValidPortablePdb(string pdbPath, Guid signature)
|
||||||
|
|
|
@ -143,17 +143,20 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
||||||
return dbgId;
|
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))
|
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||||
{
|
var local = incomingSignature;
|
||||||
return reader.IsValid();
|
dataSource.loadAndValidateDataFromPdb(pdbPath, ref local, 0x53445352, incomingAge);
|
||||||
}
|
}
|
||||||
|
catch (COMException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsValidPortablePdb(string pdbPath, Guid signature)
|
private static bool IsValidPortablePdb(string pdbPath, Guid signature)
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Dia2Lib;
|
||||||
using Microsoft.BPerf.PdbSymbolReader.Interfaces;
|
using Microsoft.BPerf.PdbSymbolReader.Interfaces;
|
||||||
using Microsoft.BPerf.SymbolicInformation.Interfaces;
|
using Microsoft.BPerf.SymbolicInformation.Interfaces;
|
||||||
|
|
||||||
|
@ -28,69 +29,133 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
||||||
|
|
||||||
public SourceLocation FindSourceLocation(uint rva)
|
public SourceLocation FindSourceLocation(uint rva)
|
||||||
{
|
{
|
||||||
LineColumnInformation lineColumnInformation;
|
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||||
string sourceLink;
|
dataSource.loadDataFromPdb(this.pdbPath);
|
||||||
string srcSrv;
|
dataSource.openSession(out var session);
|
||||||
|
|
||||||
using (var reader = new NativePdbReader(this.pdbPath))
|
session.findLinesByRVA(rva, 0, out var sourceLocs);
|
||||||
|
sourceLocs.Next(1, out var sourceLoc, out var fetchCount);
|
||||||
|
if (fetchCount == 0)
|
||||||
{
|
{
|
||||||
reader.GetSourceLinkData(out sourceLink);
|
return null;
|
||||||
reader.GetSrcSrvData(out srcSrv);
|
|
||||||
|
|
||||||
// TODO: FIXME
|
|
||||||
if (!reader.FindLineNumberForNativeMethod(rva, out lineColumnInformation))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dataSource.getStreamSize("srcsrv", out var srcSrvLen);
|
||||||
|
dataSource.getStreamSize("sourcelink", out var sourceLinkLen);
|
||||||
|
|
||||||
var sourceIndexKind = SourceKind.None;
|
var sourceIndexKind = SourceKind.None;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(srcSrv))
|
string streamName = string.Empty;
|
||||||
{
|
uint len = 0;
|
||||||
sourceIndexKind = SourceKind.SrcSrv;
|
|
||||||
}
|
if (sourceLinkLen > 0)
|
||||||
else if (!string.IsNullOrEmpty(srcSrv))
|
|
||||||
{
|
{
|
||||||
|
len = sourceLinkLen;
|
||||||
|
streamName = "sourcelink";
|
||||||
sourceIndexKind = SourceKind.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)
|
public SourceLocation FindSourceLocation(uint methodToken, int offset)
|
||||||
{
|
{
|
||||||
LineColumnInformation lineColumnInformation;
|
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||||
string sourceLink;
|
dataSource.loadDataFromPdb(this.pdbPath);
|
||||||
string srcSrv;
|
dataSource.openSession(out var session);
|
||||||
|
|
||||||
using (var reader = new NativePdbReader(this.pdbPath))
|
session.findSymbolByToken(methodToken, SymTagEnum.SymTagFunction, out var methodSym);
|
||||||
|
if (methodSym == null)
|
||||||
{
|
{
|
||||||
reader.GetSourceLinkData(out sourceLink);
|
return null;
|
||||||
reader.GetSrcSrvData(out srcSrv);
|
|
||||||
|
|
||||||
if (!reader.FindLineNumberForManagedMethod(methodToken, (uint)offset, out lineColumnInformation))
|
|
||||||
{
|
|
||||||
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;
|
var sourceIndexKind = SourceKind.None;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(srcSrv))
|
string streamName = string.Empty;
|
||||||
{
|
uint len = 0;
|
||||||
sourceIndexKind = SourceKind.SrcSrv;
|
|
||||||
}
|
if (sourceLinkLen > 0)
|
||||||
else if (!string.IsNullOrEmpty(srcSrv))
|
|
||||||
{
|
{
|
||||||
|
len = sourceLinkLen;
|
||||||
|
streamName = "sourcelink";
|
||||||
sourceIndexKind = SourceKind.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)
|
public void AddInstructionPointersForProcess(uint pid, ulong imageBase, HashSet<ulong> instructionPointers)
|
||||||
|
@ -124,20 +189,19 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
||||||
return;
|
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)
|
||||||
{
|
{
|
||||||
foreach (var rva in rvasToLookup)
|
this.AddEntry(session, symbolsByAddr, rva + imageBase, rva);
|
||||||
{
|
|
||||||
ulong eip = rva + imageBase;
|
|
||||||
|
|
||||||
if (!reader.FindNameForRVA(rva, out var functionName))
|
|
||||||
{
|
|
||||||
functionName = eip.ToString("x");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.rvaToFunctionNameMap.Add(rva, functionName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
symbolsByAddr = null;
|
||||||
|
session = null;
|
||||||
|
dataSource = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,5 +209,38 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
||||||
{
|
{
|
||||||
return this.processIdsProcessed.Contains(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");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.rvaToFunctionNameMap.Add(rva, functionName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче