-
Notifications
You must be signed in to change notification settings - Fork 100
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
Add debug info support #298
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
995089d
WIP
7e4da0a
add hash to debug info
5b8c7d0
fixup
shargon 75b61ea
don't emit hidden sequence points
8bd4248
include local variables in debug info
cad3d71
global tool support
be2db60
fix netstandard2.1
273c0d5
Merge branch 'master' into devhawk/nefdbgnfo
d523171
fixup merge
f7084bf
fix null ref issues
41657db
debug info unit test
4723e07
fix null deref in FuncExport.ConvType
b78f476
Merge branch 'master' into devhawk/nefdbgnfo
shargon 2e2678b
use TargetFramework
b0f58db
Merge branch 'master' into devhawk/nefdbgnfo
shargon 01d0c76
Merge branch 'master' into devhawk/nefdbgnfo
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
using Mono.Cecil.Cil; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Text; | ||
|
||
namespace Neo.Compiler | ||
{ | ||
public static class DebugExport | ||
{ | ||
private static MyJson.JsonNode_Array GetSequencePoints(IEnumerable<NeoCode> codes, IReadOnlyDictionary<string, int> docMap, IReadOnlyDictionary<int, int> addrConvTable) | ||
{ | ||
var points = codes | ||
.Where(code => code.sequencePoint != null) | ||
.Select(code => (code.addr, code.sequencePoint)); | ||
|
||
var outjson = new MyJson.JsonNode_Array(); | ||
|
||
foreach (var (address, sequencePoint) in points) | ||
{ | ||
var value = string.Format("{0}[{1}]{2}:{3}-{4}:{5}", | ||
addrConvTable.TryGetValue(address, out var newAddress) ? newAddress : address, | ||
docMap[sequencePoint.Document.Url], | ||
sequencePoint.StartLine, | ||
sequencePoint.StartColumn, | ||
sequencePoint.EndLine, | ||
sequencePoint.EndColumn); | ||
outjson.Add(new MyJson.JsonNode_ValueString(value)); | ||
} | ||
|
||
return outjson; | ||
} | ||
|
||
private static MyJson.JsonNode_Array ConvertParamList(IEnumerable<NeoParam> @params) | ||
{ | ||
@params ??= Enumerable.Empty<NeoParam>(); | ||
var paramsJson = new MyJson.JsonNode_Array(); | ||
foreach (var param in @params) | ||
{ | ||
var value = string.Format("{0},{1}", param.name, FuncExport.ConvType(param.type)); | ||
paramsJson.Add(new MyJson.JsonNode_ValueString(value)); | ||
} | ||
|
||
return paramsJson; | ||
} | ||
|
||
private static MyJson.JsonNode_Array GetMethods(NeoModule module, IReadOnlyDictionary<string, int> docMap, IReadOnlyDictionary<int, int> addrConvTable) | ||
{ | ||
var outjson = new MyJson.JsonNode_Array(); | ||
|
||
foreach (var method in module.mapMethods.Values) | ||
{ | ||
if (method.body_Codes.Values.Count == 0) | ||
{ | ||
continue; | ||
} | ||
|
||
var name = string.Format("{0},{1}", | ||
method._namespace, method.displayName); | ||
|
||
var range = string.Format("{0}-{1}", | ||
method.body_Codes.Values.First().addr, | ||
method.body_Codes.Values.Last().addr); | ||
|
||
var methodJson = new MyJson.JsonNode_Object(); | ||
methodJson.SetDictValue("id", method.name); | ||
methodJson.SetDictValue("name", name); | ||
methodJson.SetDictValue("range", range); | ||
methodJson.SetDictValue("params", ConvertParamList(method.paramtypes)); | ||
methodJson.SetDictValue("return", FuncExport.ConvType(method.returntype)); | ||
methodJson.SetDictValue("variables", ConvertParamList(method.method?.body_Variables)); | ||
methodJson.SetDictValue("sequence-points", GetSequencePoints(method.body_Codes.Values, docMap, addrConvTable)); | ||
devhawk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
outjson.Add(methodJson); | ||
} | ||
return outjson; | ||
} | ||
|
||
private static MyJson.JsonNode_Array GetEvents(NeoModule module) | ||
{ | ||
var outjson = new MyJson.JsonNode_Array(); | ||
foreach (var @event in module.mapEvents.Values) | ||
{ | ||
var name = string.Format("{0},{1}", | ||
@event._namespace, @event.displayName); | ||
|
||
var eventJson = new MyJson.JsonNode_Object(); | ||
eventJson.SetDictValue("id", @event.name); | ||
eventJson.SetDictValue("name", name); | ||
eventJson.SetDictValue("params", ConvertParamList(@event.paramtypes)); | ||
devhawk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
outjson.Add(eventJson); | ||
} | ||
return outjson; | ||
} | ||
|
||
private static IReadOnlyDictionary<string, int> GetDocumentMap(NeoModule module) | ||
{ | ||
return module.mapMethods.Values | ||
.SelectMany(m => m.body_Codes.Values) | ||
.Where(code => code.sequencePoint != null) | ||
.Select(code => code.sequencePoint.Document.Url) | ||
.Distinct() | ||
.Select((d, i) => (d, i)) | ||
.ToDictionary(t => t.d, t => t.i); | ||
} | ||
|
||
private static MyJson.JsonNode_Array GetDocuments(IReadOnlyDictionary<string, int> docMap) | ||
{ | ||
var outjson = new MyJson.JsonNode_Array(); | ||
foreach (var doc in docMap.OrderBy(kvp => kvp.Value)) | ||
{ | ||
Debug.Assert(outjson.Count == doc.Value); | ||
outjson.Add(new MyJson.JsonNode_ValueString(doc.Key)); | ||
} | ||
return outjson; | ||
} | ||
|
||
public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script, IReadOnlyDictionary<int, int> addrConvTable) | ||
{ | ||
var docMap = GetDocumentMap(module); | ||
addrConvTable ??= ImmutableDictionary<int, int>.Empty; | ||
|
||
var outjson = new MyJson.JsonNode_Object(); | ||
outjson.SetDictValue("hash", FuncExport.ComputeHash(script)); | ||
// outjson.SetDictValue("entrypoint", module.mainMethod); | ||
outjson.SetDictValue("documents", GetDocuments(docMap)); | ||
outjson.SetDictValue("methods", GetMethods(module, docMap, addrConvTable)); | ||
outjson.SetDictValue("events", GetEvents(module)); | ||
return outjson; | ||
} | ||
} | ||
} |
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
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 |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using Neo.Compiler.MSIL.UnitTests.Utils; | ||
using System; | ||
using System.Linq; | ||
|
||
namespace Neo.Compiler.MSIL | ||
{ | ||
[TestClass] | ||
public class UnitTest_DebugInfo | ||
{ | ||
[TestMethod] | ||
public void Test_DebugInfo() | ||
{ | ||
var testengine = new TestEngine(); | ||
testengine.AddEntryScript("./TestClasses/Contract_Event.cs"); | ||
var debugInfo = testengine.ScriptEntry.debugInfo; | ||
Assert.IsTrue(debugInfo.HaveDictItem("hash")); | ||
Assert.AreEqual(debugInfo["hash"].type, MyJson.JsonType.Value_String); | ||
Assert.IsTrue(debugInfo.HaveDictItem("documents")); | ||
Assert.AreEqual(debugInfo["documents"].type, MyJson.JsonType.Array); | ||
Assert.IsTrue(debugInfo["documents"].AsList().Count == 1); | ||
Assert.IsTrue(debugInfo["documents"].AsList().All(n => n.type == MyJson.JsonType.Value_String)); | ||
Assert.IsTrue(debugInfo.HaveDictItem("methods")); | ||
Assert.AreEqual(debugInfo["methods"].type, MyJson.JsonType.Array); | ||
Assert.AreEqual(debugInfo["methods"].AsList().Count, 1); | ||
Assert.AreEqual(debugInfo["methods"].AsList()[0].asDict()["name"].AsString(), "Neo.Compiler.MSIL.UnitTests.TestClasses.Contract_Event,main"); | ||
Assert.IsTrue(debugInfo.HaveDictItem("events")); | ||
Assert.AreEqual(debugInfo["events"].type, MyJson.JsonType.Array); | ||
Assert.AreEqual(debugInfo["events"].AsList().Count, 1); | ||
Assert.AreEqual(debugInfo["events"].AsList()[0].asDict()["name"].AsString(), "Neo.Compiler.MSIL.UnitTests.TestClasses.Contract_Event,transfer"); | ||
} | ||
} | ||
} |
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
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.
params
field does not follow the specification. Either it should beparameters
or specification should be updated.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.
Thanks for catching this @AnnaShaleva. The specification is correct. I will update the NEON code and I've filed neo-project/neo-debugger#64 to track fixing the neo 3 preview 2 debugger
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.
FYI, turns out the spec was out of sync w/ the implementation of NEON 2, Neo Smart Contract Debugger for Neo 2 and neo-boa for neo 2.
params
andreturn
are the correct property names. Sorry for the confusion! Spec update in PR: https://github.com/ngdseattle/design-notes/pull/7