RTDyldObjectLinkingLayerTest.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. //===--- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer tests ---===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "OrcTestCommon.h"
  9. #include "llvm/ExecutionEngine/ExecutionEngine.h"
  10. #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
  11. #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
  12. #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
  13. #include "llvm/ExecutionEngine/Orc/Legacy.h"
  14. #include "llvm/ExecutionEngine/Orc/NullResolver.h"
  15. #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
  16. #include "llvm/ExecutionEngine/SectionMemoryManager.h"
  17. #include "llvm/IR/Constants.h"
  18. #include "llvm/IR/LLVMContext.h"
  19. #include "gtest/gtest.h"
  20. using namespace llvm;
  21. using namespace llvm::orc;
  22. namespace {
  23. class RTDyldObjectLinkingLayerExecutionTest : public testing::Test,
  24. public OrcExecutionTest {};
  25. // Adds an object with a debug section to RuntimeDyld and then returns whether
  26. // the debug section was passed to the memory manager.
  27. static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
  28. bool ProcessAllSections) {
  29. class MemoryManagerWrapper : public SectionMemoryManager {
  30. public:
  31. MemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
  32. uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
  33. unsigned SectionID, StringRef SectionName,
  34. bool IsReadOnly) override {
  35. if (SectionName == ".debug_str")
  36. DebugSeen = true;
  37. return SectionMemoryManager::allocateDataSection(
  38. Size, Alignment, SectionID, SectionName, IsReadOnly);
  39. }
  40. private:
  41. bool &DebugSeen;
  42. };
  43. bool DebugSectionSeen = false;
  44. ExecutionSession ES;
  45. auto &JD = ES.createJITDylib("main");
  46. auto Foo = ES.intern("foo");
  47. RTDyldObjectLinkingLayer ObjLayer(ES, [&DebugSectionSeen]() {
  48. return std::make_unique<MemoryManagerWrapper>(DebugSectionSeen);
  49. });
  50. auto OnResolveDoNothing = [](Expected<SymbolMap> R) {
  51. cantFail(std::move(R));
  52. };
  53. ObjLayer.setProcessAllSections(ProcessAllSections);
  54. cantFail(ObjLayer.add(JD, std::move(Obj), ES.allocateVModule()));
  55. ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved,
  56. OnResolveDoNothing, NoDependenciesToRegister);
  57. return DebugSectionSeen;
  58. }
  59. TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
  60. LLVMContext Context;
  61. auto M = std::make_unique<Module>("", Context);
  62. M->setTargetTriple("x86_64-unknown-linux-gnu");
  63. Type *Int32Ty = IntegerType::get(Context, 32);
  64. GlobalVariable *GV =
  65. new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
  66. ConstantInt::get(Int32Ty, 42), "foo");
  67. GV->setSection(".debug_str");
  68. // Initialize the native target in case this is the first unit test
  69. // to try to build a TM.
  70. OrcNativeTarget::initialize();
  71. std::unique_ptr<TargetMachine> TM(EngineBuilder().selectTarget(
  72. Triple(M->getTargetTriple()), "", "", SmallVector<std::string, 1>()));
  73. if (!TM)
  74. return;
  75. auto Obj = SimpleCompiler(*TM)(*M);
  76. EXPECT_FALSE(testSetProcessAllSections(
  77. MemoryBuffer::getMemBufferCopy(Obj->getBuffer()), false))
  78. << "Debug section seen despite ProcessAllSections being false";
  79. EXPECT_TRUE(testSetProcessAllSections(std::move(Obj), true))
  80. << "Expected to see debug section when ProcessAllSections is true";
  81. }
  82. TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {
  83. OrcNativeTarget::initialize();
  84. std::unique_ptr<TargetMachine> TM(
  85. EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
  86. SmallVector<std::string, 1>()));
  87. if (!TM)
  88. return;
  89. // Our compiler is going to modify symbol visibility settings without telling
  90. // ORC. This will test our ability to override the flags later.
  91. class FunkySimpleCompiler : public SimpleCompiler {
  92. public:
  93. FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {}
  94. CompileResult operator()(Module &M) {
  95. auto *Foo = M.getFunction("foo");
  96. assert(Foo && "Expected function Foo not found");
  97. Foo->setVisibility(GlobalValue::HiddenVisibility);
  98. return SimpleCompiler::operator()(M);
  99. }
  100. };
  101. // Create a module with two void() functions: foo and bar.
  102. ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
  103. ThreadSafeModule M;
  104. {
  105. ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
  106. MB.getModule()->setDataLayout(TM->createDataLayout());
  107. Function *FooImpl = MB.createFunctionDecl(
  108. FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
  109. "foo");
  110. BasicBlock *FooEntry =
  111. BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
  112. IRBuilder<> B1(FooEntry);
  113. B1.CreateRetVoid();
  114. Function *BarImpl = MB.createFunctionDecl(
  115. FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
  116. "bar");
  117. BasicBlock *BarEntry =
  118. BasicBlock::Create(*TSCtx.getContext(), "entry", BarImpl);
  119. IRBuilder<> B2(BarEntry);
  120. B2.CreateRetVoid();
  121. M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
  122. }
  123. // Create a simple stack and set the override flags option.
  124. ExecutionSession ES;
  125. auto &JD = ES.createJITDylib("main");
  126. auto Foo = ES.intern("foo");
  127. RTDyldObjectLinkingLayer ObjLayer(
  128. ES, []() { return std::make_unique<SectionMemoryManager>(); });
  129. IRCompileLayer CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM));
  130. ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);
  131. cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule()));
  132. ES.lookup(
  133. JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved,
  134. [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
  135. NoDependenciesToRegister);
  136. }
  137. TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {
  138. OrcNativeTarget::initialize();
  139. std::unique_ptr<TargetMachine> TM(
  140. EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
  141. SmallVector<std::string, 1>()));
  142. if (!TM)
  143. return;
  144. // Our compiler is going to add a new symbol without telling ORC.
  145. // This will test our ability to auto-claim responsibility later.
  146. class FunkySimpleCompiler : public SimpleCompiler {
  147. public:
  148. FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {}
  149. CompileResult operator()(Module &M) {
  150. Function *BarImpl = Function::Create(
  151. FunctionType::get(Type::getVoidTy(M.getContext()), {}, false),
  152. GlobalValue::ExternalLinkage, "bar", &M);
  153. BasicBlock *BarEntry =
  154. BasicBlock::Create(M.getContext(), "entry", BarImpl);
  155. IRBuilder<> B(BarEntry);
  156. B.CreateRetVoid();
  157. return SimpleCompiler::operator()(M);
  158. }
  159. };
  160. // Create a module with two void() functions: foo and bar.
  161. ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
  162. ThreadSafeModule M;
  163. {
  164. ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
  165. MB.getModule()->setDataLayout(TM->createDataLayout());
  166. Function *FooImpl = MB.createFunctionDecl(
  167. FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
  168. "foo");
  169. BasicBlock *FooEntry =
  170. BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
  171. IRBuilder<> B(FooEntry);
  172. B.CreateRetVoid();
  173. M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
  174. }
  175. // Create a simple stack and set the override flags option.
  176. ExecutionSession ES;
  177. auto &JD = ES.createJITDylib("main");
  178. auto Foo = ES.intern("foo");
  179. RTDyldObjectLinkingLayer ObjLayer(
  180. ES, []() { return std::make_unique<SectionMemoryManager>(); });
  181. IRCompileLayer CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM));
  182. ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true);
  183. cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule()));
  184. ES.lookup(
  185. JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved,
  186. [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
  187. NoDependenciesToRegister);
  188. }
  189. } // end anonymous namespace