18
18
19
19
#include < libevmasm/Ethdebug.h>
20
20
21
+ #include < libevmasm/EthdebugSchema.h>
22
+
21
23
#include < range/v3/algorithm/any_of.hpp>
22
24
23
25
using namespace solidity ;
@@ -27,14 +29,66 @@ using namespace solidity::evmasm::ethdebug;
27
29
namespace
28
30
{
29
31
30
- std::vector<Json> codeSectionInstructions (Assembly const & _assembly, LinkerObject const & _linkerObject, unsigned _sourceId, size_t const _codeSectionIndex)
32
+ schema::program::Instruction::Operation instructionOperation (Assembly const & _assembly, LinkerObject const & _linkerObject, size_t const _start, size_t const _end)
33
+ {
34
+ solAssert (_end <= _linkerObject.bytecode .size ());
35
+ solAssert (_start < _end);
36
+ schema::program::Instruction::Operation operation;
37
+ operation.mnemonic = instructionInfo (static_cast <Instruction>(_linkerObject.bytecode [_start]), _assembly.evmVersion ()).name ;
38
+ static size_t constexpr instructionSize = 1 ;
39
+ if (_start + instructionSize < _end)
40
+ {
41
+ bytes const argumentData (
42
+ _linkerObject.bytecode .begin () + static_cast <std::ptrdiff_t >(_start) + instructionSize,
43
+ _linkerObject.bytecode .begin () + static_cast <std::ptrdiff_t >(_end)
44
+ );
45
+ solAssert (!argumentData.empty ());
46
+ operation.arguments = {{schema::data::HexValue{argumentData}}};
47
+ }
48
+ return operation;
49
+ }
50
+
51
+ schema::materials::SourceRange::Range locationRange (langutil::SourceLocation const & _location)
52
+ {
53
+ return {
54
+ .length = schema::data::Unsigned{_location.end - _location.start },
55
+ .offset = schema::data::Unsigned{_location.start }
56
+ };
57
+ }
58
+
59
+ schema::materials::Reference sourceReference (unsigned _sourceID)
60
+ {
61
+ return {
62
+ .id = schema::materials::ID{_sourceID},
63
+ .type = std::nullopt
64
+ };
65
+ }
66
+
67
+ std::optional<schema::program::Context> instructionContext (Assembly::CodeSection const & _codeSection, size_t _assemblyItemIndex, unsigned _sourceID)
68
+ {
69
+ solAssert (_assemblyItemIndex < _codeSection.items .size ());
70
+ langutil::SourceLocation const & location = _codeSection.items .at (_assemblyItemIndex).location ();
71
+ if (!location.isValid ())
72
+ return std::nullopt;
73
+
74
+ return schema::program::Context{
75
+ schema::materials::SourceRange{
76
+ .source = sourceReference (_sourceID),
77
+ .range = locationRange (location)
78
+ },
79
+ std::nullopt,
80
+ std::nullopt
81
+ };
82
+ }
83
+
84
+ std::vector<schema::program::Instruction> codeSectionInstructions (Assembly const & _assembly, LinkerObject const & _linkerObject, unsigned const _sourceID, size_t const _codeSectionIndex)
31
85
{
32
86
solAssert (_codeSectionIndex < _linkerObject.codeSectionLocations .size ());
33
87
solAssert (_codeSectionIndex < _assembly.codeSections ().size ());
34
88
auto const & locations = _linkerObject.codeSectionLocations [_codeSectionIndex];
35
89
auto const & codeSection = _assembly.codeSections ().at (_codeSectionIndex);
36
90
37
- std::vector<Json > instructions;
91
+ std::vector<schema::program::Instruction > instructions;
38
92
instructions.reserve (codeSection.items .size ());
39
93
40
94
bool const codeSectionContainsVerbatim = ranges::any_of (
@@ -52,72 +106,47 @@ std::vector<Json> codeSectionInstructions(Assembly const& _assembly, LinkerObjec
52
106
if (start == end)
53
107
continue ;
54
108
55
- size_t const assemblyItemIndex = currentInstruction.assemblyItemIndex ;
56
- solAssert (end <= _linkerObject.bytecode .size ());
57
- solAssert (start < end);
58
- solAssert (assemblyItemIndex < codeSection.items .size ());
59
- Json operation = Json::object ();
60
- operation[" mnemonic" ] = instructionInfo (static_cast <Instruction>(_linkerObject.bytecode [start]), _assembly.evmVersion ()).name ;
61
- static size_t constexpr instructionSize = 1 ;
62
- if (start + instructionSize < end)
63
- {
64
- bytes const argumentData (
65
- _linkerObject.bytecode .begin () + static_cast <std::ptrdiff_t >(start) + instructionSize,
66
- _linkerObject.bytecode .begin () + static_cast <std::ptrdiff_t >(end)
67
- );
68
- solAssert (!argumentData.empty ());
69
- operation[" arguments" ] = Json::array ({util::toHex (argumentData, util::HexPrefix::Add)});
70
- }
71
- langutil::SourceLocation const & location = codeSection.items .at (assemblyItemIndex).location ();
72
- instructions.emplace_back (Json{
73
- { " offset" , start },
74
- {" operation" , operation },
75
- {
76
- " context" , {
77
- " code" , {
78
- " source" , {
79
- { " id" , static_cast <int >(_sourceId) },
80
- },
81
- " range" , {
82
- { " offset" , location.start },
83
- { " length" , location.end - location.start }
84
- }
85
- }
86
- }
87
- }
109
+ instructions.emplace_back (schema::program::Instruction{
110
+ .offset = schema::data::Unsigned{start},
111
+ .operation = instructionOperation (_assembly, _linkerObject, start, end),
112
+ .context = instructionContext (codeSection, currentInstruction.assemblyItemIndex , _sourceID)
88
113
});
89
114
}
90
115
91
116
return instructions;
92
117
}
93
118
94
- Json programInstructions (Assembly const & _assembly, LinkerObject const & _linkerObject, unsigned _sourceId )
119
+ std::vector<schema::program::Instruction> programInstructions (Assembly const & _assembly, LinkerObject const & _linkerObject, unsigned const _sourceID )
95
120
{
96
121
auto const numCodeSections = _assembly.codeSections ().size ();
97
122
solAssert (numCodeSections == _linkerObject.codeSectionLocations .size ());
98
123
99
- std::vector<Json > instructionInfo;
124
+ std::vector<schema::program::Instruction > instructionInfo;
100
125
for (size_t codeSectionIndex = 0 ; codeSectionIndex < numCodeSections; ++codeSectionIndex)
101
- instructionInfo += codeSectionInstructions (_assembly, _linkerObject, _sourceId , codeSectionIndex);
126
+ instructionInfo += codeSectionInstructions (_assembly, _linkerObject, _sourceID , codeSectionIndex);
102
127
return instructionInfo;
103
128
}
104
129
105
130
} // anonymous namespace
106
131
107
- Json ethdebug::program (std::string_view _name, unsigned _sourceId , Assembly const & _assembly, LinkerObject const & _linkerObject)
132
+ Json ethdebug::program (std::string_view _name, unsigned _sourceID , Assembly const & _assembly, LinkerObject const & _linkerObject)
108
133
{
109
- Json result = Json::object ();
110
- result[" contract" ] = Json::object ();
111
- result[" contract" ][" name" ] = _name;
112
- result[" contract" ][" definition" ] = Json::object ();
113
- result[" contract" ][" definition" ][" source" ] = Json::object ();
114
- result[" contract" ][" definition" ][" source" ][" id" ] = _sourceId;
115
- if (_assembly)
116
- {
117
- result[" environment" ] = _assembly->isCreation () ? " create" : " call" ;
118
- result[" instructions" ] = programInstructions (*_assembly, _linkerObject, _sourceId);
119
- }
120
- return result;
134
+ return schema::Program{
135
+ .compilation = std::nullopt,
136
+ .contract = {
137
+ .name = std::string{_name},
138
+ .definition = {
139
+ .source = {
140
+ .id = {_sourceID},
141
+ .type = std::nullopt
142
+ },
143
+ .range = std::nullopt
144
+ }
145
+ },
146
+ .environment = _assembly.isCreation () ? schema::Program::Environment::CREATE : schema::Program::Environment::CALL,
147
+ .context = std::nullopt,
148
+ .instructions = programInstructions (_assembly, _linkerObject, _sourceID)
149
+ };
121
150
}
122
151
123
152
Json ethdebug::resources (std::vector<std::string> const & _sources, std::string const & _version)
0 commit comments