1 #include "OrcTestCommon.h" 2 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" 3 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" 4 #include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h" 5 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" 6 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" 7 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" 8 #include "llvm/Testing/Support/Error.h" 9 #include "gtest/gtest.h" 10 11 using namespace llvm; 12 using namespace llvm::orc; 13 using namespace llvm::jitlink; 14 15 static int initialTarget() { return 42; } 16 static int middleTarget() { return 13; } 17 static int finalTarget() { return 53; } 18 19 class JITLinkRedirectionManagerTest : public testing::Test { 20 public: 21 ~JITLinkRedirectionManagerTest() { 22 if (ES) 23 if (auto Err = ES->endSession()) 24 ES->reportError(std::move(Err)); 25 } 26 27 protected: 28 void SetUp() override { 29 auto JTMB = JITTargetMachineBuilder::detectHost(); 30 // Bail out if we can not detect the host. 31 if (!JTMB) { 32 consumeError(JTMB.takeError()); 33 GTEST_SKIP(); 34 } 35 auto DLOrErr = JTMB->getDefaultDataLayoutForTarget(); 36 if (!DLOrErr) { 37 consumeError(DLOrErr.takeError()); 38 GTEST_SKIP(); 39 } 40 41 // COFF-ARM64 is not supported yet 42 auto Triple = JTMB->getTargetTriple(); 43 if (Triple.isOSBinFormatCOFF() && Triple.isAArch64()) 44 GTEST_SKIP(); 45 46 if (Triple.isPPC()) 47 GTEST_SKIP(); 48 49 ES = std::make_unique<ExecutionSession>( 50 std::make_unique<UnsupportedExecutorProcessControl>( 51 nullptr, nullptr, JTMB->getTargetTriple().getTriple())); 52 JD = &ES->createBareJITDylib("main"); 53 ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>( 54 *ES, std::make_unique<InProcessMemoryManager>(16384)); 55 DL = std::make_unique<DataLayout>(std::move(*DLOrErr)); 56 } 57 JITDylib *JD{nullptr}; 58 std::unique_ptr<ExecutionSession> ES; 59 std::unique_ptr<ObjectLinkingLayer> ObjLinkingLayer; 60 std::unique_ptr<DataLayout> DL; 61 }; 62 63 TEST_F(JITLinkRedirectionManagerTest, BasicRedirectionOperation) { 64 auto RM = JITLinkRedirectableSymbolManager::Create(*ObjLinkingLayer, *JD); 65 // Bail out if we can not create 66 if (!RM) { 67 consumeError(RM.takeError()); 68 GTEST_SKIP(); 69 } 70 71 auto DefineTarget = [&](StringRef TargetName, ExecutorAddr Addr) { 72 SymbolStringPtr Target = ES->intern(TargetName); 73 cantFail(JD->define(std::make_unique<SimpleMaterializationUnit>( 74 SymbolFlagsMap({{Target, JITSymbolFlags::Exported}}), 75 [&](std::unique_ptr<MaterializationResponsibility> R) -> void { 76 // No dependencies registered, can't fail. 77 cantFail( 78 R->notifyResolved({{Target, {Addr, JITSymbolFlags::Exported}}})); 79 cantFail(R->notifyEmitted({})); 80 }))); 81 return cantFail(ES->lookup({JD}, TargetName)); 82 }; 83 84 auto InitialTarget = 85 DefineTarget("InitialTarget", ExecutorAddr::fromPtr(&initialTarget)); 86 auto MiddleTarget = 87 DefineTarget("MiddleTarget", ExecutorAddr::fromPtr(&middleTarget)); 88 auto FinalTarget = 89 DefineTarget("FinalTarget", ExecutorAddr::fromPtr(&finalTarget)); 90 91 auto RedirectableSymbol = ES->intern("RedirectableTarget"); 92 EXPECT_THAT_ERROR( 93 (*RM)->createRedirectableSymbols(JD->getDefaultResourceTracker(), 94 {{RedirectableSymbol, InitialTarget}}), 95 Succeeded()); 96 auto RTDef = cantFail(ES->lookup({JD}, RedirectableSymbol)); 97 98 auto RTPtr = RTDef.getAddress().toPtr<int (*)()>(); 99 auto Result = RTPtr(); 100 EXPECT_EQ(Result, 42) << "Failed to call initial target"; 101 102 EXPECT_THAT_ERROR((*RM)->redirect(*JD, {{RedirectableSymbol, MiddleTarget}}), 103 Succeeded()); 104 Result = RTPtr(); 105 EXPECT_EQ(Result, 13) << "Failed to call middle redirected target"; 106 107 EXPECT_THAT_ERROR((*RM)->redirect(*JD, {{RedirectableSymbol, FinalTarget}}), 108 Succeeded()); 109 Result = RTPtr(); 110 EXPECT_EQ(Result, 53) << "Failed to call redirected target"; 111 } 112