diff --git a/lib/Lift/Lift.cpp b/lib/Lift/Lift.cpp index 2cd3a4147..15b44f62c 100644 --- a/lib/Lift/Lift.cpp +++ b/lib/Lift/Lift.cpp @@ -29,6 +29,9 @@ alias A1("e", char LiftPass::ID; +using Register = llvm::RegisterPass; +static Register X("lift", "Lift Pass", true, true); + /// The interface with the PTC library. PTCInterface ptc = {}; diff --git a/lib/Lift/LoadBinaryPass.cpp b/lib/Lift/LoadBinaryPass.cpp index 78d773aa4..2d1489c9f 100644 --- a/lib/Lift/LoadBinaryPass.cpp +++ b/lib/Lift/LoadBinaryPass.cpp @@ -20,11 +20,14 @@ using namespace llvm; namespace { using namespace llvm::cl; -opt RawBinaryPath(Positional, desc("")); +opt RawBinaryPath("binary-path", desc("")); } // namespace char LoadBinaryWrapperPass::ID; +using Register = llvm::RegisterPass; +static Register X("load-binary", "Load Binary Pass", true, true); + LoadBinaryWrapperPass::LoadBinaryWrapperPass() : llvm::ModulePass(ID) { revng_check(RawBinaryPath.getNumOccurrences() == 1); auto Result = MemoryBuffer::getFileOrSTDIN(RawBinaryPath); diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index b17f20a82..6a154e596 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -74,8 +74,7 @@ add_custom_command( > "${CMAKE_BINARY_DIR}/lib/python/${PYTHON_GENERATED_MODEL_PATH}" DEPENDS generate-model-tuple-tree-code ) -add_custom_target(python-model-generated DEPENDS "${CMAKE_BINARY_DIR}/lib/python/${PYTHON_GENERATED_MODEL_PATH}") -add_dependencies(revng-lift python-model-generated) +add_custom_target(python-model-generated ALL DEPENDS "${CMAKE_BINARY_DIR}/lib/python/${PYTHON_GENERATED_MODEL_PATH}") # # Install revng.model (including autogenerated classes) @@ -107,7 +106,6 @@ python_module( TARGET_NAME revng-merge-dynamic MODULE_FILES ${MERGE_DYNAMIC_MODULE_FILES} ) -add_dependencies(revng-lift revng-merge-dynamic) # # Install revng.model_dump @@ -120,7 +118,6 @@ python_module( TARGET_NAME revng-dump-model MODULE_FILES ${DUMP_MODEL_MODULE_FILES} ) -add_dependencies(revng-lift revng-dump-model) # # Install revng.cli.support diff --git a/python/revng/cli/translate/__init__.py b/python/revng/cli/translate/__init__.py index 727922cc8..852aeaaf4 100644 --- a/python/revng/cli/translate/__init__.py +++ b/python/revng/cli/translate/__init__.py @@ -77,3 +77,77 @@ def run_translate(args, post_dash_dash_args, search_path, search_prefixes, comma to_execute = build_command_with_loads("revng-pipeline", command, search_path, search_prefixes) return run(to_execute + post_dash_dash_args, command_prefix) + + +# WIP: outline +def register_lift(subparsers): + parser = subparsers.add_parser("lift", description="revng lift wrapper") + parser.add_argument("input", type=str, nargs=1, help="Input binary to be lifted") + parser.add_argument("output", type=str, nargs=1, help="Output module path") + parser.add_argument("--record-asm", action="store_true") + parser.add_argument("--record-ptc", action="store_true") + parser.add_argument("--external", action="store_true") + parser.add_argument("--base", type=str) + parser.add_argument("--entry", type=str) + parser.add_argument("--debug-info", type=str) + parser.add_argument("--import-debug-info", type=str, action="append", default=[]) + + +def run_lift(args, post_dash_dash_args, search_path, search_prefixes, command_prefix): + # Run revng model import args.input + arg_or_empty = ( + lambda args, name: [f"--{name}={args.__dict__[name]}"] if args.__dict__[name] else [] + ) + + # WIP + from tempfile import NamedTemporaryFile + + with NamedTemporaryFile(suffix=".yml") as model, NamedTemporaryFile( + suffix=".ll" + ) as model_in_module: + run( + ( + [ + get_command("revng-model-import-binary", search_path), + args.input[0], + "-o", + model.name, + ] + + [f"--import-debug-info={value}" for value in args.import_debug_info] + + arg_or_empty(args, "base") + + arg_or_empty(args, "entry") + ), + command_prefix, + ) + + run( + [ + get_command("revng-model-inject", search_path), + model.name, + "/dev/null", + "-o", + model_in_module.name, + ], + command_prefix, + ) + + run( + ( + [ + get_command("revng", search_path), + "opt", + model_in_module.name, + "-o", + args.output[0], + "-load-binary", + f"-binary-path={args.input[0]}", + "-lift", + ] + + arg_or_empty(args, "external") + + arg_or_empty(args, "record_asm") + + arg_or_empty(args, "record_ptc") + ), + command_prefix, + ) + + # WIP NEXT: debug-info diff --git a/python/scripts/revng b/python/scripts/revng index 477afa824..a328a0d57 100755 --- a/python/scripts/revng +++ b/python/scripts/revng @@ -20,6 +20,7 @@ if prev_pythonpath: os.environ["PYTHONPATH"] += ":" + prev_pythonpath from revng.cli.translate import register_translate, run_translate +from revng.cli.translate import register_lift, run_lift from revng.cli.support import build_command_with_loads, set_verbose, get_command, run, log_error search_prefixes = [] @@ -126,6 +127,7 @@ def main(): subparsers = parser.add_subparsers(dest="command_name", help="sub-commands help") register_translate(subparsers) + register_lift(subparsers) subparsers.add_parser("cc", help="compile, link and translate transparently", add_help=False) subparsers.add_parser("opt", help="LLVM's opt with rev.ng passes", add_help=False) @@ -219,6 +221,8 @@ def run_command(args, unknown_args, post_dash_dash, search_path, search_prefixes return run_cc(all_args, search_path, search_prefixes, command_prefix) elif command == "translate": return run_translate(args, post_dash_dash, search_path, search_prefixes, command_prefix) + elif command == "lift": + return run_lift(args, post_dash_dash, search_path, search_prefixes, command_prefix) elif command == "model": if not all_args: log_error("No subcommand specified") diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index a92b6f561..0d40a680f 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -2,6 +2,5 @@ # This file is distributed under the MIT License. See LICENSE.md for details. # -add_subdirectory(lift) add_subdirectory(model) add_subdirectory(pipeline) diff --git a/tools/lift/CMakeLists.txt b/tools/lift/CMakeLists.txt deleted file mode 100644 index 5bde2698a..000000000 --- a/tools/lift/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# -# This file is distributed under the MIT License. See LICENSE.md for details. -# - -revng_add_executable(revng-lift - Main.cpp) - -target_link_libraries(revng-lift - revngLift - revngModelImporterBinary - ) diff --git a/tools/lift/Main.cpp b/tools/lift/Main.cpp deleted file mode 100644 index 40da7cacc..000000000 --- a/tools/lift/Main.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/// \file Main.cpp -/// \brief This file takes care of handling command-line parameters and loading -/// the appropriate flavour of libtinycode-*.so - -// -// This file is distributed under the MIT License. See LICENSE.md for details. -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/Object/Binary.h" -#include "llvm/Object/ELF.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/raw_os_ostream.h" - -#include "revng/Lift/Lift.h" -#include "revng/Model/Importer/Binary/BinaryImporter.h" -#include "revng/Model/Importer/Binary/BinaryImporterOptions.h" -#include "revng/Model/Importer/Dwarf/DwarfImporter.h" -#include "revng/Model/SerializeModelPass.h" -#include "revng/Support/CommandLine.h" -#include "revng/Support/Debug.h" -#include "revng/Support/IRAnnotators.h" -#include "revng/Support/IRHelpers.h" -#include "revng/Support/OriginalAssemblyAnnotationWriter.h" -#include "revng/Support/ResourceFinder.h" -#include "revng/Support/Statistics.h" - -// TODO: drop short aliases - -namespace { - -using namespace llvm::cl; -using std::string; - -opt InputPath(Positional, Required, desc("")); -opt OutputPath(Positional, Required, desc("")); - -} // namespace - -namespace DebugInfoType { - -/// \brief Type of debug information to produce -enum Values { - /// No debug information - None, - /// Produce a file containing the assembly code of the input binary - OriginalAssembly, - /// Produce the PTC as translated by libtinycode - PTC, - /// Prduce an LLVM IR with debug metadata referring to itself - LLVMIR -}; - -} // namespace DebugInfoType - -namespace DIT = DebugInfoType; - -static auto X = values(clEnumValN(DIT::None, "none", "no debug information"), - clEnumValN(DIT::OriginalAssembly, - "asm", - "debug information referred to the " - "assembly " - "of the input file"), - clEnumValN(DIT::PTC, - "ptc", - "debug information referred to the " - "Portable " - "Tiny Code"), - clEnumValN(DIT::LLVMIR, - "ll", - "debug information referred to the LLVM " - "IR")); -static opt DebugInfo("debug-info", - desc("emit debug information"), - X, - cat(MainCategory), - init(DIT::LLVMIR)); - -static alias A6("g", - desc("Alias for -debug-info"), - aliasopt(DebugInfo), - cat(MainCategory)); - -int main(int argc, const char *argv[]) { - // Enable LLVM stack trace - llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); - - HideUnrelatedOptions({ &MainCategory }); - ParseCommandLineOptions(argc, argv); - installStatistics(); - - auto MaybeBuffer = llvm::MemoryBuffer::getFileOrSTDIN(InputPath); - if (not MaybeBuffer) { - dbg << "Couldn't open input file\n"; - return EXIT_FAILURE; - } - llvm::MemoryBuffer &Buffer = **MaybeBuffer; - - TupleTree Model; - - revng_check(not importBinary(Model, InputPath, BaseAddress)); - - if (ImportDebugInfo.size() > 0) { - DwarfImporter Importer(Model); - for (const std::string &Path : ImportDebugInfo) - Importer.import(Path); - } - - // Translate everything - llvm::LLVMContext Context; - llvm::Module M("top", Context); - writeModel(*Model, M); - - // Perform lifting - llvm::legacy::PassManager PM; - PM.add(new LoadModelWrapperPass(Model)); - PM.add(new LoadBinaryWrapperPass(Buffer.getBuffer())); - PM.add(new LiftPass); - PM.run(M); - - OriginalAssemblyAnnotationWriter OAAW(M.getContext()); - - switch (DebugInfo) { - case DebugInfoType::None: - break; - - case DebugInfoType::OriginalAssembly: - createOriginalAssemblyDebugInfo(&M, OutputPath); - break; - - case DebugInfoType::PTC: - createPTCDebugInfo(&M, OutputPath); - break; - - case DebugInfoType::LLVMIR: - createSelfReferencingDebugInfo(&M, OutputPath, &OAAW); - break; - } - - std::ofstream OutputStream(OutputPath); - llvm::raw_os_ostream LLVMOutputStream(OutputStream); - M.print(LLVMOutputStream, &OAAW); -} diff --git a/tools/model/import/binary/Main.cpp b/tools/model/import/binary/Main.cpp index 5088892d5..c040bd2a6 100644 --- a/tools/model/import/binary/Main.cpp +++ b/tools/model/import/binary/Main.cpp @@ -13,27 +13,26 @@ #include "revng/Model/Importer/Binary/BinaryImporterOptions.h" #include "revng/Model/Importer/Dwarf/DwarfImporter.h" #include "revng/Model/ToolHelpers.h" +#include "revng/Support/CommandLine.h" using namespace llvm; using namespace cl; -static OptionCategory ThisToolCategory("Tool options", ""); - static opt InputFilename(Positional, - cat(ThisToolCategory), + cat(MainCategory), desc(""), init("-"), value_desc("filename")); static opt OutputFilename("o", - cat(ThisToolCategory), + cat(MainCategory), desc("Override output " "filename"), init("-"), value_desc("filename")); int main(int Argc, char *Argv[]) { - HideUnrelatedOptions({ &ThisToolCategory }); + HideUnrelatedOptions({ &MainCategory }); ParseCommandLineOptions(Argc, Argv); revng_check(BaseAddress % 4096 == 0, "Base address is not page aligned");