Attributor: Do not treat pointer vectors as valid for unsupported attributes (#121149)
[llvm-project.git] / llvm / unittests / ExecutionEngine / Orc / ObjectLinkingLayerTest.cpp
blob31a48e86539fdfe8ec07ebabb22cfc0af9124694
1 //===-------- ObjectLinkingLayerTest.cpp - ObjectLinkingLayer 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 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
10 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
11 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
12 #include "llvm/ExecutionEngine/JITLink/x86_64.h"
13 #include "llvm/ExecutionEngine/JITSymbol.h"
14 #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
15 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
16 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
17 #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
18 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
19 #include "llvm/Testing/Support/Error.h"
20 #include "gtest/gtest.h"
22 using namespace llvm;
23 using namespace llvm::jitlink;
24 using namespace llvm::orc;
26 namespace {
28 const char BlockContentBytes[] = {0x01, 0x02, 0x03, 0x04,
29 0x05, 0x06, 0x07, 0x08};
31 ArrayRef<char> BlockContent(BlockContentBytes);
33 class ObjectLinkingLayerTest : public testing::Test {
34 public:
35 ~ObjectLinkingLayerTest() {
36 if (auto Err = ES.endSession())
37 ES.reportError(std::move(Err));
40 protected:
41 ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
42 JITDylib &JD = ES.createBareJITDylib("main");
43 ObjectLinkingLayer ObjLinkingLayer{
44 ES, std::make_unique<InProcessMemoryManager>(4096)};
47 TEST_F(ObjectLinkingLayerTest, AddLinkGraph) {
48 auto G = std::make_unique<LinkGraph>(
49 "foo", ES.getSymbolStringPool(), Triple("x86_64-apple-darwin"), 8,
50 llvm::endianness::little, x86_64::getEdgeKindName);
52 auto &Sec1 = G->createSection("__data", MemProt::Read | MemProt::Write);
53 auto &B1 = G->createContentBlock(Sec1, BlockContent,
54 orc::ExecutorAddr(0x1000), 8, 0);
55 G->addDefinedSymbol(B1, 4, "_X", 4, Linkage::Strong, Scope::Default, false,
56 false);
57 G->addDefinedSymbol(B1, 4, "_Y", 4, Linkage::Weak, Scope::Default, false,
58 false);
59 G->addDefinedSymbol(B1, 4, "_Z", 4, Linkage::Strong, Scope::Hidden, false,
60 false);
61 G->addDefinedSymbol(B1, 4, "_W", 4, Linkage::Strong, Scope::Default, true,
62 false);
64 EXPECT_THAT_ERROR(ObjLinkingLayer.add(JD, std::move(G)), Succeeded());
66 EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_X"), Succeeded());
69 TEST_F(ObjectLinkingLayerTest, ResourceTracker) {
70 // This test transfers allocations to previously unknown ResourceTrackers,
71 // while increasing the number of trackers in the ObjectLinkingLayer, which
72 // may invalidate some iterators internally.
73 std::vector<ResourceTrackerSP> Trackers;
74 for (unsigned I = 0; I < 64; I++) {
75 auto G = std::make_unique<LinkGraph>(
76 "foo", ES.getSymbolStringPool(), Triple("x86_64-apple-darwin"), 8,
77 llvm::endianness::little, x86_64::getEdgeKindName);
79 auto &Sec1 = G->createSection("__data", MemProt::Read | MemProt::Write);
80 auto &B1 = G->createContentBlock(Sec1, BlockContent,
81 orc::ExecutorAddr(0x1000), 8, 0);
82 llvm::SmallString<0> SymbolName;
83 SymbolName += "_X";
84 SymbolName += std::to_string(I);
85 G->addDefinedSymbol(B1, 4, SymbolName, 4, Linkage::Strong, Scope::Default,
86 false, false);
88 auto RT1 = JD.createResourceTracker();
89 EXPECT_THAT_ERROR(ObjLinkingLayer.add(RT1, std::move(G)), Succeeded());
90 EXPECT_THAT_EXPECTED(ES.lookup(&JD, SymbolName), Succeeded());
92 auto RT2 = JD.createResourceTracker();
93 RT1->transferTo(*RT2);
95 Trackers.push_back(RT2);
99 TEST_F(ObjectLinkingLayerTest, ClaimLateDefinedWeakSymbols) {
100 // Check that claiming weak symbols works as expected.
102 // To do this we'll need a custom plugin to inject some new symbols during
103 // the link.
104 class TestPlugin : public ObjectLinkingLayer::Plugin {
105 public:
106 void modifyPassConfig(MaterializationResponsibility &MR,
107 jitlink::LinkGraph &G,
108 jitlink::PassConfiguration &Config) override {
109 Config.PrePrunePasses.insert(
110 Config.PrePrunePasses.begin(), [](LinkGraph &G) {
111 auto *DataSec = G.findSectionByName("__data");
112 auto &DataBlock = G.createContentBlock(
113 *DataSec, BlockContent, orc::ExecutorAddr(0x2000), 8, 0);
114 G.addDefinedSymbol(DataBlock, 4, "_x", 4, Linkage::Weak,
115 Scope::Default, false, false);
117 auto &TextSec =
118 G.createSection("__text", MemProt::Read | MemProt::Write);
119 auto &FuncBlock = G.createContentBlock(
120 TextSec, BlockContent, orc::ExecutorAddr(0x3000), 8, 0);
121 G.addDefinedSymbol(FuncBlock, 4, "_f", 4, Linkage::Weak,
122 Scope::Default, true, false);
124 return Error::success();
128 Error notifyFailed(MaterializationResponsibility &MR) override {
129 llvm_unreachable("unexpected error");
132 Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
133 return Error::success();
135 void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
136 ResourceKey SrcKey) override {
137 llvm_unreachable("unexpected resource transfer");
141 ObjLinkingLayer.addPlugin(std::make_unique<TestPlugin>());
142 auto G = std::make_unique<LinkGraph>(
143 "foo", ES.getSymbolStringPool(), Triple("x86_64-apple-darwin"), 8,
144 llvm::endianness::little, getGenericEdgeKindName);
146 auto &DataSec = G->createSection("__data", MemProt::Read | MemProt::Write);
147 auto &DataBlock = G->createContentBlock(DataSec, BlockContent,
148 orc::ExecutorAddr(0x1000), 8, 0);
149 G->addDefinedSymbol(DataBlock, 4, "_anchor", 4, Linkage::Weak, Scope::Default,
150 false, true);
152 EXPECT_THAT_ERROR(ObjLinkingLayer.add(JD, std::move(G)), Succeeded());
154 EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_anchor"), Succeeded());
157 TEST_F(ObjectLinkingLayerTest, HandleErrorDuringPostAllocationPass) {
158 // We want to confirm that Errors in post allocation passes correctly
159 // abandon the in-flight allocation and report an error.
160 class TestPlugin : public ObjectLinkingLayer::Plugin {
161 public:
162 ~TestPlugin() { EXPECT_TRUE(ErrorReported); }
164 void modifyPassConfig(MaterializationResponsibility &MR,
165 jitlink::LinkGraph &G,
166 jitlink::PassConfiguration &Config) override {
167 Config.PostAllocationPasses.insert(
168 Config.PostAllocationPasses.begin(), [](LinkGraph &G) {
169 return make_error<StringError>("Kaboom", inconvertibleErrorCode());
173 Error notifyFailed(MaterializationResponsibility &MR) override {
174 ErrorReported = true;
175 return Error::success();
178 Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
179 return Error::success();
181 void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
182 ResourceKey SrcKey) override {
183 llvm_unreachable("unexpected resource transfer");
186 private:
187 bool ErrorReported = false;
190 // We expect this test to generate errors. Consume them so that we don't
191 // add noise to the test logs.
192 ES.setErrorReporter(consumeError);
194 ObjLinkingLayer.addPlugin(std::make_unique<TestPlugin>());
195 auto G = std::make_unique<LinkGraph>(
196 "foo", ES.getSymbolStringPool(), Triple("x86_64-apple-darwin"), 8,
197 llvm::endianness::little, getGenericEdgeKindName);
199 auto &DataSec = G->createSection("__data", MemProt::Read | MemProt::Write);
200 auto &DataBlock = G->createContentBlock(DataSec, BlockContent,
201 orc::ExecutorAddr(0x1000), 8, 0);
202 G->addDefinedSymbol(DataBlock, 4, "_anchor", 4, Linkage::Weak, Scope::Default,
203 false, true);
205 EXPECT_THAT_ERROR(ObjLinkingLayer.add(JD, std::move(G)), Succeeded());
207 EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_anchor"), Failed());
210 TEST_F(ObjectLinkingLayerTest, AddAndRemovePlugins) {
211 class TestPlugin : public ObjectLinkingLayer::Plugin {
212 public:
213 TestPlugin(size_t &ActivationCount, bool &PluginDestroyed)
214 : ActivationCount(ActivationCount), PluginDestroyed(PluginDestroyed) {}
216 ~TestPlugin() { PluginDestroyed = true; }
218 void modifyPassConfig(MaterializationResponsibility &MR,
219 jitlink::LinkGraph &G,
220 jitlink::PassConfiguration &Config) override {
221 ++ActivationCount;
224 Error notifyFailed(MaterializationResponsibility &MR) override {
225 ADD_FAILURE() << "TestPlugin::notifyFailed called unexpectedly";
226 return Error::success();
229 Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
230 return Error::success();
233 void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
234 ResourceKey SrcKey) override {}
236 private:
237 size_t &ActivationCount;
238 bool &PluginDestroyed;
241 size_t ActivationCount = 0;
242 bool PluginDestroyed = false;
244 auto P = std::make_shared<TestPlugin>(ActivationCount, PluginDestroyed);
246 ObjLinkingLayer.addPlugin(P);
249 auto G1 = std::make_unique<LinkGraph>(
250 "G1", ES.getSymbolStringPool(), Triple("x86_64-apple-darwin"), 8,
251 llvm::endianness::little, x86_64::getEdgeKindName);
253 auto &DataSec = G1->createSection("__data", MemProt::Read | MemProt::Write);
254 auto &DataBlock = G1->createContentBlock(DataSec, BlockContent,
255 orc::ExecutorAddr(0x1000), 8, 0);
256 G1->addDefinedSymbol(DataBlock, 4, "_anchor1", 4, Linkage::Weak,
257 Scope::Default, false, true);
259 EXPECT_THAT_ERROR(ObjLinkingLayer.add(JD, std::move(G1)), Succeeded());
260 EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_anchor1"), Succeeded());
261 EXPECT_EQ(ActivationCount, 1U);
264 ObjLinkingLayer.removePlugin(*P);
267 auto G2 = std::make_unique<LinkGraph>(
268 "G2", ES.getSymbolStringPool(), Triple("x86_64-apple-darwin"), 8,
269 llvm::endianness::little, x86_64::getEdgeKindName);
271 auto &DataSec = G2->createSection("__data", MemProt::Read | MemProt::Write);
272 auto &DataBlock = G2->createContentBlock(DataSec, BlockContent,
273 orc::ExecutorAddr(0x1000), 8, 0);
274 G2->addDefinedSymbol(DataBlock, 4, "_anchor2", 4, Linkage::Weak,
275 Scope::Default, false, true);
277 EXPECT_THAT_ERROR(ObjLinkingLayer.add(JD, std::move(G2)), Succeeded());
278 EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_anchor2"), Succeeded());
279 EXPECT_EQ(ActivationCount, 1U);
282 P.reset();
283 EXPECT_TRUE(PluginDestroyed);
286 TEST(ObjectLinkingLayerSearchGeneratorTest, AbsoluteSymbolsObjectLayer) {
287 class TestEPC : public UnsupportedExecutorProcessControl,
288 public DylibManager {
289 public:
290 TestEPC()
291 : UnsupportedExecutorProcessControl(nullptr, nullptr,
292 "x86_64-apple-darwin") {
293 this->DylibMgr = this;
296 Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override {
297 return ExecutorAddr::fromPtr((void *)nullptr);
300 void lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
301 SymbolLookupCompleteFn Complete) override {
302 std::vector<ExecutorSymbolDef> Result;
303 EXPECT_EQ(Request.size(), 1u);
304 for (auto &LR : Request) {
305 EXPECT_EQ(LR.Symbols.size(), 1u);
306 for (auto &Sym : LR.Symbols) {
307 if (*Sym.first == "_testFunc") {
308 ExecutorSymbolDef Def{ExecutorAddr::fromPtr((void *)0x1000),
309 JITSymbolFlags::Exported};
310 Result.push_back(Def);
311 } else {
312 ADD_FAILURE() << "unexpected symbol request " << *Sym.first;
316 Complete(std::vector<tpctypes::LookupResult>{1, Result});
320 ExecutionSession ES{std::make_unique<TestEPC>()};
321 JITDylib &JD = ES.createBareJITDylib("main");
322 ObjectLinkingLayer ObjLinkingLayer{
323 ES, std::make_unique<InProcessMemoryManager>(4096)};
325 auto G = EPCDynamicLibrarySearchGenerator::GetForTargetProcess(
326 ES, {}, [&](JITDylib &JD, SymbolMap Syms) {
327 auto G = absoluteSymbolsLinkGraph(
328 ES.getTargetTriple(), ES.getSymbolStringPool(), std::move(Syms));
329 return ObjLinkingLayer.add(JD, std::move(G));
331 ASSERT_THAT_EXPECTED(G, Succeeded());
332 JD.addGenerator(std::move(*G));
334 class CheckDefs : public ObjectLinkingLayer::Plugin {
335 public:
336 ~CheckDefs() { EXPECT_TRUE(SawSymbolDef); }
338 void modifyPassConfig(MaterializationResponsibility &MR,
339 jitlink::LinkGraph &G,
340 jitlink::PassConfiguration &Config) override {
341 Config.PostAllocationPasses.push_back([this](LinkGraph &G) {
342 unsigned SymCount = 0;
343 for (Symbol *Sym : G.absolute_symbols()) {
344 SymCount += 1;
345 if (!Sym->hasName()) {
346 ADD_FAILURE() << "unexpected unnamed symbol";
347 continue;
349 if (*Sym->getName() == "_testFunc")
350 SawSymbolDef = true;
351 else
352 ADD_FAILURE() << "unexpected symbol " << Sym->getName();
354 EXPECT_EQ(SymCount, 1u);
355 return Error::success();
359 Error notifyFailed(MaterializationResponsibility &MR) override {
360 return Error::success();
363 Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
364 return Error::success();
366 void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
367 ResourceKey SrcKey) override {
368 llvm_unreachable("unexpected resource transfer");
371 private:
372 bool SawSymbolDef = false;
375 ObjLinkingLayer.addPlugin(std::make_unique<CheckDefs>());
377 EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_testFunc"), Succeeded());
378 EXPECT_THAT_ERROR(ES.endSession(), Succeeded());
381 } // end anonymous namespace