Skip to content

Commit 53e732b

Browse files
committed
Ethdebug instructions output over multiple code sections
1 parent 4f23c18 commit 53e732b

File tree

1 file changed

+51
-29
lines changed

1 file changed

+51
-29
lines changed

Diff for: libevmasm/Ethdebug.cpp

+51-29
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,39 @@
1818

1919
#include <libevmasm/Ethdebug.h>
2020

21+
#include <range/v3/algorithm/any_of.hpp>
22+
2123
using namespace solidity;
2224
using namespace solidity::evmasm;
2325
using namespace solidity::evmasm::ethdebug;
2426

2527
namespace
2628
{
2729

28-
Json programInstructions(Assembly const& _assembly, LinkerObject const& _linkerObject, unsigned _sourceId)
30+
std::vector<Json> codeSectionInstructions(Assembly const& _assembly, LinkerObject const& _linkerObject, unsigned _sourceId, size_t const _codeSectionIndex)
2931
{
30-
solUnimplementedAssert(_assembly.eofVersion() == std::nullopt, "ethdebug does not yet support EOF.");
31-
solUnimplementedAssert(_assembly.codeSections().size() == 1, "ethdebug does not yet support multiple code-sections.");
32-
for (auto const& instruction: _assembly.codeSections()[0].items)
33-
solUnimplementedAssert(instruction.type() != VerbatimBytecode, "Verbatim bytecode is currently not supported by ethdebug.");
34-
35-
solAssert(_linkerObject.codeSectionLocations.size() == 1);
36-
solAssert(_linkerObject.codeSectionLocations[0].end <= _linkerObject.bytecode.size());
37-
Json instructions = Json::array();
38-
for (size_t i = 0; i < _linkerObject.codeSectionLocations[0].instructionLocations.size(); ++i)
32+
solAssert(_codeSectionIndex < _linkerObject.codeSectionLocations.size());
33+
solAssert(_codeSectionIndex < _assembly.codeSections().size());
34+
auto const& locations = _linkerObject.codeSectionLocations[_codeSectionIndex];
35+
auto const& codeSection = _assembly.codeSections().at(_codeSectionIndex);
36+
37+
std::vector<Json> instructions;
38+
instructions.reserve(codeSection.items.size());
39+
40+
bool const codeSectionContainsVerbatim = ranges::any_of(
41+
codeSection.items,
42+
[](auto const& _instruction) { return _instruction.type() == VerbatimBytecode; }
43+
);
44+
solUnimplementedAssert(!codeSectionContainsVerbatim, "Verbatim bytecode is currently not supported by ethdebug.");
45+
46+
for (auto const& currentInstruction: locations.instructionLocations)
3947
{
40-
LinkerObject::InstructionLocation currentInstruction = _linkerObject.codeSectionLocations[0].instructionLocations[i];
41-
size_t start = currentInstruction.start;
42-
size_t end = currentInstruction.end;
43-
size_t assemblyItemIndex = currentInstruction.assemblyItemIndex;
48+
size_t const start = currentInstruction.start;
49+
size_t const end = currentInstruction.end;
50+
size_t const assemblyItemIndex = currentInstruction.assemblyItemIndex;
4451
solAssert(end <= _linkerObject.bytecode.size());
4552
solAssert(start < end);
46-
solAssert(assemblyItemIndex < _assembly.codeSections().at(0).items.size());
53+
solAssert(assemblyItemIndex < codeSection.items.size());
4754
Json operation = Json::object();
4855
operation["mnemonic"] = instructionInfo(static_cast<Instruction>(_linkerObject.bytecode[start]), _assembly.evmVersion()).name;
4956
static size_t constexpr instructionSize = 1;
@@ -56,25 +63,40 @@ Json programInstructions(Assembly const& _assembly, LinkerObject const& _linkerO
5663
solAssert(!argumentData.empty());
5764
operation["arguments"] = Json::array({util::toHex(argumentData, util::HexPrefix::Add)});
5865
}
59-
langutil::SourceLocation const& location = _assembly.codeSections().at(0).items.at(assemblyItemIndex).location();
60-
Json instruction = Json::object();
61-
instruction["offset"] = start;
62-
instruction["operation"] = operation;
63-
64-
instruction["context"] = Json::object();
65-
instruction["context"]["code"] = Json::object();
66-
instruction["context"]["code"]["source"] = Json::object();
67-
instruction["context"]["code"]["source"]["id"] = static_cast<int>(_sourceId);
68-
69-
instruction["context"]["code"]["range"] = Json::object();
70-
instruction["context"]["code"]["range"]["offset"] = location.start;
71-
instruction["context"]["code"]["range"]["length"] = location.end - location.start;
72-
instructions.emplace_back(instruction);
66+
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+
}
81+
}
82+
}
83+
});
7384
}
7485

7586
return instructions;
7687
}
7788

89+
Json programInstructions(Assembly const& _assembly, LinkerObject const& _linkerObject, unsigned _sourceId)
90+
{
91+
auto const numCodeSections = _assembly.codeSections().size();
92+
solAssert(numCodeSections == _linkerObject.codeSectionLocations.size());
93+
94+
std::vector<Json> instructionInfo;
95+
for (size_t codeSectionIndex = 0; codeSectionIndex < numCodeSections; ++codeSectionIndex)
96+
instructionInfo += codeSectionInstructions(_assembly, _linkerObject, _sourceId, codeSectionIndex);
97+
return instructionInfo;
98+
}
99+
78100
} // anonymous namespace
79101

80102
Json ethdebug::program(std::string_view _name, unsigned _sourceId, Assembly const* _assembly, LinkerObject const& _linkerObject)

0 commit comments

Comments
 (0)