19
19
#include < libevmasm/Ethdebug.h>
20
20
21
21
#include < range/v3/algorithm/any_of.hpp>
22
+ #include < range/v3/view/transform.hpp>
23
+ #include < range/v3/to_container.hpp>
22
24
23
25
using namespace solidity ;
24
26
using namespace solidity ::evmasm;
@@ -27,14 +29,64 @@ 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
+ struct SourceRange
33
+ {
34
+ size_t sourceID;
35
+ int length;
36
+ int offset;
37
+ };
38
+ void to_json (Json& _json, SourceRange const & _sourceRange)
39
+ {
40
+ _json = { {" source" , { {" id" , static_cast <int >(_sourceRange.sourceID )}} }, { " range" , { { " offset" , _sourceRange.offset }, { " length" , _sourceRange.length } } } };
41
+ }
42
+
43
+ struct Context
44
+ {
45
+ SourceRange code;
46
+ };
47
+ void to_json (Json& _json, Context const & _context)
48
+ {
49
+ _json = { {" code" , _context.code } };
50
+ }
51
+
52
+ struct Operation
53
+ {
54
+ std::string mnemonic;
55
+ std::vector<bytes> arguments;
56
+ };
57
+ void to_json (Json& _json, Operation const & _operation)
58
+ {
59
+ _json = { {" mnemonic" , _operation.mnemonic } };
60
+ if (!_operation.arguments .empty ())
61
+ {
62
+ _json[" arguments" ] = _operation.arguments |
63
+ ranges::views::transform ([](bytes const & _argumentData) { return util::toHex (_argumentData, util::HexPrefix::Add); });
64
+ }
65
+ }
66
+
67
+ struct Instruction
68
+ {
69
+ size_t offset;
70
+ Context context;
71
+ Operation operation;
72
+ };
73
+ void to_json (Json& _json, Instruction const & _instruction)
74
+ {
75
+ _json = {
76
+ {" offset" , _instruction.offset },
77
+ {" context" , _instruction.context },
78
+ {" operation" , _instruction.operation }
79
+ };
80
+ }
81
+
82
+ std::vector<Instruction> codeSectionInstructions (Assembly const & _assembly, LinkerObject const & _linkerObject, unsigned const _sourceID, size_t const _codeSectionIndex)
31
83
{
32
84
solAssert (_codeSectionIndex < _linkerObject.codeSectionLocations .size ());
33
85
solAssert (_codeSectionIndex < _assembly.codeSections ().size ());
34
86
auto const & locations = _linkerObject.codeSectionLocations [_codeSectionIndex];
35
87
auto const & codeSection = _assembly.codeSections ().at (_codeSectionIndex);
36
88
37
- std::vector<Json > instructions;
89
+ std::vector<Instruction > instructions;
38
90
instructions.reserve (codeSection.items .size ());
39
91
40
92
bool const codeSectionContainsVerbatim = ranges::any_of (
@@ -51,8 +103,9 @@ std::vector<Json> codeSectionInstructions(Assembly const& _assembly, LinkerObjec
51
103
solAssert (end <= _linkerObject.bytecode .size ());
52
104
solAssert (start < end);
53
105
solAssert (assemblyItemIndex < codeSection.items .size ());
54
- Json operation = Json::object ();
55
- operation[" mnemonic" ] = instructionInfo (static_cast <Instruction>(_linkerObject.bytecode [start]), _assembly.evmVersion ()).name ;
106
+
107
+ Operation operation;
108
+ operation.mnemonic = instructionInfo (static_cast <evmasm::Instruction>(_linkerObject.bytecode [start]), _assembly.evmVersion ()).name ;
56
109
static size_t constexpr instructionSize = 1 ;
57
110
if (start + instructionSize < end)
58
111
{
@@ -61,56 +114,51 @@ std::vector<Json> codeSectionInstructions(Assembly const& _assembly, LinkerObjec
61
114
_linkerObject.bytecode .begin () + static_cast <std::ptrdiff_t >(end)
62
115
);
63
116
solAssert (!argumentData.empty ());
64
- operation[ " arguments" ] = Json::array ({ util::toHex ( argumentData, util::HexPrefix::Add)}) ;
117
+ operation. arguments = { argumentData} ;
65
118
}
66
119
langutil::SourceLocation const & location = codeSection.items .at (assemblyItemIndex).location ();
67
- instructions.emplace_back (Json{
68
- { " offset" , start },
69
- {" operation" , operation },
70
- {
71
- " context" , {
72
- " code" , {
73
- " source" , {
74
- { " id" , static_cast <int >(_sourceId) },
75
- },
76
- " range" , {
77
- { " offset" , location.start },
78
- { " length" , location.end - location.start }
79
- }
80
- }
120
+
121
+ instructions.emplace_back (Instruction{
122
+ .offset = start,
123
+ .context = {
124
+ .code = {
125
+ .sourceID = _sourceID,
126
+ .length = location.end - location.start ,
127
+ .offset = location.start
81
128
}
82
- }
129
+ },
130
+ .operation = operation
83
131
});
84
132
}
85
133
86
134
return instructions;
87
135
}
88
136
89
- Json programInstructions (Assembly const & _assembly, LinkerObject const & _linkerObject, unsigned _sourceId )
137
+ std::vector<Instruction> programInstructions (Assembly const & _assembly, LinkerObject const & _linkerObject, unsigned const _sourceID )
90
138
{
91
139
auto const numCodeSections = _assembly.codeSections ().size ();
92
140
solAssert (numCodeSections == _linkerObject.codeSectionLocations .size ());
93
141
94
- std::vector<Json > instructionInfo;
142
+ std::vector<Instruction > instructionInfo;
95
143
for (size_t codeSectionIndex = 0 ; codeSectionIndex < numCodeSections; ++codeSectionIndex)
96
- instructionInfo += codeSectionInstructions (_assembly, _linkerObject, _sourceId , codeSectionIndex);
144
+ instructionInfo += codeSectionInstructions (_assembly, _linkerObject, _sourceID , codeSectionIndex);
97
145
return instructionInfo;
98
146
}
99
147
100
148
} // anonymous namespace
101
149
102
- Json ethdebug::program (std::string_view _name, unsigned _sourceId , Assembly const * _assembly, LinkerObject const & _linkerObject)
150
+ Json ethdebug::program (std::string_view _name, unsigned _sourceID , Assembly const * _assembly, LinkerObject const & _linkerObject)
103
151
{
104
152
Json result = Json::object ();
105
153
result[" contract" ] = Json::object ();
106
154
result[" contract" ][" name" ] = _name;
107
155
result[" contract" ][" definition" ] = Json::object ();
108
156
result[" contract" ][" definition" ][" source" ] = Json::object ();
109
- result[" contract" ][" definition" ][" source" ][" id" ] = _sourceId ;
157
+ result[" contract" ][" definition" ][" source" ][" id" ] = _sourceID ;
110
158
if (_assembly)
111
159
{
112
160
result[" environment" ] = _assembly->isCreation () ? " create" : " call" ;
113
- result[" instructions" ] = programInstructions (*_assembly, _linkerObject, _sourceId );
161
+ result[" instructions" ] = programInstructions (*_assembly, _linkerObject, _sourceID );
114
162
}
115
163
return result;
116
164
}
0 commit comments