RTDyldObjectLinkingLayerTest.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. //===- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer unit tests -===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
  10. #include "OrcTestCommon.h"
  11. #include "llvm/ExecutionEngine/ExecutionEngine.h"
  12. #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
  13. #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
  14. #include "llvm/ExecutionEngine/Orc/Legacy.h"
  15. #include "llvm/ExecutionEngine/Orc/NullResolver.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. };
  26. class SectionMemoryManagerWrapper : public SectionMemoryManager {
  27. public:
  28. int FinalizationCount = 0;
  29. int NeedsToReserveAllocationSpaceCount = 0;
  30. bool needsToReserveAllocationSpace() override {
  31. ++NeedsToReserveAllocationSpaceCount;
  32. return SectionMemoryManager::needsToReserveAllocationSpace();
  33. }
  34. bool finalizeMemory(std::string *ErrMsg = nullptr) override {
  35. ++FinalizationCount;
  36. return SectionMemoryManager::finalizeMemory(ErrMsg);
  37. }
  38. };
  39. TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
  40. class MemoryManagerWrapper : public SectionMemoryManager {
  41. public:
  42. MemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
  43. uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
  44. unsigned SectionID,
  45. StringRef SectionName,
  46. bool IsReadOnly) override {
  47. if (SectionName == ".debug_str")
  48. DebugSeen = true;
  49. return SectionMemoryManager::allocateDataSection(Size, Alignment,
  50. SectionID,
  51. SectionName,
  52. IsReadOnly);
  53. }
  54. private:
  55. bool &DebugSeen;
  56. };
  57. bool DebugSectionSeen = false;
  58. auto MM = std::make_shared<MemoryManagerWrapper>(DebugSectionSeen);
  59. ExecutionSession ES;
  60. RTDyldObjectLinkingLayer ObjLayer(ES, [&MM](VModuleKey) {
  61. return RTDyldObjectLinkingLayer::Resources{
  62. MM, std::make_shared<NullResolver>()};
  63. });
  64. LLVMContext Context;
  65. auto M = llvm::make_unique<Module>("", Context);
  66. M->setTargetTriple("x86_64-unknown-linux-gnu");
  67. Type *Int32Ty = IntegerType::get(Context, 32);
  68. GlobalVariable *GV =
  69. new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
  70. ConstantInt::get(Int32Ty, 42), "foo");
  71. GV->setSection(".debug_str");
  72. // Initialize the native target in case this is the first unit test
  73. // to try to build a TM.
  74. OrcNativeTarget::initialize();
  75. std::unique_ptr<TargetMachine> TM(
  76. EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
  77. SmallVector<std::string, 1>()));
  78. if (!TM)
  79. return;
  80. auto Obj = SimpleCompiler(*TM)(*M);
  81. {
  82. // Test with ProcessAllSections = false (the default).
  83. auto K = ES.allocateVModule();
  84. cantFail(ObjLayer.addObject(
  85. K, MemoryBuffer::getMemBufferCopy(Obj->getBuffer())));
  86. cantFail(ObjLayer.emitAndFinalize(K));
  87. EXPECT_EQ(DebugSectionSeen, false)
  88. << "Unexpected debug info section";
  89. cantFail(ObjLayer.removeObject(K));
  90. }
  91. {
  92. // Test with ProcessAllSections = true.
  93. ObjLayer.setProcessAllSections(true);
  94. auto K = ES.allocateVModule();
  95. cantFail(ObjLayer.addObject(K, std::move(Obj)));
  96. cantFail(ObjLayer.emitAndFinalize(K));
  97. EXPECT_EQ(DebugSectionSeen, true)
  98. << "Expected debug info section not seen";
  99. cantFail(ObjLayer.removeObject(K));
  100. }
  101. }
  102. TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
  103. if (!SupportsJIT)
  104. return;
  105. ExecutionSession ES;
  106. auto MM = std::make_shared<SectionMemoryManagerWrapper>();
  107. std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>> Resolvers;
  108. RTDyldObjectLinkingLayer ObjLayer(ES, [&](VModuleKey K) {
  109. auto I = Resolvers.find(K);
  110. assert(I != Resolvers.end() && "Missing resolver");
  111. auto R = std::move(I->second);
  112. Resolvers.erase(I);
  113. return RTDyldObjectLinkingLayer::Resources{MM, std::move(R)};
  114. });
  115. SimpleCompiler Compile(*TM);
  116. // Create a pair of modules that will trigger recursive finalization:
  117. // Module 1:
  118. // int bar() { return 42; }
  119. // Module 2:
  120. // int bar();
  121. // int foo() { return bar(); }
  122. //
  123. // Verify that the memory manager is only finalized once (for Module 2).
  124. // Failure suggests that finalize is being called on the inner RTDyld
  125. // instance (for Module 1) which is unsafe, as it will prevent relocation of
  126. // Module 2.
  127. ModuleBuilder MB1(Context, "", "dummy");
  128. {
  129. MB1.getModule()->setDataLayout(TM->createDataLayout());
  130. Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
  131. BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
  132. IRBuilder<> Builder(BarEntry);
  133. IntegerType *Int32Ty = IntegerType::get(Context, 32);
  134. Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
  135. Builder.CreateRet(FourtyTwo);
  136. }
  137. auto Obj1 = Compile(*MB1.getModule());
  138. ModuleBuilder MB2(Context, "", "dummy");
  139. {
  140. MB2.getModule()->setDataLayout(TM->createDataLayout());
  141. Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
  142. Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
  143. BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
  144. IRBuilder<> Builder(FooEntry);
  145. Builder.CreateRet(Builder.CreateCall(BarDecl));
  146. }
  147. auto Obj2 = Compile(*MB2.getModule());
  148. auto K1 = ES.allocateVModule();
  149. Resolvers[K1] = std::make_shared<NullResolver>();
  150. cantFail(ObjLayer.addObject(K1, std::move(Obj1)));
  151. auto K2 = ES.allocateVModule();
  152. auto LegacyLookup = [&](const std::string &Name) {
  153. return ObjLayer.findSymbol(Name, true);
  154. };
  155. Resolvers[K2] = createSymbolResolver(
  156. [&](const SymbolNameSet &Symbols) {
  157. return cantFail(
  158. getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup));
  159. },
  160. [&](std::shared_ptr<AsynchronousSymbolQuery> Query,
  161. const SymbolNameSet &Symbols) {
  162. return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
  163. });
  164. cantFail(ObjLayer.addObject(K2, std::move(Obj2)));
  165. cantFail(ObjLayer.emitAndFinalize(K2));
  166. cantFail(ObjLayer.removeObject(K2));
  167. // Finalization of module 2 should trigger finalization of module 1.
  168. // Verify that finalize on SMMW is only called once.
  169. EXPECT_EQ(MM->FinalizationCount, 1)
  170. << "Extra call to finalize";
  171. }
  172. TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
  173. if (!SupportsJIT)
  174. return;
  175. ExecutionSession ES;
  176. auto MM = std::make_shared<SectionMemoryManagerWrapper>();
  177. RTDyldObjectLinkingLayer ObjLayer(ES, [&MM](VModuleKey K) {
  178. return RTDyldObjectLinkingLayer::Resources{
  179. MM, std::make_shared<NullResolver>()};
  180. });
  181. SimpleCompiler Compile(*TM);
  182. // Create a pair of unrelated modules:
  183. //
  184. // Module 1:
  185. // int foo() { return 42; }
  186. // Module 2:
  187. // int bar() { return 7; }
  188. //
  189. // Both modules will share a memory manager. We want to verify that the
  190. // second object is not loaded before the first one is finalized. To do this
  191. // in a portable way, we abuse the
  192. // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
  193. // called once per object before any sections are allocated.
  194. ModuleBuilder MB1(Context, "", "dummy");
  195. {
  196. MB1.getModule()->setDataLayout(TM->createDataLayout());
  197. Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
  198. BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
  199. IRBuilder<> Builder(BarEntry);
  200. IntegerType *Int32Ty = IntegerType::get(Context, 32);
  201. Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
  202. Builder.CreateRet(FourtyTwo);
  203. }
  204. auto Obj1 = Compile(*MB1.getModule());
  205. ModuleBuilder MB2(Context, "", "dummy");
  206. {
  207. MB2.getModule()->setDataLayout(TM->createDataLayout());
  208. Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
  209. BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
  210. IRBuilder<> Builder(BarEntry);
  211. IntegerType *Int32Ty = IntegerType::get(Context, 32);
  212. Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
  213. Builder.CreateRet(Seven);
  214. }
  215. auto Obj2 = Compile(*MB2.getModule());
  216. auto K = ES.allocateVModule();
  217. cantFail(ObjLayer.addObject(K, std::move(Obj1)));
  218. cantFail(ObjLayer.addObject(ES.allocateVModule(), std::move(Obj2)));
  219. cantFail(ObjLayer.emitAndFinalize(K));
  220. cantFail(ObjLayer.removeObject(K));
  221. // Only one call to needsToReserveAllocationSpace should have been made.
  222. EXPECT_EQ(MM->NeedsToReserveAllocationSpaceCount, 1)
  223. << "More than one call to needsToReserveAllocationSpace "
  224. "(multiple unrelated objects loaded prior to finalization)";
  225. }
  226. TEST_F(RTDyldObjectLinkingLayerExecutionTest, TestNotifyLoadedSignature) {
  227. ExecutionSession ES;
  228. RTDyldObjectLinkingLayer ObjLayer(
  229. ES,
  230. [](VModuleKey) {
  231. return RTDyldObjectLinkingLayer::Resources{
  232. nullptr, std::make_shared<NullResolver>()};
  233. },
  234. [](VModuleKey, const object::ObjectFile &obj,
  235. const RuntimeDyld::LoadedObjectInfo &info) {});
  236. }
  237. } // end anonymous namespace