1 //===-------- ObjectLinkingLayerTest.cpp - ObjectLinkingLayer 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 "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/Testing/Support/Error.h"
14 #include "gtest/gtest.h"
17 using namespace llvm::jitlink
;
18 using namespace llvm::orc
;
22 const char BlockContentBytes
[] = {0x01, 0x02, 0x03, 0x04,
23 0x05, 0x06, 0x07, 0x08};
25 ArrayRef
<char> BlockContent(BlockContentBytes
);
27 class ObjectLinkingLayerTest
: public testing::Test
{
29 ~ObjectLinkingLayerTest() {
30 if (auto Err
= ES
.endSession())
31 ES
.reportError(std::move(Err
));
35 ExecutionSession ES
{std::make_unique
<UnsupportedExecutorProcessControl
>()};
36 JITDylib
&JD
= ES
.createBareJITDylib("main");
37 ObjectLinkingLayer ObjLinkingLayer
{
38 ES
, std::make_unique
<InProcessMemoryManager
>(4096)};
41 TEST_F(ObjectLinkingLayerTest
, AddLinkGraph
) {
42 auto G
= std::make_unique
<LinkGraph
>("foo", Triple("x86_64-apple-darwin"), 8,
43 llvm::endianness::little
,
44 x86_64::getEdgeKindName
);
46 auto &Sec1
= G
->createSection("__data", MemProt::Read
| MemProt::Write
);
47 auto &B1
= G
->createContentBlock(Sec1
, BlockContent
,
48 orc::ExecutorAddr(0x1000), 8, 0);
49 G
->addDefinedSymbol(B1
, 4, "_X", 4, Linkage::Strong
, Scope::Default
, false,
51 G
->addDefinedSymbol(B1
, 4, "_Y", 4, Linkage::Weak
, Scope::Default
, false,
53 G
->addDefinedSymbol(B1
, 4, "_Z", 4, Linkage::Strong
, Scope::Hidden
, false,
55 G
->addDefinedSymbol(B1
, 4, "_W", 4, Linkage::Strong
, Scope::Default
, true,
58 EXPECT_THAT_ERROR(ObjLinkingLayer
.add(JD
, std::move(G
)), Succeeded());
60 EXPECT_THAT_EXPECTED(ES
.lookup(&JD
, "_X"), Succeeded());
63 TEST_F(ObjectLinkingLayerTest
, ClaimLateDefinedWeakSymbols
) {
64 // Check that claiming weak symbols works as expected.
66 // To do this we'll need a custom plugin to inject some new symbols during
68 class TestPlugin
: public ObjectLinkingLayer::Plugin
{
70 void modifyPassConfig(MaterializationResponsibility
&MR
,
71 jitlink::LinkGraph
&G
,
72 jitlink::PassConfiguration
&Config
) override
{
73 Config
.PrePrunePasses
.insert(
74 Config
.PrePrunePasses
.begin(), [](LinkGraph
&G
) {
75 auto *DataSec
= G
.findSectionByName("__data");
76 auto &DataBlock
= G
.createContentBlock(
77 *DataSec
, BlockContent
, orc::ExecutorAddr(0x2000), 8, 0);
78 G
.addDefinedSymbol(DataBlock
, 4, "_x", 4, Linkage::Weak
,
79 Scope::Default
, false, false);
82 G
.createSection("__text", MemProt::Read
| MemProt::Write
);
83 auto &FuncBlock
= G
.createContentBlock(
84 TextSec
, BlockContent
, orc::ExecutorAddr(0x3000), 8, 0);
85 G
.addDefinedSymbol(FuncBlock
, 4, "_f", 4, Linkage::Weak
,
86 Scope::Default
, true, false);
88 return Error::success();
92 Error
notifyFailed(MaterializationResponsibility
&MR
) override
{
93 llvm_unreachable("unexpected error");
96 Error
notifyRemovingResources(JITDylib
&JD
, ResourceKey K
) override
{
97 return Error::success();
99 void notifyTransferringResources(JITDylib
&JD
, ResourceKey DstKey
,
100 ResourceKey SrcKey
) override
{
101 llvm_unreachable("unexpected resource transfer");
105 ObjLinkingLayer
.addPlugin(std::make_unique
<TestPlugin
>());
107 auto G
= std::make_unique
<LinkGraph
>("foo", Triple("x86_64-apple-darwin"), 8,
108 llvm::endianness::little
,
109 x86_64::getEdgeKindName
);
111 auto &DataSec
= G
->createSection("__data", MemProt::Read
| MemProt::Write
);
112 auto &DataBlock
= G
->createContentBlock(DataSec
, BlockContent
,
113 orc::ExecutorAddr(0x1000), 8, 0);
114 G
->addDefinedSymbol(DataBlock
, 4, "_anchor", 4, Linkage::Weak
, Scope::Default
,
117 EXPECT_THAT_ERROR(ObjLinkingLayer
.add(JD
, std::move(G
)), Succeeded());
119 EXPECT_THAT_EXPECTED(ES
.lookup(&JD
, "_anchor"), Succeeded());
122 TEST_F(ObjectLinkingLayerTest
, HandleErrorDuringPostAllocationPass
) {
123 // We want to confirm that Errors in post allocation passes correctly
124 // abandon the in-flight allocation and report an error.
125 class TestPlugin
: public ObjectLinkingLayer::Plugin
{
127 ~TestPlugin() { EXPECT_TRUE(ErrorReported
); }
129 void modifyPassConfig(MaterializationResponsibility
&MR
,
130 jitlink::LinkGraph
&G
,
131 jitlink::PassConfiguration
&Config
) override
{
132 Config
.PostAllocationPasses
.insert(
133 Config
.PostAllocationPasses
.begin(), [](LinkGraph
&G
) {
134 return make_error
<StringError
>("Kaboom", inconvertibleErrorCode());
138 Error
notifyFailed(MaterializationResponsibility
&MR
) override
{
139 ErrorReported
= true;
140 return Error::success();
143 Error
notifyRemovingResources(JITDylib
&JD
, ResourceKey K
) override
{
144 return Error::success();
146 void notifyTransferringResources(JITDylib
&JD
, ResourceKey DstKey
,
147 ResourceKey SrcKey
) override
{
148 llvm_unreachable("unexpected resource transfer");
152 bool ErrorReported
= false;
155 // We expect this test to generate errors. Consume them so that we don't
156 // add noise to the test logs.
157 ES
.setErrorReporter(consumeError
);
159 ObjLinkingLayer
.addPlugin(std::make_unique
<TestPlugin
>());
161 auto G
= std::make_unique
<LinkGraph
>("foo", Triple("x86_64-apple-darwin"), 8,
162 llvm::endianness::little
,
163 x86_64::getEdgeKindName
);
165 auto &DataSec
= G
->createSection("__data", MemProt::Read
| MemProt::Write
);
166 auto &DataBlock
= G
->createContentBlock(DataSec
, BlockContent
,
167 orc::ExecutorAddr(0x1000), 8, 0);
168 G
->addDefinedSymbol(DataBlock
, 4, "_anchor", 4, Linkage::Weak
, Scope::Default
,
171 EXPECT_THAT_ERROR(ObjLinkingLayer
.add(JD
, std::move(G
)), Succeeded());
173 EXPECT_THAT_EXPECTED(ES
.lookup(&JD
, "_anchor"), Failed());
176 } // end anonymous namespace