Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wasm] Download Symbols from microsoft symbol server #40690

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
67075a6
Creating a draft to download symbols from microsoft symbol server whe…
thaystg Aug 12, 2020
45c6f81
Fix what lewing suggested.
thaystg Aug 14, 2020
34932d6
Changing what @radical suggested.
thaystg Aug 17, 2020
b94e6d5
Changed what @radical suggested.
thaystg Aug 25, 2020
4f29f82
Update src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs
thaystg Aug 25, 2020
07cc6ca
Update src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs
thaystg Aug 25, 2020
64c1ef9
If it's not available on a URL try in the next one in the list.
thaystg Aug 25, 2020
9792356
Merge branch 'thays_load_symbols_from_ms_symbol_server' of github.com…
thaystg Aug 25, 2020
b4f55d8
Logging error and adding comment about SDSR
thaystg Aug 25, 2020
9f41f60
Returning if we find the method even if we have an exception sending …
thaystg Aug 25, 2020
e8a13d3
Logging when we don't find the pdb.
thaystg Aug 25, 2020
b8c48e3
Changing what @radical suggested.
thaystg Aug 25, 2020
076eb42
Avoiding that we try to load symbols from the same assembly more than…
thaystg Aug 25, 2020
bdfc1c3
Simplifying and adding more log.
thaystg Aug 25, 2020
429907f
Update src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs
thaystg Aug 26, 2020
7598ac9
Adding support for receive the urlSymbolServer as a parameter in the …
thaystg Sep 4, 2020
12f45c9
Merge remote-tracking branch 'upstream/master' into thays_load_symbol…
thaystg Sep 4, 2020
8b955aa
Fix @radical suggestion.
thaystg Sep 8, 2020
09729c4
Removing default symbol server URL, like this we can land this on rc …
thaystg Sep 14, 2020
b989c8e
Fix compilation.
thaystg Sep 14, 2020
2d5812e
Update src/mono/wasm/debugger/DebuggerTestSuite/TestHarnessStartup.cs
thaystg Sep 15, 2020
d72fc69
Update src/mono/wasm/debugger/BrowserDebugHost/Startup.cs
thaystg Sep 15, 2020
f9c93d2
Accepting @radical suggestion.
thaystg Sep 15, 2020
729887b
Adding workaround on dotnet/runtime while PR 686 is not merged on Cec…
thaystg Sep 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/mono/wasm/debugger/BrowserDebugHost/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;

namespace Microsoft.WebAssembly.Diagnostics
{
Expand Down Expand Up @@ -138,7 +139,10 @@ async Task ConnectProxy(HttpContext context)
{
using var loggerFactory = LoggerFactory.Create(
builder => builder.AddConsole().AddFilter(null, LogLevel.Information));
var proxy = new DebuggerProxy(loggerFactory);

context.Request.Query.TryGetValue("urlSymbolServer", out StringValues urlSymbolServerList);
var proxy = new DebuggerProxy(loggerFactory, urlSymbolServerList.ToList());

var ideSocket = await context.WebSockets.AcceptWebSocketAsync();

await proxy.Run(endpoint, ideSocket);
Expand Down
19 changes: 18 additions & 1 deletion src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ class AssemblyInfo
Dictionary<string, TypeInfo> typesByName = new Dictionary<string, TypeInfo>();
readonly List<SourceFile> sources = new List<SourceFile>();
internal string Url { get; }
public bool TriedToLoadSymbolsOnDemand { get; set; }

public AssemblyInfo(IAssemblyResolver resolver, string url, byte[] assembly, byte[] pdb)
{
Expand Down Expand Up @@ -438,8 +439,24 @@ public AssemblyInfo(ILogger logger)
{
this.logger = logger;
}

public ModuleDefinition Image => image;

void Populate()
public void ClearDebugInfo()
{
foreach (var type in image.GetTypes())
{
var typeInfo = new TypeInfo(this, type);
typesByName[type.FullName] = typeInfo;

foreach (var method in type.Methods)
{
method.DebugInformation = null;
}
}
}

public void Populate()
{
ProcessSourceLink();

Expand Down
5 changes: 3 additions & 2 deletions src/mono/wasm/debugger/BrowserDebugProxy/DebuggerProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Net.WebSockets;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
Expand All @@ -16,9 +17,9 @@ public class DebuggerProxy
{
private readonly MonoProxy proxy;

public DebuggerProxy(ILoggerFactory loggerFactory)
public DebuggerProxy(ILoggerFactory loggerFactory, IList<string> urlSymbolServerList)
{
proxy = new MonoProxy(loggerFactory);
proxy = new MonoProxy(loggerFactory, urlSymbolServerList);
}

public Task Run(Uri browserUri, WebSocket ideSocket)
Expand Down
107 changes: 106 additions & 1 deletion src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,26 @@
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Mono.Cecil.Cil;
using Mono.Cecil.Pdb;
using Mono.Cecil;
using System.Net.Http;

namespace Microsoft.WebAssembly.Diagnostics
{

internal class MonoProxy : DevToolsProxy
{
IList<string> urlSymbolServerList;
static HttpClient client = new HttpClient();
HashSet<SessionId> sessions = new HashSet<SessionId>();
Dictionary<SessionId, ExecutionContext> contexts = new Dictionary<SessionId, ExecutionContext>();

public MonoProxy(ILoggerFactory loggerFactory, bool hideWebDriver = true) : base(loggerFactory) { this.hideWebDriver = hideWebDriver; }
public MonoProxy(ILoggerFactory loggerFactory, IList<string> urlSymbolServerList, bool hideWebDriver = true) : base(loggerFactory)
{
this.hideWebDriver = hideWebDriver;
this.urlSymbolServerList = urlSymbolServerList ?? new List<string>();
}

readonly bool hideWebDriver;

Expand Down Expand Up @@ -337,6 +347,13 @@ protected override async Task<bool> AcceptCommand(MessageId id, string method, J
}

// Protocol extensions
case "DotnetDebugger.addSymbolServerUrl":
{
string url = args["url"]?.Value<string>();
if (!String.IsNullOrEmpty(url) && !urlSymbolServerList.Contains(url))
urlSymbolServerList.Add(url);
return true;
}
case "DotnetDebugger.getMethodLocation":
{
Console.WriteLine("set-breakpoint-by-method: " + id + " " + args);
Expand Down Expand Up @@ -541,6 +558,19 @@ async Task<bool> OnPause(SessionId sessionId, JObject args, CancellationToken to

var method = asm.GetMethodByToken(method_token);

if (method == null && !asm.Image.HasSymbols)
{
try
{
method = await LoadSymbolsOnDemand(asm, method_token, sessionId, token);
}
catch (Exception e)
{
Log("info", $"Unable to find il offset: {il_pos} in method token: {method_token} assembly name: {assembly_name} exception: {e.ToString()}");
continue;
}
}

if (method == null)
{
Log("info", $"Unable to find il offset: {il_pos} in method token: {method_token} assembly name: {assembly_name}");
Expand Down Expand Up @@ -618,6 +648,81 @@ async Task<bool> OnPause(SessionId sessionId, JObject args, CancellationToken to
return true;
}

async Task<MethodInfo> LoadSymbolsOnDemand(AssemblyInfo asm, uint method_token, SessionId sessionId, CancellationToken token)
radical marked this conversation as resolved.
Show resolved Hide resolved
{
var context = GetContext(sessionId);
if (asm.TriedToLoadSymbolsOnDemand)
return null;
asm.TriedToLoadSymbolsOnDemand = true;
ImageDebugHeader header = asm.Image.GetDebugHeader();

for (var i = 0; i < header.Entries.Length; i++)
{
var entry = header.Entries[i];
if (entry.Directory.Type != ImageDebugType.CodeView)
{
continue;
}

var data = entry.Data;

if (data.Length < 24)
return null;

var pdbSignature = (data[0]
| (data[1] << 8)
| (data[2] << 16)
| (data[3] << 24));

if (pdbSignature != 0x53445352) // "SDSR" mono/metadata/debug-mono-ppdb.c#L101
return null;

var buffer = new byte[16];
Buffer.BlockCopy(data, 4, buffer, 0, 16);

var pdbAge = (data[20]
| (data[21] << 8)
| (data[22] << 16)
| (data[23] << 24));

var pdbGuid = new Guid(buffer);
var buffer2 = new byte[(data.Length - 24) - 1];
Buffer.BlockCopy(data, 24, buffer2, 0, (data.Length - 24) - 1);
var pdbName = System.Text.Encoding.UTF8.GetString(buffer2, 0, buffer2.Length);
pdbName = Path.GetFileName(pdbName);

foreach (var urlSymbolServer in urlSymbolServerList)
{
var downloadURL = $"{urlSymbolServer}/{pdbName}/{pdbGuid.ToString("N").ToUpper() + pdbAge}/{pdbName}";

try
{
using HttpResponseMessage response = await client.GetAsync(downloadURL);
using Stream streamToReadFrom = await response.Content.ReadAsStreamAsync();
var portablePdbReaderProvider = new PdbReaderProvider();
var symbolReader = portablePdbReaderProvider.GetSymbolReader(asm.Image, streamToReadFrom);
asm.ClearDebugInfo(); //workaround while cecil PR #686 is not merged
asm.Image.ReadSymbols(symbolReader);
asm.Populate();
foreach (var source in asm.Sources)
{
var scriptSource = JObject.FromObject(source.ToScriptSource(context.Id, context.AuxData));
SendEvent(sessionId, "Debugger.scriptParsed", scriptSource, token);
}
radical marked this conversation as resolved.
Show resolved Hide resolved
return asm.GetMethodByToken(method_token);
}
catch (Exception e)
radical marked this conversation as resolved.
Show resolved Hide resolved
{
Log("info", $"Unable to load symbols on demand exception: {e.ToString()} url:{downloadURL} assembly: {asm.Name}");
}
}
break;
}

Log("info", "Unable to load symbols on demand assembly: {asm.Name}");
return null;
radical marked this conversation as resolved.
Show resolved Hide resolved
}

async Task OnDefaultContext(SessionId sessionId, ExecutionContext context, CancellationToken token)
{
Log("verbose", "Default context created, clearing state and sending events");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;

namespace Microsoft.WebAssembly.Diagnostics
{
Expand Down Expand Up @@ -122,7 +123,8 @@ public async Task LaunchAndServe(ProcessStartInfo psi, HttpContext context, Func

using var loggerFactory = LoggerFactory.Create(
builder => builder.AddConsole().AddFilter(null, LogLevel.Information));
var proxy = new DebuggerProxy(loggerFactory);

var proxy = new DebuggerProxy(loggerFactory, null);
var browserUri = new Uri(con_str);
var ideSocket = await context.WebSockets.AcceptWebSocketAsync();

Expand Down