|  | #include "OrcTestCommon.h" | 
|  | #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" | 
|  | #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" | 
|  | #include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h" | 
|  | #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" | 
|  | #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" | 
|  | #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" | 
|  | #include "llvm/Testing/Support/Error.h" | 
|  | #include "gtest/gtest.h" | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::orc; | 
|  | using namespace llvm::jitlink; | 
|  |  | 
|  | static int initialTarget() { return 42; } | 
|  | static int middleTarget() { return 13; } | 
|  | static int finalTarget() { return 53; } | 
|  |  | 
|  | class JITLinkRedirectionManagerTest : public testing::Test { | 
|  | public: | 
|  | ~JITLinkRedirectionManagerTest() { | 
|  | if (ES) | 
|  | if (auto Err = ES->endSession()) | 
|  | ES->reportError(std::move(Err)); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | void SetUp() override { | 
|  | OrcNativeTarget::initialize(); | 
|  |  | 
|  | auto JTMB = JITTargetMachineBuilder::detectHost(); | 
|  | // Bail out if we can not detect the host. | 
|  | if (!JTMB) { | 
|  | consumeError(JTMB.takeError()); | 
|  | GTEST_SKIP(); | 
|  | } | 
|  | auto DLOrErr = JTMB->getDefaultDataLayoutForTarget(); | 
|  | if (!DLOrErr) { | 
|  | consumeError(DLOrErr.takeError()); | 
|  | GTEST_SKIP(); | 
|  | } | 
|  |  | 
|  | // COFF-ARM64 is not supported yet | 
|  | auto Triple = JTMB->getTargetTriple(); | 
|  | if (Triple.isOSBinFormatCOFF() && Triple.isAArch64()) | 
|  | GTEST_SKIP(); | 
|  |  | 
|  | if (Triple.isPPC()) | 
|  | GTEST_SKIP(); | 
|  |  | 
|  | auto PageSize = sys::Process::getPageSize(); | 
|  | if (!PageSize) { | 
|  | consumeError(PageSize.takeError()); | 
|  | GTEST_SKIP(); | 
|  | } | 
|  |  | 
|  | ES = std::make_unique<ExecutionSession>( | 
|  | std::make_unique<UnsupportedExecutorProcessControl>( | 
|  | nullptr, nullptr, JTMB->getTargetTriple().getTriple(), *PageSize)); | 
|  | JD = &ES->createBareJITDylib("main"); | 
|  | ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>( | 
|  | *ES, std::make_unique<InProcessMemoryManager>(*PageSize)); | 
|  | DL = std::make_unique<DataLayout>(std::move(*DLOrErr)); | 
|  | } | 
|  | JITDylib *JD{nullptr}; | 
|  | std::unique_ptr<ExecutionSession> ES; | 
|  | std::unique_ptr<ObjectLinkingLayer> ObjLinkingLayer; | 
|  | std::unique_ptr<DataLayout> DL; | 
|  | }; | 
|  |  | 
|  | TEST_F(JITLinkRedirectionManagerTest, BasicRedirectionOperation) { | 
|  | auto RM = JITLinkRedirectableSymbolManager::Create(*ObjLinkingLayer); | 
|  | // Bail out if we can not create | 
|  | if (!RM) { | 
|  | consumeError(RM.takeError()); | 
|  | GTEST_SKIP(); | 
|  | } | 
|  |  | 
|  | auto MakeTarget = [](int (*Fn)()) { | 
|  | return ExecutorSymbolDef(ExecutorAddr::fromPtr(Fn), | 
|  | JITSymbolFlags::Exported | | 
|  | JITSymbolFlags::Callable); | 
|  | }; | 
|  |  | 
|  | auto RedirectableSymbol = ES->intern("RedirectableTarget"); | 
|  | EXPECT_THAT_ERROR((*RM)->createRedirectableSymbols( | 
|  | JD->getDefaultResourceTracker(), | 
|  | {{RedirectableSymbol, MakeTarget(initialTarget)}}), | 
|  | Succeeded()); | 
|  |  | 
|  | auto RTDef = cantFail(ES->lookup({JD}, RedirectableSymbol)); | 
|  | auto RTPtr = RTDef.getAddress().toPtr<int (*)()>(); | 
|  | auto Result = RTPtr(); | 
|  | EXPECT_EQ(Result, 42) << "Failed to call initial target"; | 
|  |  | 
|  | EXPECT_THAT_ERROR( | 
|  | (*RM)->redirect(*JD, {{RedirectableSymbol, MakeTarget(middleTarget)}}), | 
|  | Succeeded()); | 
|  | Result = RTPtr(); | 
|  | EXPECT_EQ(Result, 13) << "Failed to call middle redirected target"; | 
|  |  | 
|  | EXPECT_THAT_ERROR( | 
|  | (*RM)->redirect(*JD, {{RedirectableSymbol, MakeTarget(finalTarget)}}), | 
|  | Succeeded()); | 
|  | Result = RTPtr(); | 
|  | EXPECT_EQ(Result, 53) << "Failed to call redirected target"; | 
|  | } |