зеркало из https://github.com/microsoft/BPerf.git
SrcSrv fixes
This commit is contained in:
Родитель
8fdfc6a40d
Коммит
4b093aa8e7
|
@ -34,6 +34,8 @@ namespace Microsoft.BPerf.StackViewer
|
|||
|
||||
private readonly ISymbolServerArtifactRetriever symbolServerArtifactRetriever;
|
||||
|
||||
private readonly ISourceServerAuthorizationInformationProvider sourceServerInformationProvider;
|
||||
|
||||
private readonly EtwDeserializer deserializer;
|
||||
|
||||
private readonly StackViewerModel model;
|
||||
|
@ -42,9 +44,10 @@ namespace Microsoft.BPerf.StackViewer
|
|||
|
||||
private CallTree callTree;
|
||||
|
||||
public CallTreeData(ISymbolServerArtifactRetriever symbolServerArtifactRetriever, EtwDeserializer deserializer, StackViewerModel model)
|
||||
public CallTreeData(ISymbolServerArtifactRetriever symbolServerArtifactRetriever, ISourceServerAuthorizationInformationProvider sourceServerInformationProvider, EtwDeserializer deserializer, StackViewerModel model)
|
||||
{
|
||||
this.symbolServerArtifactRetriever = symbolServerArtifactRetriever;
|
||||
this.sourceServerInformationProvider = sourceServerInformationProvider;
|
||||
this.deserializer = deserializer;
|
||||
this.model = model;
|
||||
}
|
||||
|
@ -220,10 +223,15 @@ namespace Microsoft.BPerf.StackViewer
|
|||
|
||||
var client = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false })
|
||||
{
|
||||
DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", "FIXME") },
|
||||
BaseAddress = new Uri(urlPath)
|
||||
};
|
||||
|
||||
var authorizationHeader = this.sourceServerInformationProvider.GetAuthorizationHeaderValue(urlPath);
|
||||
if (!string.IsNullOrEmpty(authorizationHeader))
|
||||
{
|
||||
client.DefaultRequestHeaders.Add("Authorization", authorizationHeader);
|
||||
}
|
||||
|
||||
var result = client.GetStringAsync(urlPath).Result;
|
||||
|
||||
var lines = result.Split('\n');
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// 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.StackViewer
|
||||
{
|
||||
using Microsoft.BPerf.SymbolServer.Interfaces;
|
||||
|
||||
public sealed class SourceServer : ISourceServerAuthorizationInformation
|
||||
{
|
||||
public string UrlPrefix { get; set; }
|
||||
|
||||
public string AuthorizationHeader { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// 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.StackViewer
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
public sealed class SourceServerAuthorizationInformation
|
||||
{
|
||||
public IEnumerable<SourceServer> SourceServers { get; set; }
|
||||
}
|
||||
}
|
|
@ -3,8 +3,10 @@
|
|||
|
||||
namespace Microsoft.BPerf.StackViewer
|
||||
{
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
public sealed class StackViewerUIController : Controller
|
||||
|
@ -39,10 +41,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
[Route("ui/stackviewer/callertree", Name = "Callers", Order = 2)]
|
||||
public async ValueTask<ActionResult> Callers(string name)
|
||||
{
|
||||
if (name.Contains("&"))
|
||||
{
|
||||
name = name.Replace("&", "%26");
|
||||
}
|
||||
name = Encoding.UTF8.GetString(Base64UrlTextEncoder.Decode(name));
|
||||
|
||||
this.ViewBag.Title = "Callers Viewer";
|
||||
|
||||
|
@ -58,10 +57,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
[Route("ui/stackviewer/callertree/children", Name = "CallersChildren", Order = 1)]
|
||||
public async ValueTask<ActionResult> CallersChildren(string name, string path)
|
||||
{
|
||||
if (name.Contains("&"))
|
||||
{
|
||||
name = name.Replace("&", "%26");
|
||||
}
|
||||
name = Encoding.UTF8.GetString(Base64UrlTextEncoder.Decode(name));
|
||||
|
||||
var model = new CallersViewStackViewerViewModel(this.HttpContext)
|
||||
{
|
||||
|
@ -75,10 +71,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
[Route("ui/stackviewer/source/callertree", Name = "SourceViewer")]
|
||||
public async ValueTask<ActionResult> SourceViewer(string name, string path)
|
||||
{
|
||||
if (name.Contains("&"))
|
||||
{
|
||||
name = name.Replace("&", "%26");
|
||||
}
|
||||
name = Encoding.UTF8.GetString(Base64UrlTextEncoder.Decode(name));
|
||||
|
||||
return this.View(await this.controller.CallerContextSource(name, path));
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace Microsoft.BPerf.StackViewer
|
|||
|
||||
private readonly FileLocationType locationType;
|
||||
|
||||
private readonly ISourceServerAuthorizationInformationProvider sourceServerAuthorizationInformationProvider;
|
||||
|
||||
private readonly ISymbolServerArtifactRetriever symbolServerArtifactRetriever;
|
||||
|
||||
private readonly string tempDownloadLocation;
|
||||
|
@ -36,10 +38,11 @@ namespace Microsoft.BPerf.StackViewer
|
|||
|
||||
private EtwDeserializer deserializer;
|
||||
|
||||
public DeserializedData(string uri, FileLocationType locationType, ISymbolServerArtifactRetriever symbolServerArtifactRetriever, string tempDownloadLocation)
|
||||
public DeserializedData(string uri, FileLocationType locationType, ISourceServerAuthorizationInformationProvider sourceServerAuthorizationInformationProvider, ISymbolServerArtifactRetriever symbolServerArtifactRetriever, string tempDownloadLocation)
|
||||
{
|
||||
this.uri = uri;
|
||||
this.locationType = locationType;
|
||||
this.sourceServerAuthorizationInformationProvider = sourceServerAuthorizationInformationProvider;
|
||||
this.symbolServerArtifactRetriever = symbolServerArtifactRetriever;
|
||||
this.tempDownloadLocation = tempDownloadLocation;
|
||||
}
|
||||
|
@ -58,7 +61,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
{
|
||||
if (!this.callTreeDataCache.TryGetValue(model, out var value))
|
||||
{
|
||||
value = new CallTreeData(this.symbolServerArtifactRetriever, this.deserializer, model);
|
||||
value = new CallTreeData(this.symbolServerArtifactRetriever, this.sourceServerAuthorizationInformationProvider, this.deserializer, model);
|
||||
this.callTreeDataCache.Add(model, value);
|
||||
}
|
||||
|
||||
|
@ -80,7 +83,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
{
|
||||
using (var streamToReadFrom = await response.Content.ReadAsStreamAsync())
|
||||
{
|
||||
string fileToWriteTo = Path.Combine(Environment.ExpandEnvironmentVariables(this.tempDownloadLocation) + Guid.NewGuid() + ".etl");
|
||||
string fileToWriteTo = Path.Combine(this.tempDownloadLocation + Guid.NewGuid() + ".etl");
|
||||
using (Stream streamToWriteTo = File.Open(fileToWriteTo, FileMode.Create))
|
||||
{
|
||||
await streamToReadFrom.CopyToAsync(streamToWriteTo);
|
||||
|
|
|
@ -13,16 +13,19 @@ namespace Microsoft.BPerf.StackViewer
|
|||
{
|
||||
private readonly CallTreeDataCache cache;
|
||||
|
||||
private readonly ISourceServerAuthorizationInformationProvider sourceServerAuthorizationInformationProvider;
|
||||
|
||||
private readonly ISymbolServerArtifactRetriever symbolServerArtifactRetriever;
|
||||
|
||||
private readonly ICacheExpirationTimeProvider cacheExpirationTimeProvider;
|
||||
|
||||
private readonly IOptions<StackViewerSettings> stackViewerSettings;
|
||||
|
||||
public DeserializedDataCache(CallTreeDataCache cache, ISymbolServerArtifactRetriever symbolServerArtifactRetriever, ICacheExpirationTimeProvider cacheExpirationTimeProvider, IOptions<StackViewerSettings> stackViewerSettings)
|
||||
public DeserializedDataCache(CallTreeDataCache cache, ISymbolServerArtifactRetriever symbolServerArtifactRetriever, ISourceServerAuthorizationInformationProvider sourceServerAuthorizationInformationProvider, ICacheExpirationTimeProvider cacheExpirationTimeProvider, IOptions<StackViewerSettings> stackViewerSettings)
|
||||
{
|
||||
this.cache = cache;
|
||||
this.symbolServerArtifactRetriever = symbolServerArtifactRetriever;
|
||||
this.sourceServerAuthorizationInformationProvider = sourceServerAuthorizationInformationProvider;
|
||||
this.cacheExpirationTimeProvider = cacheExpirationTimeProvider;
|
||||
this.stackViewerSettings = stackViewerSettings;
|
||||
}
|
||||
|
@ -39,7 +42,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
if (!this.cache.TryGetValue(model.Filename, out IDeserializedData data))
|
||||
{
|
||||
var cacheEntryOptions = new MemoryCacheEntryOptions().SetPriority(CacheItemPriority.NeverRemove).RegisterPostEvictionCallback(callback: EvictionCallback, state: this).SetSlidingExpiration(this.cacheExpirationTimeProvider.Expiration);
|
||||
data = new DeserializedData(model.Filename, model.LocationType, this.symbolServerArtifactRetriever, this.stackViewerSettings.Value.TemporaryDataFileDownloadLocation);
|
||||
data = new DeserializedData(model.Filename, model.LocationType, this.sourceServerAuthorizationInformationProvider, this.symbolServerArtifactRetriever, this.stackViewerSettings.Value.TemporaryDataFileDownloadLocation);
|
||||
this.cache.Set(model.Filename, data, cacheEntryOptions);
|
||||
CacheMonitorEventSource.Logger.CacheEntryAdded(Environment.MachineName, model.Filename);
|
||||
}
|
||||
|
|
|
@ -23,10 +23,11 @@ namespace Microsoft.BPerf.StackViewer
|
|||
UriBuilder uriBuilder = new UriBuilder(urlHelper.RouteUrl(routeName, routeValues, request.Scheme));
|
||||
|
||||
var str = uriBuilder.ToString();
|
||||
str = str.Substring(str.IndexOf('/', str.IndexOf('/', str.IndexOf('/') + 1) + 1));
|
||||
|
||||
foreach (var p in request.Query)
|
||||
{
|
||||
if (string.Equals(p.Key, "path", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(p.Key, "path", StringComparison.OrdinalIgnoreCase) || string.Equals(p.Key, "name", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -34,8 +35,6 @@ namespace Microsoft.BPerf.StackViewer
|
|||
str = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString(str, p.Key, p.Value);
|
||||
}
|
||||
|
||||
str = str.Substring(str.IndexOf('/', str.IndexOf('/', str.IndexOf('/') + 1) + 1));
|
||||
|
||||
return new HtmlString("<a href=\"" + str + "\">" + linkText + "</a>");
|
||||
}
|
||||
|
||||
|
@ -49,7 +48,7 @@ namespace Microsoft.BPerf.StackViewer
|
|||
|
||||
foreach (var p in request.Query)
|
||||
{
|
||||
if (string.Equals(p.Key, "path", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(p.Key, "path", StringComparison.OrdinalIgnoreCase) || string.Equals(p.Key, "name", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
||||
<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.0" />
|
||||
<PackageReference Include="Microsoft.BPerf.Dia2Lib" Version="1.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// 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.StackViewer
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.BPerf.SymbolServer.Interfaces;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
public sealed class SourceServerAuthorizationInformationProvider : ISourceServerAuthorizationInformationProvider
|
||||
{
|
||||
private readonly IEnumerable<ISourceServerAuthorizationInformation> sourceServers;
|
||||
|
||||
public SourceServerAuthorizationInformationProvider(IOptions<SourceServerAuthorizationInformation> options)
|
||||
{
|
||||
this.sourceServers = options.Value.SourceServers;
|
||||
}
|
||||
|
||||
public string GetAuthorizationHeaderValue(string url)
|
||||
{
|
||||
foreach (var sourceServer in this.sourceServers)
|
||||
{
|
||||
if (sourceServer.UrlPrefix.StartsWith(url))
|
||||
{
|
||||
return sourceServer.AuthorizationHeader;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,12 +34,14 @@ namespace Microsoft.BPerf.StackViewer
|
|||
services.Configure<SymbolServerInformation>(this.Configuration.GetSection("SymbolServerInformation"));
|
||||
services.Configure<CacheSettings>(this.Configuration.GetSection("CacheSettings"));
|
||||
services.Configure<StackViewerSettings>(this.Configuration.GetSection("StackViewerSettings"));
|
||||
services.Configure<SourceServerAuthorizationInformation>(this.Configuration.GetSection("SourceServerAuthorizationInformation"));
|
||||
|
||||
services.AddMvc();
|
||||
services.AddMemoryCache();
|
||||
services.AddTransient<StackViewerController, StackViewerController>();
|
||||
services.AddTransient<ICallTreeData, CallTreeData>();
|
||||
services.AddTransient<ISymbolServerArtifactRetriever, SymbolServerArtifactRetriever>();
|
||||
services.AddSingleton<ISourceServerAuthorizationInformationProvider, SourceServerAuthorizationInformationProvider>();
|
||||
services.AddTransient<StackViewerModel, StackViewerModel>();
|
||||
services.AddSingleton<IDeserializedDataCache, DeserializedDataCache>();
|
||||
services.AddSingleton<CallTreeDataCache, CallTreeDataCache>();
|
||||
|
@ -52,7 +54,8 @@ namespace Microsoft.BPerf.StackViewer
|
|||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||
{
|
||||
// TODO: Make this crossplat
|
||||
var etlDir = 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;
|
||||
Directory.CreateDirectory(etlDir);
|
||||
Directory.SetCurrentDirectory(etlDir);
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
@model TreeNode
|
||||
@using System.Text
|
||||
@using Microsoft.AspNetCore.WebUtilities
|
||||
@model TreeNode
|
||||
<tr data-tt-id="@this.Html.Encode(this.Model.ContextId)" data-tt-parent-id="@this.Html.Encode(this.Model.ParentContextId)" data-tt-branch="@this.Model.HasChildren.ToString().ToLower()">
|
||||
<td class="node">@this.Html.CustomRouteLink(this.Model.Name, "Callers", new { name = this.Model.Id })</td>
|
||||
<td class="src">@this.Html.RouteLinkTargetTab("Source", "SourceViewer", new { name = (this.Model.ContextId.IndexOf('/') == -1) ? this.Model.ContextId : this.Model.ContextId.Substring(0, this.Model.ContextId.IndexOf('/')), path = (this.Model.ContextId.IndexOf('/') != -1) ? this.Model.ContextId.Substring(this.Model.ContextId.IndexOf('/') + 1) : string.Empty })</td>
|
||||
<td class="node">@this.Html.CustomRouteLink(this.Model.Name, "Callers", new { name = Base64UrlTextEncoder.Encode(Encoding.UTF8.GetBytes(this.Model.Id)) })</td>
|
||||
<td class="src">@this.Html.RouteLinkTargetTab("Source", "SourceViewer", new { name = Base64UrlTextEncoder.Encode(Encoding.UTF8.GetBytes(this.Model.ContextId.IndexOf('/') == -1 ? this.Model.ContextId : this.Model.ContextId.Substring(0, this.Model.ContextId.IndexOf('/')))), path = (this.Model.ContextId.IndexOf('/') != -1) ? this.Model.ContextId.Substring(this.Model.ContextId.IndexOf('/') + 1) : string.Empty })</td>
|
||||
<td>@this.Model.InclusiveMetricPercent.ToString("n1")%</td>
|
||||
<td>@this.Model.InclusiveCount</td>
|
||||
<td>@this.Model.ExclusiveMetricPercent.ToString("n1")%</td>
|
||||
|
@ -10,4 +12,4 @@
|
|||
<td>@this.Model.InclusiveMetricByTimeString</td>
|
||||
<td>@this.Model.FirstTimeRelativeMSec.ToString("n3")</td>
|
||||
<td>@this.Model.LastTimeRelativeMSec.ToString("n3")</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
this.Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
}
|
||||
|
||||
@using System.Text
|
||||
@using Microsoft.AspNetCore.WebUtilities
|
||||
@model StackViewerViewModel
|
||||
|
||||
<h4>Hotspots View</h4>
|
||||
|
@ -25,7 +27,7 @@
|
|||
@foreach (var node in this.Model.TreeNodes)
|
||||
{
|
||||
<tr data-tt-id="@this.Html.Encode(node.ContextId)" data-tt-parent-id="@this.Html.Encode(node.ParentContextId)" data-tt-branch="@node.HasChildren.ToString().ToLower()">
|
||||
<td class="node">@this.Html.CustomRouteLink(node.Name, "Callers", new { name = node.Id })</td>
|
||||
<td class="node">@this.Html.CustomRouteLink(node.Name, "Callers", new { name = Base64UrlTextEncoder.Encode(Encoding.UTF8.GetBytes(node.Id)) })</td>
|
||||
<td>@node.ExclusiveMetricPercent.ToString("n2")%</td>
|
||||
<td>@node.ExclusiveCount</td>
|
||||
<td>@node.InclusiveMetricPercent.ToString("n2")%</td>
|
||||
|
|
Двоичные данные
WebViewer/Microsoft.BPerf.StackViewer/amd64/msdia140.dll
Двоичные данные
WebViewer/Microsoft.BPerf.StackViewer/amd64/msdia140.dll
Двоичный файл не отображается.
|
@ -4,7 +4,7 @@
|
|||
},
|
||||
"StackViewerSettings": {
|
||||
"NumberOfDisplayedTableEntries": 100,
|
||||
"TemporaryDataFileDownloadLocation": "%TEMP%\\ETLFiles"
|
||||
"TemporaryDataFileDownloadLocation": "%TEMP%//ETLFiles"
|
||||
},
|
||||
"SymbolServerInformation": {
|
||||
"DownloadLocation": "%TEMP%",
|
||||
|
@ -12,7 +12,7 @@
|
|||
{
|
||||
"Url": "https://microsoft.artifacts.visualstudio.com/defaultcollection/_apis/symbol/symsrv",
|
||||
"Priority": 1,
|
||||
"AuthorizationHeader": "%INJECTEDSECRET_DEFAULTSYMSRVPAT%"
|
||||
"AuthorizationHeader": "Basic Omh5Y3Z2czcyaHVtaDc0cmRlamo1aTRoZGxhcjN5Z3lzNWFjNmt6bGJzd3picW4yaDJxZ2E="
|
||||
},
|
||||
{
|
||||
"Url": "http://msdl.microsoft.com/download/symbols",
|
||||
|
@ -21,7 +21,15 @@
|
|||
{
|
||||
"Url": "https://msasg.artifacts.visualstudio.com/defaultcollection/_apis/symbol/symsrv",
|
||||
"Priority": 3,
|
||||
"AuthorizationHeader": "%INJECTEDSECRET_MSASGSYMSRVPAT%"
|
||||
"AuthorizationHeader": "Basic Omh5Y3Z2czcyaHVtaDc0cmRlamo1aTRoZGxhcjN5Z3lzNWFjNmt6bGJzd3picW4yaDJxZ2E="
|
||||
}
|
||||
]
|
||||
},
|
||||
"SourceServerAuthorizationInformation": {
|
||||
"SourceServers": [
|
||||
{
|
||||
"UrlPrefix": "https://msasg.visualstudio.com/Bing_UX/_git/snrcode",
|
||||
"AuthorizationHeader": "Basic Omh5Y3Z2czcyaHVtaDc0cmRlamo1aTRoZGxhcjN5Z3lzNWFjNmt6bGJzd3picW4yaDJxZ2E="
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// 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.SymbolServer.Interfaces
|
||||
{
|
||||
public interface ISourceServerAuthorizationInformation
|
||||
{
|
||||
string UrlPrefix { get; }
|
||||
|
||||
string AuthorizationHeader { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
// 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.SymbolServer.Interfaces
|
||||
{
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
public interface ISourceServerAuthorizationInformationProvider
|
||||
{
|
||||
string GetAuthorizationHeaderValue(string url);
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ namespace Microsoft.BPerf.SymbolicInformation.Interfaces
|
|||
None,
|
||||
Illegal,
|
||||
Embedded,
|
||||
Indexed
|
||||
SrcSrv,
|
||||
SourceLink
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,52 +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;
|
||||
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(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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// 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
|
||||
{
|
||||
internal struct LineColumnInformation
|
||||
{
|
||||
public LineColumnInformation(string filename, uint lineStart, uint lineEnd, ushort columnStart, ushort columnEnd)
|
||||
{
|
||||
this.Filename = filename;
|
||||
this.LineStart = lineStart;
|
||||
this.LineEnd = lineEnd;
|
||||
this.ColumnStart = columnStart;
|
||||
this.ColumnEnd = columnEnd;
|
||||
}
|
||||
|
||||
public string Filename { get; }
|
||||
|
||||
public uint LineStart { get; }
|
||||
|
||||
public uint LineEnd { get; }
|
||||
|
||||
public ushort ColumnStart { get; }
|
||||
|
||||
public ushort ColumnEnd { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -92,14 +92,14 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
|
||||
customDebugInformationHandleCollection = metadataReader.CustomDebugInformation;
|
||||
|
||||
string srcSrvString = null;
|
||||
string sourceLinkString = null;
|
||||
foreach (var customDebugInformationHandle in customDebugInformationHandleCollection)
|
||||
{
|
||||
var customDebugInformation = metadataReader.GetCustomDebugInformation(customDebugInformationHandle);
|
||||
|
||||
if (metadataReader.GetGuid(customDebugInformation.Kind) == SourceLink)
|
||||
{
|
||||
srcSrvString = Encoding.UTF8.GetString(metadataReader.GetBlobBytes(customDebugInformation.Value));
|
||||
sourceLinkString = Encoding.UTF8.GetString(metadataReader.GetBlobBytes(customDebugInformation.Value));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,11 +127,11 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
}
|
||||
|
||||
var kind = lineNumber == -1 ? SourceKind.Illegal : SourceKind.None;
|
||||
kind = srcSrvString != null ? SourceKind.Indexed : kind;
|
||||
kind = sourceLinkString != null ? SourceKind.SourceLink : kind;
|
||||
kind = embeddedSource ? SourceKind.Embedded : kind; /* yeah, kinda weird that embedded takes precedence, in fact it could be indexed and embedded
|
||||
however, if it is embedded likely I want to get it from here because I already have it */
|
||||
|
||||
return new SourceLocation(new SourceFile(documentName, kind, srcSrvString), lineNumber);
|
||||
return new SourceLocation(new SourceFile(documentName, kind, sourceLinkString), lineNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
using System.Management.Automation.Internal;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.BPerf.SymbolServer.Interfaces;
|
||||
|
@ -150,10 +149,14 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
{
|
||||
var client = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false })
|
||||
{
|
||||
DefaultRequestHeaders = { Authorization = new AuthenticationHeaderValue("Basic", symbolServer.AuthorizationHeader) },
|
||||
BaseAddress = new Uri(symbolServer.Url)
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(symbolServer.AuthorizationHeader))
|
||||
{
|
||||
client.DefaultRequestHeaders.Add("Authorization", symbolServer.AuthorizationHeader);
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
|
@ -168,6 +171,11 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
return false;
|
||||
}
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.Found && response.Headers.Location != null)
|
||||
{
|
||||
var client2 = new HttpClient();
|
||||
|
@ -207,18 +215,15 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
|
||||
private static bool IsValidPdb(string pdbPath, Guid signature, uint age)
|
||||
{
|
||||
try
|
||||
if (File.Exists(pdbPath))
|
||||
{
|
||||
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||
var local = signature;
|
||||
dataSource.loadAndValidateDataFromPdb(pdbPath, ref local, 0x53445352, age);
|
||||
}
|
||||
catch (System.Runtime.InteropServices.COMException)
|
||||
{
|
||||
return false;
|
||||
using (var reader = new NativePdbReader(pdbPath, signature, age))
|
||||
{
|
||||
return reader.IsValid();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsValidPortablePdb(string pdbPath, Guid signature)
|
||||
|
|
|
@ -145,22 +145,12 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
|
||||
private static bool IsValidPdb(string pdbPath, Guid signature, uint age)
|
||||
{
|
||||
// otherwise we'll try to load DIA on non Windows
|
||||
if (File.Exists(pdbPath) && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
if (File.Exists(pdbPath))
|
||||
{
|
||||
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||
var local = signature;
|
||||
|
||||
try
|
||||
using (var reader = new NativePdbReader(pdbPath, signature, age))
|
||||
{
|
||||
dataSource.loadAndValidateDataFromPdb(pdbPath, ref local, 0x53445352, age);
|
||||
return reader.IsValid();
|
||||
}
|
||||
catch (COMException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -5,7 +5,6 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Dia2Lib;
|
||||
using Microsoft.BPerf.PdbSymbolReader.Interfaces;
|
||||
using Microsoft.BPerf.SymbolicInformation.Interfaces;
|
||||
|
||||
|
@ -29,95 +28,69 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
|
||||
public SourceLocation FindSourceLocation(uint rva)
|
||||
{
|
||||
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||
dataSource.loadDataFromPdb(this.pdbPath);
|
||||
dataSource.openSession(out var session);
|
||||
LineColumnInformation lineColumnInformation;
|
||||
string sourceLink;
|
||||
string srcSrv;
|
||||
|
||||
session.findLinesByRVA(rva, 0, out var sourceLocs);
|
||||
sourceLocs.Next(1, out var sourceLoc, out var fetchCount);
|
||||
if (fetchCount == 0)
|
||||
using (var reader = new NativePdbReader(this.pdbPath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
reader.GetSourceLinkData(out sourceLink);
|
||||
reader.GetSrcSrvData(out srcSrv);
|
||||
|
||||
dataSource.getStreamSize("srcsrv", out var len);
|
||||
|
||||
string srcSrvString = null;
|
||||
if (len > 0)
|
||||
{
|
||||
var buffer = new byte[len];
|
||||
unsafe
|
||||
// TODO: FIXME
|
||||
if (!reader.FindLineNumberForNativeMethod(rva, out lineColumnInformation))
|
||||
{
|
||||
fixed (byte* bufferPtr = buffer)
|
||||
{
|
||||
dataSource.getStreamRawData("srcsrv", len, out *bufferPtr);
|
||||
srcSrvString = Encoding.UTF8.GetString(buffer);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
var sourceFile = new SourceFile(sourceLoc.sourceFile.fileName, len == 0 ? SourceKind.Indexed : SourceKind.None, srcSrvString); // we should support embedded
|
||||
var lineNum = (int)sourceLoc.lineNumber;
|
||||
var sourceIndexKind = SourceKind.None;
|
||||
|
||||
return new SourceLocation(sourceFile, lineNum);
|
||||
if (!string.IsNullOrEmpty(srcSrv))
|
||||
{
|
||||
sourceIndexKind = SourceKind.SrcSrv;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(srcSrv))
|
||||
{
|
||||
sourceIndexKind = SourceKind.SourceLink;
|
||||
}
|
||||
|
||||
var sourceFile = new SourceFile(lineColumnInformation.Filename, sourceIndexKind, sourceIndexKind == SourceKind.SourceLink ? sourceLink : srcSrv); // we should support embedded
|
||||
|
||||
return new SourceLocation(sourceFile, (int)lineColumnInformation.LineStart);
|
||||
}
|
||||
|
||||
public SourceLocation FindSourceLocation(uint methodToken, int offset)
|
||||
{
|
||||
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||
dataSource.loadDataFromPdb(this.pdbPath);
|
||||
dataSource.openSession(out var session);
|
||||
LineColumnInformation lineColumnInformation;
|
||||
string sourceLink;
|
||||
string srcSrv;
|
||||
|
||||
session.findSymbolByToken(methodToken, SymTagEnum.SymTagFunction, out var methodSym);
|
||||
if (methodSym == null)
|
||||
using (var reader = new NativePdbReader(this.pdbPath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
reader.GetSourceLinkData(out sourceLink);
|
||||
reader.GetSrcSrvData(out srcSrv);
|
||||
|
||||
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 len);
|
||||
|
||||
string srcSrvString = null;
|
||||
if (len > 0)
|
||||
{
|
||||
var buffer = new byte[len];
|
||||
unsafe
|
||||
if (!reader.FindLineNumberForManagedMethod(methodToken, (uint)offset, out lineColumnInformation))
|
||||
{
|
||||
fixed (byte* bufferPtr = buffer)
|
||||
{
|
||||
dataSource.getStreamRawData("srcsrv", len, out *bufferPtr);
|
||||
srcSrvString = Encoding.UTF8.GetString(buffer);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
var sourceFile = new SourceFile(sourceLoc.sourceFile.fileName, len == 0 ? SourceKind.Indexed : SourceKind.None, srcSrvString); // we should support embedded
|
||||
var sourceIndexKind = SourceKind.None;
|
||||
|
||||
int lineNum;
|
||||
|
||||
while (true)
|
||||
if (!string.IsNullOrEmpty(srcSrv))
|
||||
{
|
||||
lineNum = (int)sourceLoc.lineNumber;
|
||||
if (lineNum != 0xFEEFEE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
lineNum = 0;
|
||||
sourceLocs.Next(1, out sourceLoc, out fetchCount);
|
||||
if (fetchCount == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
sourceIndexKind = SourceKind.SrcSrv;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(srcSrv))
|
||||
{
|
||||
sourceIndexKind = SourceKind.SourceLink;
|
||||
}
|
||||
|
||||
return new SourceLocation(sourceFile, lineNum);
|
||||
var sourceFile = new SourceFile(lineColumnInformation.Filename, sourceIndexKind, sourceIndexKind == SourceKind.SourceLink ? sourceLink : srcSrv); // we should support embedded
|
||||
|
||||
return new SourceLocation(sourceFile, (int)lineColumnInformation.LineStart);
|
||||
}
|
||||
|
||||
public void AddInstructionPointersForProcess(uint pid, ulong imageBase, HashSet<ulong> instructionPointers)
|
||||
|
@ -151,19 +124,20 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
return;
|
||||
}
|
||||
|
||||
var dataSource = DiaLoader.GetDiaSourceObject();
|
||||
dataSource.loadDataFromPdb(this.pdbPath);
|
||||
dataSource.openSession(out var session);
|
||||
session.getSymbolsByAddr(out var symbolsByAddr);
|
||||
|
||||
foreach (var rva in rvasToLookup)
|
||||
using (var reader = new NativePdbReader(this.pdbPath))
|
||||
{
|
||||
this.AddEntry(session, symbolsByAddr, rva + imageBase, rva);
|
||||
}
|
||||
foreach (var rva in rvasToLookup)
|
||||
{
|
||||
ulong eip = rva + imageBase;
|
||||
|
||||
symbolsByAddr = null;
|
||||
session = null;
|
||||
dataSource = null;
|
||||
if (!reader.FindNameForRVA(rva, out var functionName))
|
||||
{
|
||||
functionName = eip.ToString("x");
|
||||
}
|
||||
|
||||
this.rvaToFunctionNameMap.Add(rva, functionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,38 +145,5 @@ namespace Microsoft.BPerf.SymbolicInformation.ProgramDatabase
|
|||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче