Skip to content

Commit 7d99bc7

Browse files
committed
Implement ethdebug instruction json as struct hierarchy
1 parent 3aa86bf commit 7d99bc7

File tree

2 files changed

+75
-27
lines changed

2 files changed

+75
-27
lines changed

Diff for: libevmasm/Ethdebug.cpp

+74-26
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <libevmasm/Ethdebug.h>
2020

2121
#include <range/v3/algorithm/any_of.hpp>
22+
#include <range/v3/view/transform.hpp>
23+
#include <range/v3/to_container.hpp>
2224

2325
using namespace solidity;
2426
using namespace solidity::evmasm;
@@ -27,14 +29,64 @@ using namespace solidity::evmasm::ethdebug;
2729
namespace
2830
{
2931

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)
3183
{
3284
solAssert(_codeSectionIndex < _linkerObject.codeSectionLocations.size());
3385
solAssert(_codeSectionIndex < _assembly.codeSections().size());
3486
auto const& locations = _linkerObject.codeSectionLocations[_codeSectionIndex];
3587
auto const& codeSection = _assembly.codeSections().at(_codeSectionIndex);
3688

37-
std::vector<Json> instructions;
89+
std::vector<Instruction> instructions;
3890
instructions.reserve(codeSection.items.size());
3991

4092
bool const codeSectionContainsVerbatim = ranges::any_of(
@@ -51,8 +103,9 @@ std::vector<Json> codeSectionInstructions(Assembly const& _assembly, LinkerObjec
51103
solAssert(end <= _linkerObject.bytecode.size());
52104
solAssert(start < end);
53105
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;
56109
static size_t constexpr instructionSize = 1;
57110
if (start + instructionSize < end)
58111
{
@@ -61,56 +114,51 @@ std::vector<Json> codeSectionInstructions(Assembly const& _assembly, LinkerObjec
61114
_linkerObject.bytecode.begin() + static_cast<std::ptrdiff_t>(end)
62115
);
63116
solAssert(!argumentData.empty());
64-
operation["arguments"] = Json::array({util::toHex(argumentData, util::HexPrefix::Add)});
117+
operation.arguments = {argumentData};
65118
}
66119
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
81128
}
82-
}
129+
},
130+
.operation = operation
83131
});
84132
}
85133

86134
return instructions;
87135
}
88136

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)
90138
{
91139
auto const numCodeSections = _assembly.codeSections().size();
92140
solAssert(numCodeSections == _linkerObject.codeSectionLocations.size());
93141

94-
std::vector<Json> instructionInfo;
142+
std::vector<Instruction> instructionInfo;
95143
for (size_t codeSectionIndex = 0; codeSectionIndex < numCodeSections; ++codeSectionIndex)
96-
instructionInfo += codeSectionInstructions(_assembly, _linkerObject, _sourceId, codeSectionIndex);
144+
instructionInfo += codeSectionInstructions(_assembly, _linkerObject, _sourceID, codeSectionIndex);
97145
return instructionInfo;
98146
}
99147

100148
} // anonymous namespace
101149

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)
103151
{
104152
Json result = Json::object();
105153
result["contract"] = Json::object();
106154
result["contract"]["name"] = _name;
107155
result["contract"]["definition"] = Json::object();
108156
result["contract"]["definition"]["source"] = Json::object();
109-
result["contract"]["definition"]["source"]["id"] = _sourceId;
157+
result["contract"]["definition"]["source"]["id"] = _sourceID;
110158
if (_assembly)
111159
{
112160
result["environment"] = _assembly->isCreation() ? "create" : "call";
113-
result["instructions"] = programInstructions(*_assembly, _linkerObject, _sourceId);
161+
result["instructions"] = programInstructions(*_assembly, _linkerObject, _sourceID);
114162
}
115163
return result;
116164
}

Diff for: libevmasm/Ethdebug.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace solidity::evmasm::ethdebug
2727
{
2828

2929
// returns ethdebug/format/program.
30-
Json program(std::string_view _name, unsigned _sourceId, Assembly const* _assembly, LinkerObject const& _linkerObject);
30+
Json program(std::string_view _name, unsigned _sourceID, Assembly const* _assembly, LinkerObject const& _linkerObject);
3131

3232
// returns ethdebug/format/info/resources
3333
Json resources(std::vector<std::string> const& _sources, std::string const& _version);

0 commit comments

Comments
 (0)