This commit is contained in:
Alessandro Di Federico
2021-05-31 17:09:03 +02:00
parent 5578d8f170
commit b874e3cf91
19 changed files with 432 additions and 54 deletions
@@ -41,6 +41,9 @@ public:
void mergeBackDerived(LLVMContainer &ToMerge) {
llvm::Linker TheLinker(*Module);
// WIP: drop body of stuff that it's already there
bool Result = TheLinker.linkInModule(std::move(ToMerge.Module),
llvm::Linker::OverrideFromSrc);
revng_assert(!Result, "Linker failed");
@@ -26,6 +26,7 @@ public:
cloneFiltered(const TargetContainer &Container) const final;
bool contains(const AutoEnforcerTarget &Target) const final {
// WIP: more to check?
return not Path.empty();
}
+27
View File
@@ -0,0 +1,27 @@
#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
// WIP: reduce headers
#include "revng/AutoEnforcer/AutoEnforcerTarget.h"
#include "revng/AutoEnforcer/BackingContainers.h"
#include "revng/AutoEnforcer/InputOutputContract.h"
#include "revng/Enforcers/RevngEnforcers.h"
#include "revng/AutoEnforcer/LLVMEnforcer.h"
namespace AutoEnforcer {
class CompileModuleEnforcer {
public:
static constexpr auto Name = "Compile Module Enforcer";
std::array<InputOutputContract, 1> getContract() const {
return {
InputOutputContract(Root, KindExactness::DerivedFrom, 0, Object, 1, true)
};
}
void run(DefaultLLVMContainer &TargetContainer, BinaryContainer &TargetBinary);
};
}
@@ -0,0 +1,35 @@
#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
// WIP: reduce headers
#include "revng/AutoEnforcer/AutoEnforcerTarget.h"
#include "revng/AutoEnforcer/BackingContainers.h"
#include "revng/AutoEnforcer/InputOutputContract.h"
#include "revng/Enforcers/RevngEnforcers.h"
#include "revng/AutoEnforcer/LLVMEnforcer.h"
namespace AutoEnforcer {
class LinkForTranslationEnforcer {
public:
static constexpr auto Name = "Link for Translation Enforcer";
std::array<InputOutputContract, 3> getContract() const {
return {
InputOutputContract(Root, KindExactness::DerivedFrom, 0, Translated, 3, true),
InputOutputContract(Binary, KindExactness::Exact, 1, Translated, 3, true),
InputOutputContract(Object, KindExactness::Exact, 2, Translated, 3, true)
};
}
void run(DefaultLLVMContainer &M,
BinaryContainer &InputBinary,
BinaryContainer &ObjectFile,
BinaryContainer &OutputBinary);
};
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
// WIP: reduce headers
#include "revng/AutoEnforcer/AutoEnforcerTarget.h"
#include "revng/AutoEnforcer/BackingContainers.h"
#include "revng/AutoEnforcer/InputOutputContract.h"
#include "revng/Enforcers/RevngEnforcers.h"
#include "revng/AutoEnforcer/LLVMEnforcer.h"
namespace AutoEnforcer {
class LinkSupportEnforcer {
public:
static constexpr auto Name = "LLVM Link Support Enforcer";
std::array<InputOutputContract, 0> getContract() const {
return {};
}
void run(DefaultLLVMContainer &TargetContainer);
};
}
+8 -42
View File
@@ -4,6 +4,8 @@
// This file is distributed under the MIT License. See LICENSE.md for details.
//
// WIP: split up
#include <array>
#include "llvm/IR/LegacyPassManager.h"
@@ -15,6 +17,8 @@
namespace AutoEnforcer {
class BinaryContainer;
extern Granularity RootGranularity;
extern Granularity FunctionsGranularity;
@@ -22,7 +26,6 @@ extern Kind CFepper;
extern Kind Binary;
extern Kind Root;
extern Kind RootIsolated;
extern Kind Support;
extern Kind Object;
extern Kind Translated;
@@ -43,47 +46,8 @@ public:
void registerPassess(llvm::legacy::PassManager &Manager) {}
};
class LLCEnforcer {
public:
static constexpr auto Name = "LLC Enforcer";
std::array<InputOutputContract, 1> getContract() const {
return {
InputOutputContract(Root, KindExactness::DerivedFrom, 0, Object, 1)
};
}
void
run(DefaultLLVMContainer &TargetContainer, BinaryContainer &TargetBinary) {
revng_abort("Not implemented");
}
};
class LinkSupportEnforcer {
public:
static constexpr auto Name = "LLVM Link Support Enforcer";
std::array<InputOutputContract, 1> getContract() const {
return {
InputOutputContract(Root, KindExactness::Exact, 0, Support, true)
};
}
void run(DefaultLLVMContainer &TargetContainer) {
revng_abort("Not implemented");
}
};
class LinkEnoforcer {
public:
static constexpr auto Name = "Link Enforcer";
std::array<InputOutputContract, 2> getContract() const {
return { InputOutputContract(Support, KindExactness::Exact, 0, Object, 1),
InputOutputContract(Root, KindExactness::Exact, 0, Dead) };
}
void run(DefaultLLVMContainer &SourceBinary, BinaryContainer &Binary) {
revng_abort("Not implemented, i guess here we need a container with "
"multiple objects files in it?");
}
};
class LinkEnoforcerWithFunctions {
#if 0
class LinkEnforcerWithFunctions {
public:
static constexpr auto Name = "Link Enforcer";
std::array<InputOutputContract, 3> getContract() const {
@@ -168,4 +132,6 @@ public:
}
};
#endif
} // namespace AutoEnforcer
+5
View File
@@ -4,9 +4,14 @@
revng_add_library_internal(revngEnforcers SHARED
BinaryContainer.cpp
CompileModule.cpp
Lift.cpp
LinkSupport.cpp
LinkForTranslation.cpp
RevngEnforcers.cpp)
llvm_map_components_to_libnames(LLVM_LIBRARIES MC)
target_link_libraries(revngEnforcers
revngSupport
revngLift
+70
View File
@@ -0,0 +1,70 @@
// WIP
#include <memory>
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/CodeGen/CommandFlags.inc"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/raw_os_ostream.h"
#include "revng/Enforcers/BinaryContainer.h"
#include "revng/Enforcers/CompileModule.h"
using namespace llvm;
void AutoEnforcer::CompileModuleEnforcer::run(DefaultLLVMContainer &TargetContainer,
BinaryContainer &TargetBinary) {
Module *M = &TargetContainer.getModule();
// Get the target specific parser.
std::string Error;
Triple TheTriple(M->getTargetTriple());
const Target *TheTarget = TargetRegistry::lookupTarget("",
TheTriple,
Error);
revng_assert(TheTarget);
TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
std::unique_ptr<TargetMachine> Target(TheTarget->createTargetMachine(TheTriple.getTriple(),
"",
"",
Options,
getRelocModel(),
getCodeModel(),
CodeGenOpt::Aggressive /* WIP */));
// Add the target data from the target machine, if it exists, or the module.
M->setDataLayout(Target->createDataLayout());
// This needs to be done after setting datalayout since it calls verifier
// to check debug info whereas verifier relies on correct datalayout.
UpgradeDebugInfo(*M);
LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target);
MachineModuleInfoWrapperPass *MMIWP =
new MachineModuleInfoWrapperPass(&LLVMTM);
std::error_code EC;
raw_fd_ostream OutputStream(TargetBinary.path(), EC);
revng_assert(!EC);
// Create pass manager
legacy::PassManager PM;
// Add an appropriate TargetLibraryInfo pass for the module's triple.
TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
PM.add(new TargetLibraryInfoWrapperPass(TLII));
bool Result = Target->addPassesToEmitFile(PM,
OutputStream,
nullptr,
CGFT_ObjectFile,
true,
MMIWP);
revng_assert(Result);
PM.run(*M);
}
+117
View File
@@ -0,0 +1,117 @@
// WIP
#include "llvm/Support/Program.h"
#include "revng/Model/LoadModelPass.h"
#include "revng/Enforcers/BinaryContainer.h"
#include "revng/Enforcers/LinkForTranslation.h"
#include "revng/Enforcers/Lift.h"
using namespace llvm;
using namespace llvm::sys;
extern int main(int argc, char *argv[]);
class ProgramRunner {
private:
std::string MainExecutable;
SmallVector<StringRef, 64> Paths;
public:
ProgramRunner() : MainExecutable(fs::getMainExecutable("", reinterpret_cast<void *>(main))) {
Paths = { { path::parent_path(MainExecutable) } };
// Appent PATH
char *Path = getenv("PATH");
if (Path == nullptr)
return;
StringRef(Path).split(Paths, ":");
}
template<typename R>
void run(llvm::StringRef ProgramName, R Args) {
auto MaybeProgramPath = findProgramByName(ProgramName, Paths);
revng_assert(MaybeProgramPath);
// Prepare actual arguments
std::vector<StringRef> StringRefs { *MaybeProgramPath };
for (std::string &Arg : Args)
StringRefs.push_back(Arg);
// Invoke linker
int ExitCode = ExecuteAndWait(StringRefs[0], StringRefs);
revng_assert(ExitCode == 0);
}
};
static ProgramRunner Runner;
void AutoEnforcer::LinkForTranslationEnforcer::run(DefaultLLVMContainer &M,
BinaryContainer &InputBinary,
BinaryContainer &ObjectFile,
BinaryContainer &OutputBinary) {
const auto &Model = loadModel(M.getModule());
const size_t PageSize = 4096;
BinaryContainer LinkerOutput;
std::vector<std::string> Args = {
"-lz",
"-lm",
"-lrt",
"-lpthread",
"-L./",
"-no-pie",
ObjectFile.path(),
"-o", LinkerOutput.path(),
("-Wl,-z,max-page-size=" + Twine(PageSize)).str(),
"-fuse-ld=bfd"
};
revng_assert(Model->Segments.size() > 0);
uint64_t Min = Model->Segments.begin()->Start.address();
uint64_t Max = Model->Segments.begin()->End.address();;
for (const auto &Segment : Model->Segments) {
Min = std::min(Min, Segment.Start.address());
Max = std::max(Max, Segment.End.address());
// Force section address
Args.push_back((Twine("-Wl,--section-start=.") + Segment.Name).str());
}
// Force text to start on the page after all the original program segments
auto PageAddress = PageSize * ((Max + PageSize - 1) / PageSize);
Args.push_back(("-Wl,-Ttext-segment=" + Twine(PageAddress).str()));
// Force a page before the lowest original address for the ELF header
Args.push_back(("-Wl,--section-start=.elfheaderhelper=" +
Twine::utohexstr(Min - 1)).str());
// Link required dynamic libraries
Args.push_back("-Wl,--no-as-needed");
for (std::string &ImportedLibrary : Model->ImportedLibraries)
Args.push_back((Twine("-l") + ImportedLibrary).str());
Args.push_back("-Wl,--as-needed");
// Prepare actual arguments
Runner.run("c++", Args);
// Invoke revng-merge-dynamic
Args = {
"merge-dynamic",
LinkerOutput.path(),
InputBinary.path(),
OutputBinary.path()
};
// Add base
if (BaseAddress.getNumOccurrences() > 0) {
Args.push_back("--base");
Args.push_back(Twine::utohexstr(BaseAddress).str());
}
Runner.run("revng", Args);
}
+21
View File
@@ -0,0 +1,21 @@
// WIP
#include "revng/Enforcers/LinkSupport.h"
#include "revng/Support/ResourceFinder.h"
void AutoEnforcer::LinkSupportEnforcer::run(DefaultLLVMContainer &TargetContainer) {
// WIP: option for trace
const char *SupportConfig = "normal";
// WIP
std::string ArchName = "mips";
std::string SupportSearchPath = ("/share/revng/support-"
+ ArchName
+ "-" + SupportConfig + ".ll");
auto OptionalSupportPath = revng::ResourceFinder.findFile(SupportSearchPath);
revng_assert(OptionalSupportPath.has_value(), "Cannot find the support module");
std::string SupportPath = OptionalSupportPath.value();
// WIP: load
// WIP: link
}
+2 -1
View File
@@ -1,3 +1,5 @@
// WIP
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
@@ -15,7 +17,6 @@ Granularity
Kind AutoEnforcer::Binary("Binary Kind", &RootGranularity);
Kind AutoEnforcer::Root("Root kind", &RootGranularity);
Kind AutoEnforcer::RootIsolated("Root Isolated Kind", Root, &RootGranularity);
Kind AutoEnforcer::Support("Support Kind", &RootGranularity);
Kind AutoEnforcer::Object("Object File Kind", &RootGranularity);
Kind AutoEnforcer::Translated("Translated Kind", &RootGranularity);
Kind AutoEnforcer::Dead("Dead Kind", &RootGranularity);
+1 -1
View File
@@ -2,7 +2,7 @@
# This file is distributed under the MIT License. See LICENSE.md for details.
#
revng_add_library_internal(revngLift
revng_add_library_internal(revngLift SHARED
BinaryFile.cpp
CodeGenerator.cpp
CPUStateAccessAnalysisPass.cpp
@@ -1,12 +1,14 @@
#include "revng/AutoEnforcer/AutoEnforcerLibraryRegistry.h"
#include "revng/AutoEnforcer/CopyEnforcer.h"
#include "revng/AutoEnforcer/RevngEnforcers.h"
using std::string;
using namespace llvm;
using namespace llvm::cl;
using namespace AutoEnforcer;
static Granularity RootGranularity("Root Granularity");
static Kind Root("Root", &RootGranularity);
class StringContainer : public BackingContainer<StringContainer> {
public:
using TargertContainer = BackingContainersStatus::TargetContainer;
@@ -112,7 +114,9 @@ public:
CopyEnforcer<StringContainer>(Root));
}
void registerKinds(llvm::StringMap<Kind *> &KindDictionary) override {}
void registerKinds(llvm::StringMap<Kind *> &KindDictionary) override {
KindDictionary["Root"] = &Root;
}
~ExampleRegistryLibrary() override = default;
};
+1 -3
View File
@@ -277,14 +277,12 @@ target_compile_definitions(test_upcastablepointer
target_include_directories(test_upcastablepointer
PRIVATE "${CMAKE_SOURCE_DIR}")
target_link_libraries(test_upcastablepointer
revngSupport
revngUnitTestHelpers
revngModel
Boost::unit_test_framework
${LLVM_LIBRARIES})
add_test(NAME test_upcastablepointer COMMAND ./bin/test_upcastablepointer)
set_tests_properties(test_upcastablepointer PROPERTIES LABELS "unit")
#
# test_autoenforcer
#
+1
View File
@@ -4,3 +4,4 @@
add_subdirectory(revng-lift)
add_subdirectory(revng-autoenforcer)
add_subdirectory(revng-translate2)
+2 -1
View File
@@ -5,6 +5,7 @@
revng_add_executable(revng-autoenforcer
Main.cpp)
# WIP: should not depend on revngLift
target_link_libraries(revng-autoenforcer
revngEnforcers
revngAutoEnforcer)
revngAutoEnforcer)
+1 -4
View File
@@ -87,10 +87,7 @@ public:
Loader.registerContainerFactory<Type>("LLVMContainer", **MaybeLLVMContext);
}
void registerKinds(llvm::StringMap<Kind *> &KindDictionary) override {
KindDictionary["Root"] = &Root;
KindDictionary["Isolated"] = &Isolated;
}
void registerKinds(llvm::StringMap<Kind *> &KindDictionary) override {}
~LLVMAutoEnforcerLibraryRegistry() override = default;
};
+10
View File
@@ -0,0 +1,10 @@
#
# This file is distributed under the MIT License. See LICENSE.md for details.
#
revng_add_executable(revng-translate2
Main.cpp)
target_link_libraries(revng-translate2
revngLift
revngEnforcers)
+93
View File
@@ -0,0 +1,93 @@
/// \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 <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <type_traits>
#include <vector>
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ELF.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_os_ostream.h"
#include "revng/AutoEnforcer/AutoEnforcer.h"
#include "revng/Enforcers/BinaryContainer.h"
#include "revng/Enforcers/CompileModule.h"
#include "revng/Enforcers/Lift.h"
#include "revng/Enforcers/LinkSupport.h"
#include "revng/Enforcers/LinkForTranslation.h"
#include "revng/Enforcers/RevngEnforcers.h"
#include "revng/Support/CommandLine.h"
#include "revng/Support/Debug.h"
#include "revng/Support/DebugHelper.h"
#include "revng/Support/OriginalAssemblyAnnotationWriter.h"
#include "revng/Support/Statistics.h"
#include "revng/Support/revng.h"
using namespace llvm::cl;
opt<std::string> InputPath(Positional, Required, desc("<input path>"));
opt<std::string> OutputPath(Positional, Required, desc("<output path>"));
int main(int argc, const char *argv[]) {
// Enable LLVM stack trace
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
HideUnrelatedOptions({ &MainCategory });
ParseCommandLineOptions(argc, argv);
installStatistics();
llvm::LLVMContext C;
using namespace AutoEnforcer;
PipelineRunner AE;
std::string Lifted = "lifted.ll";
std::string Binary = "binary";
std::string ObjectFile = "object.o";
std::string TranslatedBinary = "translated-binary";
AE.registerContainerFactory<DefaultLLVMContainerFactory>(Lifted, C);
AE.registerDefaultConstructibleFactory<BinaryContainer>(Binary);
AE.registerDefaultConstructibleFactory<BinaryContainer>(ObjectFile);
AE.registerDefaultConstructibleFactory<BinaryContainer>(TranslatedBinary);
AE.addStep("first_step",
bindEnforcer<LiftEnforcer>(Binary, Lifted),
bindEnforcer<LinkSupportEnforcer>(Lifted),
bindEnforcer<CompileModuleEnforcer>(Lifted, ObjectFile),
bindEnforcer<LinkForTranslationEnforcer>(Lifted,
Binary,
ObjectFile,
TranslatedBinary));
AE.addStep("end");
// Load input file
auto &BC = AE.getStartingContainer<BinaryContainer>(Binary);
cantFail(BC.loadFromDisk(InputPath));
// Establish goals
BackingContainersStatus Targets;
Targets.add(Lifted,
AutoEnforcerTarget({ AutoEnforcerQuantifier("root") }, Translated));
// Run the pipeline
auto Error = AE.run(Targets);
revng_assert(not Error);
// Save output file
auto &Final = AE.getFinalContainer<BinaryContainer>(TranslatedBinary);
cantFail(BC.storeToDisk(Final.path()));
}