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
+ size_t const assemblyItemIndex = currentInstruction.assemblyItemIndex ;
44
51
solAssert (end <= _linkerObject.bytecode .size ());
45
52
solAssert (start < end);
46
- solAssert (assemblyItemIndex < _assembly. codeSections (). at ( 0 ) .items .size ());
53
+ solAssert (assemblyItemIndex < codeSection .items .size ());
47
54
Json operation = Json::object ();
48
55
operation[" mnemonic" ] = instructionInfo (static_cast <Instruction>(_linkerObject.bytecode [start]), _assembly.evmVersion ()).name ;
49
56
static size_t constexpr instructionSize = 1 ;
@@ -56,25 +63,40 @@ Json programInstructions(Assembly const& _assembly, LinkerObject const& _linkerO
56
63
solAssert (!argumentData.empty ());
57
64
operation[" arguments" ] = Json::array ({util::toHex (argumentData, util::HexPrefix::Add)});
58
65
}
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
+ });
73
84
}
74
85
75
86
return instructions;
76
87
}
77
88
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
+
78
100
} // anonymous namespace
79
101
80
102
Json ethdebug::program (std::string_view _name, unsigned _sourceId, Assembly const * _assembly, LinkerObject const & _linkerObject)
0 commit comments