1 //===--- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer tests ---===//
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
7 //===----------------------------------------------------------------------===//
9 #include "OrcTestCommon.h"
10 #include "llvm/ExecutionEngine/ExecutionEngine.h"
11 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
12 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
13 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
14 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
15 #include "llvm/IR/Constants.h"
16 #include "llvm/IR/LLVMContext.h"
17 #include "gtest/gtest.h"
21 using namespace llvm::orc
;
25 // Returns whether a non-alloc section was passed to the memory manager.
26 static bool testSetProcessAllSections(std::unique_ptr
<MemoryBuffer
> Obj
,
27 bool ProcessAllSections
) {
28 class MemoryManagerWrapper
: public SectionMemoryManager
{
30 MemoryManagerWrapper(bool &NonAllocSeen
) : NonAllocSeen(NonAllocSeen
) {}
31 uint8_t *allocateDataSection(uintptr_t Size
, unsigned Alignment
,
32 unsigned SectionID
, StringRef SectionName
,
33 bool IsReadOnly
) override
{
34 // We check for ".note.GNU-stack" here because it is currently the only
35 // non-alloc section seen in the module. If this changes in future any
36 // other non-alloc section would do here.
37 if (SectionName
== ".note.GNU-stack")
39 return SectionMemoryManager::allocateDataSection(
40 Size
, Alignment
, SectionID
, SectionName
, IsReadOnly
);
47 bool NonAllocSectionSeen
= false;
49 ExecutionSession
ES(std::make_unique
<UnsupportedExecutorProcessControl
>());
50 auto &JD
= ES
.createBareJITDylib("main");
51 auto Foo
= ES
.intern("foo");
53 RTDyldObjectLinkingLayer
ObjLayer(ES
, [&NonAllocSectionSeen
]() {
54 return std::make_unique
<MemoryManagerWrapper
>(NonAllocSectionSeen
);
57 auto OnResolveDoNothing
= [](Expected
<SymbolMap
> R
) {
58 cantFail(std::move(R
));
61 ObjLayer
.setProcessAllSections(ProcessAllSections
);
62 cantFail(ObjLayer
.add(JD
, std::move(Obj
)));
63 ES
.lookup(LookupKind::Static
, makeJITDylibSearchOrder(&JD
),
64 SymbolLookupSet(Foo
), SymbolState::Resolved
, OnResolveDoNothing
,
65 NoDependenciesToRegister
);
67 if (auto Err
= ES
.endSession())
68 ES
.reportError(std::move(Err
));
70 return NonAllocSectionSeen
;
73 TEST(RTDyldObjectLinkingLayerTest
, TestSetProcessAllSections
) {
75 auto M
= std::make_unique
<Module
>("", Context
);
76 M
->setTargetTriple("x86_64-unknown-linux-gnu");
78 // These values are only here to ensure that the module is non-empty.
79 // They are no longer relevant to the test.
80 Constant
*StrConstant
= ConstantDataArray::getString(Context
, "forty-two");
82 new GlobalVariable(*M
, StrConstant
->getType(), true,
83 GlobalValue::ExternalLinkage
, StrConstant
, "foo");
84 GV
->setUnnamedAddr(GlobalValue::UnnamedAddr::Global
);
85 GV
->setAlignment(Align(1));
87 // Initialize the native target in case this is the first unit test
88 // to try to build a TM.
89 OrcNativeTarget::initialize();
90 std::unique_ptr
<TargetMachine
> TM(EngineBuilder().selectTarget(
91 Triple(M
->getTargetTriple()), "", "", SmallVector
<std::string
, 1>()));
95 auto Obj
= cantFail(SimpleCompiler(*TM
)(*M
));
97 EXPECT_FALSE(testSetProcessAllSections(
98 MemoryBuffer::getMemBufferCopy(Obj
->getBuffer()), false))
99 << "Non-alloc section seen despite ProcessAllSections being false";
100 EXPECT_TRUE(testSetProcessAllSections(std::move(Obj
), true))
101 << "Expected to see non-alloc section when ProcessAllSections is true";
104 TEST(RTDyldObjectLinkingLayerTest
, TestOverrideObjectFlags
) {
106 OrcNativeTarget::initialize();
108 std::unique_ptr
<TargetMachine
> TM(
109 EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
110 SmallVector
<std::string
, 1>()));
115 // Our compiler is going to modify symbol visibility settings without telling
116 // ORC. This will test our ability to override the flags later.
117 class FunkySimpleCompiler
: public SimpleCompiler
{
119 FunkySimpleCompiler(TargetMachine
&TM
) : SimpleCompiler(TM
) {}
121 Expected
<CompileResult
> operator()(Module
&M
) override
{
122 auto *Foo
= M
.getFunction("foo");
123 assert(Foo
&& "Expected function Foo not found");
124 Foo
->setVisibility(GlobalValue::HiddenVisibility
);
125 return SimpleCompiler::operator()(M
);
129 // Create a module with two void() functions: foo and bar.
130 ThreadSafeContext
TSCtx(std::make_unique
<LLVMContext
>());
133 ModuleBuilder
MB(*TSCtx
.getContext(), TM
->getTargetTriple().str(), "dummy");
134 MB
.getModule()->setDataLayout(TM
->createDataLayout());
136 Function
*FooImpl
= MB
.createFunctionDecl(
137 FunctionType::get(Type::getVoidTy(*TSCtx
.getContext()), {}, false),
139 BasicBlock
*FooEntry
=
140 BasicBlock::Create(*TSCtx
.getContext(), "entry", FooImpl
);
141 IRBuilder
<> B1(FooEntry
);
144 Function
*BarImpl
= MB
.createFunctionDecl(
145 FunctionType::get(Type::getVoidTy(*TSCtx
.getContext()), {}, false),
147 BasicBlock
*BarEntry
=
148 BasicBlock::Create(*TSCtx
.getContext(), "entry", BarImpl
);
149 IRBuilder
<> B2(BarEntry
);
152 M
= ThreadSafeModule(MB
.takeModule(), std::move(TSCtx
));
155 // Create a simple stack and set the override flags option.
156 ExecutionSession ES
{std::make_unique
<UnsupportedExecutorProcessControl
>()};
157 auto &JD
= ES
.createBareJITDylib("main");
158 auto Foo
= ES
.intern("foo");
159 RTDyldObjectLinkingLayer
ObjLayer(
160 ES
, []() { return std::make_unique
<SectionMemoryManager
>(); });
161 IRCompileLayer
CompileLayer(ES
, ObjLayer
,
162 std::make_unique
<FunkySimpleCompiler
>(*TM
));
164 ObjLayer
.setOverrideObjectFlagsWithResponsibilityFlags(true);
166 cantFail(CompileLayer
.add(JD
, std::move(M
)));
168 LookupKind::Static
, makeJITDylibSearchOrder(&JD
), SymbolLookupSet(Foo
),
169 SymbolState::Resolved
,
170 [](Expected
<SymbolMap
> R
) { cantFail(std::move(R
)); },
171 NoDependenciesToRegister
);
173 if (auto Err
= ES
.endSession())
174 ES
.reportError(std::move(Err
));
177 TEST(RTDyldObjectLinkingLayerTest
, TestAutoClaimResponsibilityForSymbols
) {
179 OrcNativeTarget::initialize();
181 std::unique_ptr
<TargetMachine
> TM(
182 EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",
183 SmallVector
<std::string
, 1>()));
188 // Our compiler is going to add a new symbol without telling ORC.
189 // This will test our ability to auto-claim responsibility later.
190 class FunkySimpleCompiler
: public SimpleCompiler
{
192 FunkySimpleCompiler(TargetMachine
&TM
) : SimpleCompiler(TM
) {}
194 Expected
<CompileResult
> operator()(Module
&M
) override
{
195 Function
*BarImpl
= Function::Create(
196 FunctionType::get(Type::getVoidTy(M
.getContext()), {}, false),
197 GlobalValue::ExternalLinkage
, "bar", &M
);
198 BasicBlock
*BarEntry
=
199 BasicBlock::Create(M
.getContext(), "entry", BarImpl
);
200 IRBuilder
<> B(BarEntry
);
203 return SimpleCompiler::operator()(M
);
207 // Create a module with two void() functions: foo and bar.
208 ThreadSafeContext
TSCtx(std::make_unique
<LLVMContext
>());
211 ModuleBuilder
MB(*TSCtx
.getContext(), TM
->getTargetTriple().str(), "dummy");
212 MB
.getModule()->setDataLayout(TM
->createDataLayout());
214 Function
*FooImpl
= MB
.createFunctionDecl(
215 FunctionType::get(Type::getVoidTy(*TSCtx
.getContext()), {}, false),
217 BasicBlock
*FooEntry
=
218 BasicBlock::Create(*TSCtx
.getContext(), "entry", FooImpl
);
219 IRBuilder
<> B(FooEntry
);
222 M
= ThreadSafeModule(MB
.takeModule(), std::move(TSCtx
));
225 // Create a simple stack and set the override flags option.
226 ExecutionSession ES
{std::make_unique
<UnsupportedExecutorProcessControl
>()};
227 auto &JD
= ES
.createBareJITDylib("main");
228 auto Foo
= ES
.intern("foo");
229 RTDyldObjectLinkingLayer
ObjLayer(
230 ES
, []() { return std::make_unique
<SectionMemoryManager
>(); });
231 IRCompileLayer
CompileLayer(ES
, ObjLayer
,
232 std::make_unique
<FunkySimpleCompiler
>(*TM
));
234 ObjLayer
.setAutoClaimResponsibilityForObjectSymbols(true);
236 cantFail(CompileLayer
.add(JD
, std::move(M
)));
238 LookupKind::Static
, makeJITDylibSearchOrder(&JD
), SymbolLookupSet(Foo
),
239 SymbolState::Resolved
,
240 [](Expected
<SymbolMap
> R
) { cantFail(std::move(R
)); },
241 NoDependenciesToRegister
);
243 if (auto Err
= ES
.endSession())
244 ES
.reportError(std::move(Err
));
247 } // end anonymous namespace