Skip to content

Commit 0312a10

Browse files
committed
Add ethdebug schema
1 parent db6cb3f commit 0312a10

File tree

3 files changed

+317
-0
lines changed

3 files changed

+317
-0
lines changed

Diff for: libevmasm/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ set(sources
66
AssemblyItem.h
77
Ethdebug.cpp
88
Ethdebug.h
9+
EthdebugSchema.cpp
10+
EthdebugSchema.h
911
EVMAssemblyStack.cpp
1012
EVMAssemblyStack.h
1113
BlockDeduplicator.cpp

Diff for: libevmasm/EthdebugSchema.cpp

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
This file is part of solidity.
3+
4+
solidity is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
solidity is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with solidity. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
// SPDX-License-Identifier: GPL-3.0
18+
19+
#include <libevmasm/EthdebugSchema.h>
20+
21+
#include <libsolutil/Numeric.h>
22+
#include <libsolutil/Visitor.h>
23+
24+
using namespace solidity;
25+
using namespace solidity::evmasm::ethdebug;
26+
27+
void schema::data::to_json(Json& _json, HexValue const& _hexValue)
28+
{
29+
_json = util::toHex(_hexValue.value, util::HexPrefix::Add);
30+
}
31+
32+
void schema::data::to_json(Json& _json, Unsigned const& _unsigned)
33+
{
34+
std::visit(util::GenericVisitor{
35+
[&](HexValue const& _hexValue) { _json = _hexValue; },
36+
[&](std::uint64_t const _value) { _json = _value; }
37+
}, _unsigned.value);
38+
}
39+
40+
void schema::materials::to_json(Json& _json, ID const& _id)
41+
{
42+
std::visit(util::GenericVisitor{
43+
[&](std::string const& _hexValue) { _json = _hexValue; },
44+
[&](std::uint64_t const _value) { _json = _value; }
45+
}, _id.value);
46+
}
47+
48+
void schema::materials::to_json(Json& _json, Reference const& _source)
49+
{
50+
_json["id"] = _source.id;
51+
if (_source.type)
52+
_json["type"] = *_source.type == Reference::Type::Compilation ? "compilation" : "source";
53+
}
54+
55+
void schema::materials::to_json(Json& _json, SourceRange::Range const& _range)
56+
{
57+
_json["length"] = _range.length;
58+
_json["offset"] = _range.offset;
59+
}
60+
61+
62+
void schema::materials::to_json(Json& _json, SourceRange const& _sourceRange)
63+
{
64+
_json["source"] = _sourceRange.source;
65+
if (_sourceRange.range)
66+
_json["range"] = *_sourceRange.range;
67+
}
68+
69+
void schema::to_json(Json& _json, Program::Contract const& _contract)
70+
{
71+
if (_contract.name)
72+
_json["name"] = *_contract.name;
73+
_json["definition"] = _contract.definition;
74+
}
75+
76+
void schema::program::to_json(Json& _json, Context::Variable const& _contextVariable)
77+
{
78+
auto const numProperties =
79+
_contextVariable.identifier.has_value() +
80+
_contextVariable.declaration.has_value();
81+
solRequire(numProperties >= 1, EthdebugException, "Context variable has no properties.");
82+
if (_contextVariable.identifier)
83+
{
84+
solRequire(!_contextVariable.identifier->empty(), EthdebugException, "Variable identifier must not be empty.");
85+
_json["identifier"] = *_contextVariable.identifier;
86+
}
87+
if (_contextVariable.declaration)
88+
_json["declaration"] = *_contextVariable.declaration;
89+
}
90+
91+
void schema::program::to_json(Json& _json, Context const& _context)
92+
{
93+
solRequire(_context.code.has_value() + _context.remark.has_value() + _context.variables.has_value() >= 1, EthdebugException, "Context needs >=1 properties.");
94+
if (_context.code)
95+
_json["code"] = *_context.code;
96+
if (_context.variables)
97+
{
98+
solRequire(!_context.variables->empty(), EthdebugException, "Context variables must not be empty if provided.");
99+
_json["variables"] = *_context.variables;
100+
}
101+
if (_context.remark)
102+
_json["remark"] = *_context.remark;
103+
}
104+
105+
void schema::program::to_json(Json& _json, Instruction::Operation const& _operation)
106+
{
107+
_json = { {"mnemonic", _operation.mnemonic} };
108+
if (!_operation.arguments.empty())
109+
_json["arguments"] = _operation.arguments;
110+
}
111+
112+
void schema::program::to_json(Json& _json, Instruction const& _instruction)
113+
{
114+
_json["offset"] = _instruction.offset;
115+
if (_instruction.operation)
116+
_json["operation"] = *_instruction.operation;
117+
if (_instruction.context)
118+
_json["context"] = *_instruction.context;
119+
}
120+
121+
void schema::to_json(Json& _json, Program const& _program)
122+
{
123+
if (_program.compilation)
124+
_json["compilation"] = *_program.compilation;
125+
_json["contract"] = _program.contract;
126+
_json["environment"] = _program.environment;
127+
if (_program.context)
128+
_json["context"] = *_program.context;
129+
_json["instructions"] = _program.instructions;
130+
}
131+
132+
void schema::to_json(Json& _json, Program::Environment const& _environment)
133+
{
134+
switch (_environment)
135+
{
136+
case Program::Environment::CALL:
137+
_json = "call";
138+
break;
139+
case Program::Environment::CREATE:
140+
_json = "create";
141+
break;
142+
}
143+
}

Diff for: libevmasm/EthdebugSchema.h

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/*
2+
This file is part of solidity.
3+
4+
solidity is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
solidity is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with solidity. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
// SPDX-License-Identifier: GPL-3.0
18+
19+
#pragma once
20+
21+
#include <libsolutil/Common.h>
22+
#include <libsolutil/JSON.h>
23+
24+
#include <concepts>
25+
#include <optional>
26+
#include <variant>
27+
#include <vector>
28+
29+
namespace solidity::evmasm::ethdebug::schema
30+
{
31+
32+
struct EthdebugException: virtual util::Exception {};
33+
34+
namespace data
35+
{
36+
37+
struct HexValue
38+
{
39+
bytes value;
40+
};
41+
42+
struct Unsigned
43+
{
44+
template<std::unsigned_integral T>
45+
Unsigned(T const _value)
46+
{
47+
solRequire(static_cast<T>(_value) <= std::numeric_limits<std::uint64_t>::max(), EthdebugException, "Too large value.");
48+
value = static_cast<std::uint64_t>(_value);
49+
}
50+
template<std::signed_integral T>
51+
Unsigned(T const _value)
52+
{
53+
solRequire(_value >= 0, EthdebugException, "NonNegativeValue got negative value.");
54+
solRequire(static_cast<std::make_unsigned_t<T>>(_value) <= std::numeric_limits<std::uint64_t>::max(), EthdebugException, "Too large value.");
55+
value = static_cast<std::uint64_t>(_value);
56+
}
57+
Unsigned(HexValue&& _value): value(std::move(_value)) {}
58+
59+
std::variant<std::uint64_t, HexValue> value;
60+
};
61+
62+
}
63+
64+
namespace materials
65+
{
66+
67+
struct ID
68+
{
69+
std::variant<std::string, std::uint64_t> value;
70+
};
71+
72+
struct Reference
73+
{
74+
enum class Type { Compilation, Source };
75+
ID id;
76+
std::optional<Type> type;
77+
};
78+
79+
struct SourceRange
80+
{
81+
struct Range
82+
{
83+
data::Unsigned length;
84+
data::Unsigned offset;
85+
};
86+
87+
Reference source;
88+
std::optional<Range> range;
89+
};
90+
91+
}
92+
93+
namespace program
94+
{
95+
96+
struct Context
97+
{
98+
struct Variable
99+
{
100+
std::optional<std::string> identifier;
101+
std::optional<materials::SourceRange> declaration;
102+
// todo type
103+
// todo pointer according to ethdebug/format/spec/pointer
104+
};
105+
106+
std::optional<materials::SourceRange> code;
107+
std::optional<std::vector<Variable>> variables;
108+
std::optional<std::string> remark;
109+
};
110+
111+
struct Instruction
112+
{
113+
struct Operation
114+
{
115+
std::string mnemonic;
116+
std::vector<data::Unsigned> arguments;
117+
};
118+
119+
data::Unsigned offset;
120+
std::optional<Operation> operation;
121+
std::optional<Context> context;
122+
};
123+
124+
}
125+
126+
struct Program
127+
{
128+
enum class Environment
129+
{
130+
CALL, CREATE
131+
};
132+
133+
struct Contract
134+
{
135+
std::optional<std::string> name;
136+
materials::SourceRange definition;
137+
};
138+
139+
std::optional<materials::Reference> compilation;
140+
Contract contract;
141+
Environment environment;
142+
std::optional<program::Context> context;
143+
std::vector<program::Instruction> instructions;
144+
};
145+
146+
namespace data
147+
{
148+
void to_json(Json& _json, HexValue const& _hexValue);
149+
void to_json(Json& _json, Unsigned const& _unsigned);
150+
}
151+
152+
namespace materials
153+
{
154+
void to_json(Json& _json, ID const& _id);
155+
void to_json(Json& _json, Reference const& _source);
156+
void to_json(Json& _json, SourceRange::Range const& _range);
157+
void to_json(Json& _json, SourceRange const& _sourceRange);
158+
}
159+
160+
namespace program
161+
{
162+
void to_json(Json& _json, Context::Variable const& _contextVariable);
163+
void to_json(Json& _json, Context const& _context);
164+
void to_json(Json& _json, Instruction::Operation const& _operation);
165+
void to_json(Json& _json, Instruction const& _instruction);
166+
}
167+
168+
void to_json(Json& _json, Program::Contract const& _contract);
169+
void to_json(Json& _json, Program::Environment const& _environment);
170+
void to_json(Json& _json, Program const& _program);
171+
172+
}

0 commit comments

Comments
 (0)