-
Notifications
You must be signed in to change notification settings - Fork 6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
2,426 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
include(${CMAKE_SOURCE_DIR}/cmake/submodules.cmake) | ||
initialize_submodule(imgui) | ||
|
||
find_package(PkgConfig REQUIRED) | ||
pkg_check_modules(SDL2 REQUIRED sdl2) | ||
find_package(OpenGL REQUIRED) | ||
set(IMGUI_SOURCES | ||
${CMAKE_SOURCE_DIR}/deps/imgui/imgui.cpp | ||
${CMAKE_SOURCE_DIR}/deps/imgui/imgui_draw.cpp | ||
${CMAKE_SOURCE_DIR}/deps/imgui/imgui_tables.cpp | ||
${CMAKE_SOURCE_DIR}/deps/imgui/imgui_widgets.cpp | ||
${CMAKE_SOURCE_DIR}/deps/imgui/backends/imgui_impl_sdl2.cpp | ||
${CMAKE_SOURCE_DIR}/deps/imgui/backends/imgui_impl_opengl3.cpp | ||
) | ||
add_executable(ethdebug-tool | ||
src/main.cpp | ||
src/ui/UserInterface.cpp | ||
src/ui/UserInterface.h | ||
src/ui/Styles.h | ||
src/ui/HighlightedTextView.cpp | ||
src/ui/HighlightedTextView.h | ||
src/ui/InstructionTableView.h | ||
src/ui/InstructionTableView.cpp | ||
src/context/CodeContextDecoder.h | ||
src/Compiler.cpp | ||
src/Compiler.h | ||
src/data/InstructionInfo.h | ||
${IMGUI_SOURCES} | ||
) | ||
target_include_directories(ethdebug-tool PRIVATE | ||
${CMAKE_SOURCE_DIR}/tools/ethdebug/src | ||
${CMAKE_SOURCE_DIR}/deps | ||
${CMAKE_SOURCE_DIR}/deps/imgui | ||
${SDL2_INCLUDE_DIRS} | ||
) | ||
target_link_libraries(ethdebug-tool PRIVATE -L${SDL2_LIBRARY_DIRS} ${SDL2_LIBRARIES} OpenGL::GL solidity Boost::boost Boost::program_options) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
#include <Compiler.h> | ||
|
||
#include <libsolidity/interface/StandardCompiler.h> | ||
#include <libsolutil/JSON.h> | ||
|
||
#include <fstream> | ||
|
||
namespace ethdebug | ||
{ | ||
|
||
Compiler::Compiler(std::set<std::string> const& _sources, bool _optimize): m_files(_sources), m_optimize(_optimize) | ||
{ | ||
using namespace solidity::frontend; | ||
solidity::frontend::StandardCompiler compiler; | ||
|
||
solidity::Json input; | ||
input["language"] = "Solidity"; | ||
(void) m_optimize; | ||
|
||
solidity::Json sources; | ||
for (auto const& file: _sources) | ||
{ | ||
std::ifstream ifs(file); | ||
if (!ifs.is_open()) | ||
{ | ||
std::cerr << "Could not open: " << file << "\n"; | ||
continue; | ||
} | ||
std::string sourceContent((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>())); | ||
sources[file]["content"] = sourceContent; | ||
m_content[file] = sourceContent; | ||
} | ||
input["sources"] = sources; | ||
|
||
solidity::Json settings; | ||
solidity::Json outputSel; | ||
outputSel["*"]["*"] = nlohmann::json::array({"evm.bytecode.ethdebug", "evm.deployedBytecode.ethdebug", "ir"}); | ||
settings["outputSelection"] = outputSel; | ||
settings["viaIR"] = true; | ||
if (_optimize) | ||
{ | ||
nlohmann::json optimizer; | ||
optimizer["enabled"] = true; | ||
settings["optimizer"] = optimizer; | ||
} | ||
input["settings"] = settings; | ||
|
||
m_standardJson = compiler.compile(input); | ||
|
||
bool errors = false; | ||
if (m_standardJson.contains("errors")) | ||
for (auto const& error: m_standardJson["errors"]) | ||
if (error["severity"] == "error") | ||
{ | ||
std::cout << "Error: " << error["formattedMessage"].get<std::string>() << std::endl; | ||
errors = true; | ||
} | ||
if (errors) | ||
exit(1); | ||
|
||
parseArtifacts(); | ||
} | ||
|
||
void Compiler::parseArtifacts() | ||
{ | ||
m_ethdebug = m_standardJson["ethdebug"]; | ||
for (auto const& [fileName, contracts]: m_standardJson["contracts"].items()) | ||
{ | ||
for (auto const& [contractName, data]: contracts.items()) | ||
{ | ||
std::string irContent = m_standardJson["contracts"][fileName][contractName]["ir"].get<std::string>(); | ||
if (!irContent.empty()) | ||
{ | ||
Artifacts::Ptr artifact = std::make_shared<Artifacts>(); | ||
artifact->name = contractName; | ||
artifact->ethdebugCreation = data["evm"]["bytecode"]["ethdebug"]; | ||
artifact->ethdebugRuntime = data["evm"]["deployedBytecode"]["ethdebug"]; | ||
artifact->yulCode = irContent; | ||
artifact->solidityCode = m_content[fileName]; | ||
m_contracts[fileName][contractName] = artifact; | ||
} | ||
} | ||
} | ||
} | ||
|
||
Artifacts::Ptr Compiler::artifact(std::string const& _filename, std::string const& _contractName) | ||
{ | ||
if (m_contracts.count(_filename) && m_contracts[_filename].count(_contractName)) | ||
return m_contracts[_filename][_contractName]; | ||
return {}; | ||
} | ||
|
||
solidity::Json const& | ||
Compiler::instructions(std::string const& _filename, std::string const& _contractName, bool _creationCode) | ||
{ | ||
if (m_contracts.count(_filename) && m_contracts[_filename][_contractName]) | ||
return _creationCode | ||
? m_contracts[_filename][_contractName]->ethdebugCreation["instructions"] | ||
: m_contracts[_filename][_contractName]->ethdebugRuntime["instructions"]; | ||
|
||
static solidity::Json empty = solidity::Json::array(); | ||
return empty; | ||
} | ||
|
||
solidity::Json const& Compiler::instruction(std::string const& _filename, std::string const& _contractName, bool _creationCode, size_t _instructionIndex) | ||
{ | ||
solidity::Json const& instructions = this->instructions(_filename, _contractName, _creationCode); | ||
solAssert(instructions.is_array()); | ||
if (_instructionIndex >= 0 && _instructionIndex < instructions.size()) | ||
{ | ||
return instructions[_instructionIndex]; | ||
} | ||
static solidity::Json empty = solidity::Json::object(); | ||
return empty; | ||
} | ||
|
||
} // ethdebug |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#pragma once | ||
|
||
#include <libsolutil/JSON.h> | ||
#include <range/v3/range.hpp> | ||
#include <range/v3/view/map.hpp> | ||
#include <set> | ||
#include <string> | ||
|
||
namespace ethdebug | ||
{ | ||
|
||
struct Artifacts | ||
{ | ||
typedef std::shared_ptr<Artifacts> Ptr; | ||
|
||
std::string name; | ||
std::string solidityCode; | ||
std::string yulCode; | ||
solidity::Json ethdebugCreation; | ||
solidity::Json ethdebugRuntime; | ||
}; | ||
|
||
class Compiler | ||
{ | ||
public: | ||
typedef std::shared_ptr<Compiler> Ptr; | ||
Compiler(std::set<std::string> const& _sources, bool _optimize); | ||
|
||
std::vector<std::string> files() | ||
{ | ||
return m_contracts | ranges::views::keys | ranges::to<std::vector<std::string>>(); | ||
} | ||
|
||
std::vector<std::string> contracts(std::string const& _filename) | ||
{ | ||
return m_contracts[_filename] | ranges::views::keys | ranges::to<std::vector<std::string>>(); | ||
} | ||
|
||
Artifacts::Ptr artifact(std::string const& _filename, std::string const& _contractName); | ||
|
||
solidity::Json const& instructions(std::string const& _filename, std::string const& _contractName, bool _creationCode); | ||
|
||
solidity::Json const& instruction(std::string const& _filename, std::string const& _contractName, bool _creationCode, size_t _instructionIndex); | ||
|
||
solidity::Json const& ethdebug() const { return m_ethdebug; } | ||
|
||
private: | ||
void parseArtifacts(); | ||
|
||
std::set<std::string> m_files; | ||
bool m_optimize; | ||
std::map<std::string, std::string> m_content; | ||
solidity::Json m_ethdebug; | ||
std::map<std::string, std::map<std::string, Artifacts::Ptr>> m_contracts; | ||
solidity::Json m_standardJson; | ||
}; | ||
|
||
} // ethdebug |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#pragma once | ||
|
||
#include <fmt/printf.h> | ||
#include <libsolutil/JSON.h> | ||
|
||
namespace ethdebug | ||
{ | ||
|
||
inline std::string CodeContextDecoder(solidity::Json const& _ethdebug, solidity::Json const&, solidity::Json const& _context) | ||
{ | ||
if (_ethdebug.is_object() && _ethdebug.contains("sources") && _ethdebug["sources"].is_array() && _context.is_object() && _context.contains("source") && _context["source"].contains("id")) | ||
if (_context["source"]["id"].get<int>() >= 0 && _context["source"]["id"].get<uint64_t>() < _ethdebug["sources"].size()) | ||
return fmt::sprintf("Source: %s", (_ethdebug["sources"][(_context["source"]["id"].get<uint64_t>())]).get<std::string>()); | ||
return {}; | ||
} | ||
|
||
|
||
} // namespace ethdebug |
Oops, something went wrong.