1079df9abSLang Hames //===--- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer tests ---===//
267de5d24SLang Hames //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
667de5d24SLang Hames //
767de5d24SLang Hames //===----------------------------------------------------------------------===//
867de5d24SLang Hames
967de5d24SLang Hames #include "OrcTestCommon.h"
1067de5d24SLang Hames #include "llvm/ExecutionEngine/ExecutionEngine.h"
1167de5d24SLang Hames #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
12079df9abSLang Hames #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
13079df9abSLang Hames #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
149a67b073SChandler Carruth #include "llvm/ExecutionEngine/SectionMemoryManager.h"
1567de5d24SLang Hames #include "llvm/IR/Constants.h"
1667de5d24SLang Hames #include "llvm/IR/LLVMContext.h"
1767de5d24SLang Hames #include "gtest/gtest.h"
18367ec775SSimon Pilgrim #include <string>
1967de5d24SLang Hames
2067de5d24SLang Hames using namespace llvm;
2167de5d24SLang Hames using namespace llvm::orc;
2267de5d24SLang Hames
2367de5d24SLang Hames namespace {
2467de5d24SLang Hames
25165321b3STomas Matheson // Returns whether a non-alloc section was passed to the memory manager.
testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,bool ProcessAllSections)26079df9abSLang Hames static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
27079df9abSLang Hames bool ProcessAllSections) {
285b518160SLang Hames class MemoryManagerWrapper : public SectionMemoryManager {
2967de5d24SLang Hames public:
30165321b3STomas Matheson MemoryManagerWrapper(bool &NonAllocSeen) : NonAllocSeen(NonAllocSeen) {}
3167de5d24SLang Hames uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
32079df9abSLang Hames unsigned SectionID, StringRef SectionName,
3367de5d24SLang Hames bool IsReadOnly) override {
34165321b3STomas Matheson // We check for ".note.GNU-stack" here because it is currently the only
35165321b3STomas Matheson // non-alloc section seen in the module. If this changes in future any
36165321b3STomas Matheson // other non-alloc section would do here.
37165321b3STomas Matheson if (SectionName == ".note.GNU-stack")
38165321b3STomas Matheson NonAllocSeen = true;
39079df9abSLang Hames return SectionMemoryManager::allocateDataSection(
40079df9abSLang Hames Size, Alignment, SectionID, SectionName, IsReadOnly);
4167de5d24SLang Hames }
42079df9abSLang Hames
4367de5d24SLang Hames private:
44165321b3STomas Matheson bool &NonAllocSeen;
4567de5d24SLang Hames };
4667de5d24SLang Hames
47165321b3STomas Matheson bool NonAllocSectionSeen = false;
485b518160SLang Hames
492487db1fSLang Hames ExecutionSession ES(std::make_unique<UnsupportedExecutorProcessControl>());
5085fb9976SLang Hames auto &JD = ES.createBareJITDylib("main");
51079df9abSLang Hames auto Foo = ES.intern("foo");
524b546c91SLang Hames
53165321b3STomas Matheson RTDyldObjectLinkingLayer ObjLayer(ES, [&NonAllocSectionSeen]() {
54165321b3STomas Matheson return std::make_unique<MemoryManagerWrapper>(NonAllocSectionSeen);
551cd3dd0bSLang Hames });
5667de5d24SLang Hames
57079df9abSLang Hames auto OnResolveDoNothing = [](Expected<SymbolMap> R) {
58079df9abSLang Hames cantFail(std::move(R));
59079df9abSLang Hames };
60079df9abSLang Hames
61079df9abSLang Hames ObjLayer.setProcessAllSections(ProcessAllSections);
620aec49c8SLang Hames cantFail(ObjLayer.add(JD, std::move(Obj)));
63674df13bSLang Hames ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),
64674df13bSLang Hames SymbolLookupSet(Foo), SymbolState::Resolved, OnResolveDoNothing,
65674df13bSLang Hames NoDependenciesToRegister);
66d4a8089fSLang Hames
670aec49c8SLang Hames if (auto Err = ES.endSession())
680aec49c8SLang Hames ES.reportError(std::move(Err));
690aec49c8SLang Hames
70165321b3STomas Matheson return NonAllocSectionSeen;
71079df9abSLang Hames }
72079df9abSLang Hames
TEST(RTDyldObjectLinkingLayerTest,TestSetProcessAllSections)73079df9abSLang Hames TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
7467de5d24SLang Hames LLVMContext Context;
750eaee545SJonas Devlieghere auto M = std::make_unique<Module>("", Context);
7667de5d24SLang Hames M->setTargetTriple("x86_64-unknown-linux-gnu");
77165321b3STomas Matheson
78165321b3STomas Matheson // These values are only here to ensure that the module is non-empty.
79165321b3STomas Matheson // They are no longer relevant to the test.
8086478d3dSbd1976llvm Constant *StrConstant = ConstantDataArray::getString(Context, "forty-two");
8186478d3dSbd1976llvm auto *GV =
8286478d3dSbd1976llvm new GlobalVariable(*M, StrConstant->getType(), true,
8386478d3dSbd1976llvm GlobalValue::ExternalLinkage, StrConstant, "foo");
8486478d3dSbd1976llvm GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
8586478d3dSbd1976llvm GV->setAlignment(Align(1));
8667de5d24SLang Hames
87d22badefSLang Hames // Initialize the native target in case this is the first unit test
88d22badefSLang Hames // to try to build a TM.
89d22badefSLang Hames OrcNativeTarget::initialize();
90079df9abSLang Hames std::unique_ptr<TargetMachine> TM(EngineBuilder().selectTarget(
91079df9abSLang Hames Triple(M->getTargetTriple()), "", "", SmallVector<std::string, 1>()));
9267de5d24SLang Hames if (!TM)
93*7fc87159SPaul Robinson GTEST_SKIP();
9467de5d24SLang Hames
95ce2207abSLang Hames auto Obj = cantFail(SimpleCompiler(*TM)(*M));
9667de5d24SLang Hames
97079df9abSLang Hames EXPECT_FALSE(testSetProcessAllSections(
98079df9abSLang Hames MemoryBuffer::getMemBufferCopy(Obj->getBuffer()), false))
99165321b3STomas Matheson << "Non-alloc section seen despite ProcessAllSections being false";
100079df9abSLang Hames EXPECT_TRUE(testSetProcessAllSections(std::move(Obj), true))
101165321b3STomas Matheson << "Expected to see non-alloc section when ProcessAllSections is true";
10267de5d24SLang Hames }
10367de5d24SLang Hames
TEST(RTDyldObjectLinkingLayerTest,TestOverrideObjectFlags)104079df9abSLang Hames TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {
10567de5d24SLang Hames
106079df9abSLang Hames OrcNativeTarget::initialize();
107079df9abSLang Hames
108079df9abSLang Hames std::unique_ptr<TargetMachine> TM(
109079df9abSLang Hames EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
110079df9abSLang Hames SmallVector<std::string, 1>()));
111079df9abSLang Hames
112079df9abSLang Hames if (!TM)
113*7fc87159SPaul Robinson GTEST_SKIP();
11467de5d24SLang Hames
115079df9abSLang Hames // Our compiler is going to modify symbol visibility settings without telling
116079df9abSLang Hames // ORC. This will test our ability to override the flags later.
117079df9abSLang Hames class FunkySimpleCompiler : public SimpleCompiler {
118079df9abSLang Hames public:
119079df9abSLang Hames FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {}
1204b546c91SLang Hames
12131eb8349SLogan Smith Expected<CompileResult> operator()(Module &M) override {
122079df9abSLang Hames auto *Foo = M.getFunction("foo");
123079df9abSLang Hames assert(Foo && "Expected function Foo not found");
124079df9abSLang Hames Foo->setVisibility(GlobalValue::HiddenVisibility);
125079df9abSLang Hames return SimpleCompiler::operator()(M);
12667de5d24SLang Hames }
1274b546c91SLang Hames };
1284b546c91SLang Hames
129079df9abSLang Hames // Create a module with two void() functions: foo and bar.
1300eaee545SJonas Devlieghere ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
131079df9abSLang Hames ThreadSafeModule M;
132079df9abSLang Hames {
133079df9abSLang Hames ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
134079df9abSLang Hames MB.getModule()->setDataLayout(TM->createDataLayout());
13567de5d24SLang Hames
136c0044118SJames Y Knight Function *FooImpl = MB.createFunctionDecl(
137c0044118SJames Y Knight FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
138c0044118SJames Y Knight "foo");
139079df9abSLang Hames BasicBlock *FooEntry =
140079df9abSLang Hames BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
141079df9abSLang Hames IRBuilder<> B1(FooEntry);
142079df9abSLang Hames B1.CreateRetVoid();
14367de5d24SLang Hames
144c0044118SJames Y Knight Function *BarImpl = MB.createFunctionDecl(
145c0044118SJames Y Knight FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
146c0044118SJames Y Knight "bar");
147079df9abSLang Hames BasicBlock *BarEntry =
148079df9abSLang Hames BasicBlock::Create(*TSCtx.getContext(), "entry", BarImpl);
149079df9abSLang Hames IRBuilder<> B2(BarEntry);
150079df9abSLang Hames B2.CreateRetVoid();
151079df9abSLang Hames
152079df9abSLang Hames M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
15367de5d24SLang Hames }
15467de5d24SLang Hames
155079df9abSLang Hames // Create a simple stack and set the override flags option.
1562487db1fSLang Hames ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
15785fb9976SLang Hames auto &JD = ES.createBareJITDylib("main");
158079df9abSLang Hames auto Foo = ES.intern("foo");
159079df9abSLang Hames RTDyldObjectLinkingLayer ObjLayer(
1600eaee545SJonas Devlieghere ES, []() { return std::make_unique<SectionMemoryManager>(); });
161ce2207abSLang Hames IRCompileLayer CompileLayer(ES, ObjLayer,
162ce2207abSLang Hames std::make_unique<FunkySimpleCompiler>(*TM));
163079df9abSLang Hames
164079df9abSLang Hames ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);
165079df9abSLang Hames
1660aec49c8SLang Hames cantFail(CompileLayer.add(JD, std::move(M)));
167d4a8089fSLang Hames ES.lookup(
168674df13bSLang Hames LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
169674df13bSLang Hames SymbolState::Resolved,
17023cb2e7fSLang Hames [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
171079df9abSLang Hames NoDependenciesToRegister);
1720aec49c8SLang Hames
1730aec49c8SLang Hames if (auto Err = ES.endSession())
1740aec49c8SLang Hames ES.reportError(std::move(Err));
175079df9abSLang Hames }
176079df9abSLang Hames
TEST(RTDyldObjectLinkingLayerTest,TestAutoClaimResponsibilityForSymbols)177079df9abSLang Hames TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {
178079df9abSLang Hames
179079df9abSLang Hames OrcNativeTarget::initialize();
180079df9abSLang Hames
181079df9abSLang Hames std::unique_ptr<TargetMachine> TM(
182079df9abSLang Hames EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
183079df9abSLang Hames SmallVector<std::string, 1>()));
184079df9abSLang Hames
185079df9abSLang Hames if (!TM)
186*7fc87159SPaul Robinson GTEST_SKIP();
18767de5d24SLang Hames
188079df9abSLang Hames // Our compiler is going to add a new symbol without telling ORC.
189079df9abSLang Hames // This will test our ability to auto-claim responsibility later.
190079df9abSLang Hames class FunkySimpleCompiler : public SimpleCompiler {
191079df9abSLang Hames public:
192079df9abSLang Hames FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {}
1934b546c91SLang Hames
19431eb8349SLogan Smith Expected<CompileResult> operator()(Module &M) override {
195c0044118SJames Y Knight Function *BarImpl = Function::Create(
196c0044118SJames Y Knight FunctionType::get(Type::getVoidTy(M.getContext()), {}, false),
197079df9abSLang Hames GlobalValue::ExternalLinkage, "bar", &M);
198079df9abSLang Hames BasicBlock *BarEntry =
199079df9abSLang Hames BasicBlock::Create(M.getContext(), "entry", BarImpl);
200079df9abSLang Hames IRBuilder<> B(BarEntry);
201079df9abSLang Hames B.CreateRetVoid();
2025b518160SLang Hames
203079df9abSLang Hames return SimpleCompiler::operator()(M);
204079df9abSLang Hames }
205079df9abSLang Hames };
20667de5d24SLang Hames
207079df9abSLang Hames // Create a module with two void() functions: foo and bar.
2080eaee545SJonas Devlieghere ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
209079df9abSLang Hames ThreadSafeModule M;
21067de5d24SLang Hames {
211079df9abSLang Hames ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy");
212079df9abSLang Hames MB.getModule()->setDataLayout(TM->createDataLayout());
213079df9abSLang Hames
214c0044118SJames Y Knight Function *FooImpl = MB.createFunctionDecl(
215c0044118SJames Y Knight FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false),
216c0044118SJames Y Knight "foo");
217079df9abSLang Hames BasicBlock *FooEntry =
218079df9abSLang Hames BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl);
219079df9abSLang Hames IRBuilder<> B(FooEntry);
220079df9abSLang Hames B.CreateRetVoid();
221079df9abSLang Hames
222079df9abSLang Hames M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx));
22367de5d24SLang Hames }
22467de5d24SLang Hames
225079df9abSLang Hames // Create a simple stack and set the override flags option.
2262487db1fSLang Hames ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
22785fb9976SLang Hames auto &JD = ES.createBareJITDylib("main");
228079df9abSLang Hames auto Foo = ES.intern("foo");
229fa769be5SEvgeniy Stepanov RTDyldObjectLinkingLayer ObjLayer(
2300eaee545SJonas Devlieghere ES, []() { return std::make_unique<SectionMemoryManager>(); });
231ce2207abSLang Hames IRCompileLayer CompileLayer(ES, ObjLayer,
232ce2207abSLang Hames std::make_unique<FunkySimpleCompiler>(*TM));
233079df9abSLang Hames
234079df9abSLang Hames ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true);
235079df9abSLang Hames
2360aec49c8SLang Hames cantFail(CompileLayer.add(JD, std::move(M)));
237d4a8089fSLang Hames ES.lookup(
238674df13bSLang Hames LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),
239674df13bSLang Hames SymbolState::Resolved,
24023cb2e7fSLang Hames [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
241079df9abSLang Hames NoDependenciesToRegister);
2420aec49c8SLang Hames
2430aec49c8SLang Hames if (auto Err = ES.endSession())
2440aec49c8SLang Hames ES.reportError(std::move(Err));
245705db63cSLang Hames }
246705db63cSLang Hames
24767de5d24SLang Hames } // end anonymous namespace
248