-
Notifications
You must be signed in to change notification settings - Fork 4.6k
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
[debugger][wasm] Support DebuggerProxyAttribute #56872
Merged
thaystg
merged 15 commits into
dotnet:main
from
thaystg:thays_implement_debugger_proxy_attribute
Aug 16, 2021
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
7e985d2
Implementing debugger proxy
thaystg 33652d5
Merge remote-tracking branch 'origin/main' into thays_implement_debug…
thaystg f56ef84
Merge remote-tracking branch 'origin/main' into thays_implement_debug…
thaystg 3a55e21
fix compilation
thaystg 394e3f6
Implement debuggerproxy attribute.
thaystg 79e81ff
Reusing code for DebuggerProxy method and DebuggerDisplay method.
thaystg 6c0abf2
Fix unit tests.
thaystg 19d6864
Fixing unit tests that uses List<T>.
thaystg b1a32b5
Fix unit tests that uses List.
thaystg 3091b2f
Addressing @radical comments.
thaystg de72265
Using flags enum as suggested by @lewing.
thaystg a0a420e
Merge branch 'main' into thays_implement_debugger_proxy_attribute
lewing 31eff80
Fixing merge.
thaystg 427b1f2
Addressing @radical comments.
thaystg 9d6b705
Addressing @radical comments.
thaystg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,8 @@ internal class MemberReferenceResolver | |
private PerScopeCache scopeCache; | ||
private ILogger logger; | ||
private bool localsFetched; | ||
private int linqTypeId; | ||
private MonoSDBHelper sdbHelper; | ||
|
||
public MemberReferenceResolver(MonoProxy proxy, ExecutionContext ctx, SessionId sessionId, int scopeId, ILogger logger) | ||
{ | ||
|
@@ -32,6 +34,8 @@ public MemberReferenceResolver(MonoProxy proxy, ExecutionContext ctx, SessionId | |
this.ctx = ctx; | ||
this.logger = logger; | ||
scopeCache = ctx.GetCacheForScope(scopeId); | ||
sdbHelper = proxy.SdbHelper; | ||
linqTypeId = -1; | ||
} | ||
|
||
public MemberReferenceResolver(MonoProxy proxy, ExecutionContext ctx, SessionId sessionId, JArray objectValues, ILogger logger) | ||
|
@@ -43,6 +47,8 @@ public MemberReferenceResolver(MonoProxy proxy, ExecutionContext ctx, SessionId | |
this.logger = logger; | ||
scopeCache = new PerScopeCache(objectValues); | ||
localsFetched = true; | ||
sdbHelper = proxy.SdbHelper; | ||
linqTypeId = -1; | ||
} | ||
|
||
public async Task<JObject> GetValueFromObject(JToken objRet, CancellationToken token) | ||
|
@@ -51,7 +57,7 @@ public async Task<JObject> GetValueFromObject(JToken objRet, CancellationToken t | |
{ | ||
if (DotnetObjectId.TryParse(objRet?["value"]?["objectId"]?.Value<string>(), out DotnetObjectId objectId)) | ||
{ | ||
var exceptionObject = await proxy.SdbHelper.GetObjectValues(sessionId, int.Parse(objectId.Value), true, false, false, true, token); | ||
var exceptionObject = await sdbHelper.GetObjectValues(sessionId, int.Parse(objectId.Value), GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.OwnProperties, token); | ||
var exceptionObjectMessage = exceptionObject.FirstOrDefault(attr => attr["name"].Value<string>().Equals("_message")); | ||
exceptionObjectMessage["value"]["value"] = objRet["value"]?["className"]?.Value<string>() + ": " + exceptionObjectMessage["value"]?["value"]?.Value<string>(); | ||
return exceptionObjectMessage["value"]?.Value<JObject>(); | ||
|
@@ -67,8 +73,8 @@ public async Task<JObject> GetValueFromObject(JToken objRet, CancellationToken t | |
{ | ||
var commandParams = new MemoryStream(); | ||
var commandParamsWriter = new MonoBinaryWriter(commandParams); | ||
commandParamsWriter.WriteObj(objectId, proxy.SdbHelper); | ||
var ret = await proxy.SdbHelper.InvokeMethod(sessionId, commandParams.ToArray(), objRet["get"]["methodId"].Value<int>(), objRet["name"].Value<string>(), token); | ||
commandParamsWriter.WriteObj(objectId, sdbHelper); | ||
var ret = await sdbHelper.InvokeMethod(sessionId, commandParams.ToArray(), objRet["get"]["methodId"].Value<int>(), objRet["name"].Value<string>(), token); | ||
return await GetValueFromObject(ret, token); | ||
} | ||
|
||
|
@@ -88,27 +94,27 @@ public async Task<JObject> TryToRunOnLoadedClasses(string varName, CancellationT | |
classNameToFind += part.Trim(); | ||
if (typeId != -1) | ||
{ | ||
var fields = await proxy.SdbHelper.GetTypeFields(sessionId, typeId, token); | ||
var fields = await sdbHelper.GetTypeFields(sessionId, typeId, onlyPublic: false, token); | ||
foreach (var field in fields) | ||
{ | ||
if (field.Name == part.Trim()) | ||
{ | ||
var isInitialized = await proxy.SdbHelper.TypeIsInitialized(sessionId, typeId, token); | ||
var isInitialized = await sdbHelper.TypeIsInitialized(sessionId, typeId, token); | ||
if (isInitialized == 0) | ||
{ | ||
isInitialized = await proxy.SdbHelper.TypeInitialize(sessionId, typeId, token); | ||
isInitialized = await sdbHelper.TypeInitialize(sessionId, typeId, token); | ||
} | ||
var valueRet = await proxy.SdbHelper.GetFieldValue(sessionId, typeId, field.Id, token); | ||
var valueRet = await sdbHelper.GetFieldValue(sessionId, typeId, field.Id, token); | ||
return await GetValueFromObject(valueRet, token); | ||
} | ||
} | ||
var methodId = await proxy.SdbHelper.GetPropertyMethodIdByName(sessionId, typeId, part.Trim(), token); | ||
var methodId = await sdbHelper.GetPropertyMethodIdByName(sessionId, typeId, part.Trim(), token); | ||
if (methodId != -1) | ||
{ | ||
var commandParamsObj = new MemoryStream(); | ||
var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); | ||
commandParamsObjWriter.Write(0); //param count | ||
var retMethod = await proxy.SdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); | ||
var retMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); | ||
return await GetValueFromObject(retMethod, token); | ||
} | ||
} | ||
|
@@ -118,8 +124,8 @@ public async Task<JObject> TryToRunOnLoadedClasses(string varName, CancellationT | |
var type = asm.GetTypeByName(classNameToFind); | ||
if (type != null) | ||
{ | ||
var assemblyId = await proxy.SdbHelper.GetAssemblyId(sessionId, type.assembly.Name, token); | ||
typeId = await proxy.SdbHelper.GetTypeIdFromToken(sessionId, assemblyId, type.Token, token); | ||
var assemblyId = await sdbHelper.GetAssemblyId(sessionId, type.assembly.Name, token); | ||
typeId = await sdbHelper.GetTypeIdFromToken(sessionId, assemblyId, type.Token, token); | ||
} | ||
} | ||
} | ||
|
@@ -204,6 +210,7 @@ public async Task<JObject> Resolve(string varName, CancellationToken token) | |
public async Task<JObject> Resolve(InvocationExpressionSyntax method, Dictionary<string, JObject> memberAccessValues, CancellationToken token) | ||
{ | ||
var methodName = ""; | ||
int isTryingLinq = 0; | ||
try | ||
{ | ||
JObject rootObject = null; | ||
|
@@ -223,33 +230,56 @@ public async Task<JObject> Resolve(InvocationExpressionSyntax method, Dictionary | |
if (rootObject != null) | ||
{ | ||
DotnetObjectId.TryParse(rootObject?["objectId"]?.Value<string>(), out DotnetObjectId objectId); | ||
var typeId = await proxy.SdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token); | ||
int methodId = await proxy.SdbHelper.GetMethodIdByName(sessionId, typeId[0], methodName, token); | ||
var typeIds = await sdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token); | ||
int methodId = await sdbHelper.GetMethodIdByName(sessionId, typeIds[0], methodName, token); | ||
var className = await sdbHelper.GetTypeNameOriginal(sessionId, typeIds[0], token); | ||
if (methodId == 0) //try to search on System.Linq.Enumerable | ||
radical marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
if (linqTypeId == -1) | ||
linqTypeId = await sdbHelper.GetTypeByName(sessionId, "System.Linq.Enumerable", token); | ||
methodId = await sdbHelper.GetMethodIdByName(sessionId, linqTypeId, methodName, token); | ||
if (methodId != 0) | ||
{ | ||
foreach (var typeId in typeIds) | ||
{ | ||
var genericTypeArgs = await sdbHelper.GetTypeParamsOrArgsForGenericType(sessionId, typeId, token); | ||
if (genericTypeArgs.Count > 0) | ||
{ | ||
isTryingLinq = 1; | ||
methodId = await sdbHelper.MakeGenericMethod(sessionId, methodId, genericTypeArgs, token); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
if (methodId == 0) { | ||
var typeName = await proxy.SdbHelper.GetTypeName(sessionId, typeId[0], token); | ||
var typeName = await sdbHelper.GetTypeName(sessionId, typeIds[0], token); | ||
throw new Exception($"Method '{methodName}' not found in type '{typeName}'"); | ||
} | ||
var commandParamsObj = new MemoryStream(); | ||
var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); | ||
commandParamsObjWriter.WriteObj(objectId, proxy.SdbHelper); | ||
if (isTryingLinq == 0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this writing? |
||
commandParamsObjWriter.WriteObj(objectId, sdbHelper); | ||
if (method.ArgumentList != null) | ||
{ | ||
commandParamsObjWriter.Write((int)method.ArgumentList.Arguments.Count); | ||
commandParamsObjWriter.Write((int)method.ArgumentList.Arguments.Count + isTryingLinq); | ||
if (isTryingLinq == 1) | ||
commandParamsObjWriter.WriteObj(objectId, sdbHelper); | ||
foreach (var arg in method.ArgumentList.Arguments) | ||
{ | ||
if (arg.Expression is LiteralExpressionSyntax) | ||
{ | ||
if (!await commandParamsObjWriter.WriteConst(sessionId, arg.Expression as LiteralExpressionSyntax, proxy.SdbHelper, token)) | ||
if (!await commandParamsObjWriter.WriteConst(sessionId, arg.Expression as LiteralExpressionSyntax, sdbHelper, token)) | ||
return null; | ||
} | ||
if (arg.Expression is IdentifierNameSyntax) | ||
{ | ||
var argParm = arg.Expression as IdentifierNameSyntax; | ||
if (!await commandParamsObjWriter.WriteJsonValue(sessionId, memberAccessValues[argParm.Identifier.Text], proxy.SdbHelper, token)) | ||
if (!await commandParamsObjWriter.WriteJsonValue(sessionId, memberAccessValues[argParm.Identifier.Text], sdbHelper, token)) | ||
return null; | ||
} | ||
} | ||
var retMethod = await proxy.SdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); | ||
var retMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); | ||
return await GetValueFromObject(retMethod, token); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests needed for this