18
18
19
19
#include < libevmasm/Ethdebug.h>
20
20
21
+ #include < range/v3/algorithm/any_of.hpp>
22
+
21
23
using namespace solidity ;
22
24
using namespace solidity ::evmasm;
23
25
using namespace solidity ::evmasm::ethdebug;
24
26
25
27
namespace
26
28
{
27
29
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 )
29
31
{
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 )
39
47
{
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
+
51
+ // some instructions do not contribute to the bytecode
52
+ if (start == end)
53
+ continue ;
54
+
55
+ size_t const assemblyItemIndex = currentInstruction.assemblyItemIndex ;
44
56
solAssert (end <= _linkerObject.bytecode .size ());
45
57
solAssert (start < end);
46
- solAssert (assemblyItemIndex < _assembly. codeSections (). at ( 0 ) .items .size ());
58
+ solAssert (assemblyItemIndex < codeSection .items .size ());
47
59
Json operation = Json::object ();
48
60
operation[" mnemonic" ] = instructionInfo (static_cast <Instruction>(_linkerObject.bytecode [start]), _assembly.evmVersion ()).name ;
49
61
static size_t constexpr instructionSize = 1 ;
@@ -56,25 +68,40 @@ Json programInstructions(Assembly const& _assembly, LinkerObject const& _linkerO
56
68
solAssert (!argumentData.empty ());
57
69
operation[" arguments" ] = Json::array ({util::toHex (argumentData, util::HexPrefix::Add)});
58
70
}
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);
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
+ }
88
+ });
73
89
}
74
90
75
91
return instructions;
76
92
}
77
93
94
+ Json programInstructions (Assembly const & _assembly, LinkerObject const & _linkerObject, unsigned _sourceId)
95
+ {
96
+ auto const numCodeSections = _assembly.codeSections ().size ();
97
+ solAssert (numCodeSections == _linkerObject.codeSectionLocations .size ());
98
+
99
+ std::vector<Json> instructionInfo;
100
+ for (size_t codeSectionIndex = 0 ; codeSectionIndex < numCodeSections; ++codeSectionIndex)
101
+ instructionInfo += codeSectionInstructions (_assembly, _linkerObject, _sourceId, codeSectionIndex);
102
+ return instructionInfo;
103
+ }
104
+
78
105
} // anonymous namespace
79
106
80
107
Json ethdebug::program (std::string_view _name, unsigned _sourceId, Assembly const & _assembly, LinkerObject const & _linkerObject)
0 commit comments