#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Memory.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace llvm::jitlink;
static const char BlockContentBytes[] = {
0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d, 0x6f,
0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68,
0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x66,
0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x20,
0x68, 0x61, 0x64, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x61,
0x72, 0x6f, 0x75, 0x6e, 0x64, 0x0a, 0x54, 0x68, 0x61, 0x74, 0x20, 0x74,
0x68, 0x65, 0x20, 0x63, 0x6f, 0x6c, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d,
0x20, 0x4f, 0x6c, 0x64, 0x20, 0x52, 0x65, 0x67, 0x72, 0x65, 0x74, 0x20,
0x68, 0x61, 0x64, 0x20, 0x67, 0x6f, 0x74, 0x20, 0x61, 0x77, 0x61, 0x79,
0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6a, 0x6f,
0x69, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c,
0x64, 0x20, 0x62, 0x75, 0x73, 0x68, 0x20, 0x68, 0x6f, 0x72, 0x73, 0x65,
0x73, 0x20, 0x2d, 0x2d, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
0x77, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x20, 0x74, 0x68, 0x6f, 0x75,
0x73, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x0a,
0x53, 0x6f, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
0x72, 0x61, 0x63, 0x6b, 0x73, 0x20, 0x68, 0x61, 0x64, 0x20, 0x67, 0x61,
0x74, 0x68, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
0x65, 0x20, 0x66, 0x72, 0x61, 0x79, 0x2e, 0x0a, 0x41, 0x6c, 0x6c, 0x20,
0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x69, 0x65, 0x64, 0x20, 0x61, 0x6e,
0x64, 0x20, 0x6e, 0x6f, 0x74, 0x65, 0x64, 0x20, 0x72, 0x69, 0x64, 0x65,
0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6e, 0x65, 0x61,
0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x61, 0x72, 0x0a, 0x48, 0x61,
0x64, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61,
0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x6d, 0x65, 0x73, 0x74,
0x65, 0x61, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x69, 0x67, 0x68,
0x74, 0x2c, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62,
0x75, 0x73, 0x68, 0x6d, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x20,
0x68, 0x61, 0x72, 0x64, 0x20, 0x72, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x20,
0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69,
0x6c, 0x64, 0x20, 0x62, 0x75, 0x73, 0x68, 0x20, 0x68, 0x6f, 0x72, 0x73,
0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20,
0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x2d, 0x68, 0x6f,
0x72, 0x73, 0x65, 0x20, 0x73, 0x6e, 0x75, 0x66, 0x66, 0x73, 0x20, 0x74,
0x68, 0x65, 0x20, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x77, 0x69,
0x74, 0x68, 0x20, 0x64, 0x65, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x00};
static ArrayRef<char> BlockContent(BlockContentBytes);
TEST(LinkGraphTest, Construction) {
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
getGenericEdgeKindName);
EXPECT_EQ(G.getName(), "foo");
EXPECT_EQ(G.getTargetTriple().str(), "x86_64-apple-darwin");
EXPECT_EQ(G.getPointerSize(), 8U);
EXPECT_EQ(G.getEndianness(), support::little);
EXPECT_TRUE(llvm::empty(G.external_symbols()));
EXPECT_TRUE(llvm::empty(G.absolute_symbols()));
EXPECT_TRUE(llvm::empty(G.defined_symbols()));
EXPECT_TRUE(llvm::empty(G.blocks()));
}
TEST(LinkGraphTest, AddressAccess) {
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
getGenericEdgeKindName);
auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write);
orc::ExecutorAddr B1Addr(0x1000);
auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0);
auto &S1 = G.addDefinedSymbol(B1, 4, "S1", 4, Linkage::Strong, Scope::Default,
false, false);
B1.addEdge(Edge::FirstRelocation, 8, S1, 0);
auto &E1 = *B1.edges().begin();
EXPECT_EQ(B1.getAddress(), B1Addr) << "Incorrect block address";
EXPECT_EQ(S1.getAddress(), B1Addr + 4) << "Incorrect symbol address";
EXPECT_EQ(B1.getFixupAddress(E1), B1Addr + 8) << "Incorrect fixup address";
}
TEST(LinkGraphTest, BlockAndSymbolIteration) {
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
getGenericEdgeKindName);
auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write);
orc::ExecutorAddr B1Addr(0x1000);
auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0);
orc::ExecutorAddr B2Addr(0x1000);
auto &B2 = G.createContentBlock(Sec1, BlockContent, B2Addr, 8, 0);
auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default,
false, false);
auto &S2 = G.addDefinedSymbol(B2, 4, "S2", 4, Linkage::Strong, Scope::Default,
false, false);
auto &Sec2 = G.createSection("__data.2", MemProt::Read | MemProt::Write);
orc::ExecutorAddr B3Addr(0x3000);
auto &B3 = G.createContentBlock(Sec2, BlockContent, B3Addr, 8, 0);
orc::ExecutorAddr B4Addr(0x4000);
auto &B4 = G.createContentBlock(Sec2, BlockContent, B4Addr, 8, 0);
auto &S3 = G.addDefinedSymbol(B3, 0, "S3", 4, Linkage::Strong, Scope::Default,
false, false);
auto &S4 = G.addDefinedSymbol(B4, 4, "S4", 4, Linkage::Strong, Scope::Default,
false, false);
EXPECT_EQ(std::distance(Sec1.blocks().begin(), Sec1.blocks().end()), 2);
EXPECT_TRUE(llvm::count(Sec1.blocks(), &B1));
EXPECT_TRUE(llvm::count(Sec1.blocks(), &B2));
EXPECT_EQ(std::distance(Sec1.symbols().begin(), Sec1.symbols().end()), 2);
EXPECT_TRUE(llvm::count(Sec1.symbols(), &S1));
EXPECT_TRUE(llvm::count(Sec1.symbols(), &S2));
EXPECT_EQ(std::distance(G.blocks().begin(), G.blocks().end()), 4);
EXPECT_TRUE(llvm::count(G.blocks(), &B1));
EXPECT_TRUE(llvm::count(G.blocks(), &B2));
EXPECT_TRUE(llvm::count(G.blocks(), &B3));
EXPECT_TRUE(llvm::count(G.blocks(), &B4));
EXPECT_EQ(
std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 4);
EXPECT_TRUE(llvm::count(G.defined_symbols(), &S1));
EXPECT_TRUE(llvm::count(G.defined_symbols(), &S2));
EXPECT_TRUE(llvm::count(G.defined_symbols(), &S3));
EXPECT_TRUE(llvm::count(G.defined_symbols(), &S4));
}
TEST(LinkGraphTest, ContentAccessAndUpdate) {
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
getGenericEdgeKindName);
auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write);
orc::ExecutorAddr BAddr(0x1000);
auto &B = G.createContentBlock(Sec, BlockContent, BAddr, 8, 0);
EXPECT_FALSE(B.isContentMutable()) << "Content unexpectedly mutable";
EXPECT_EQ(B.getContent().data(), BlockContent.data())
<< "Unexpected block content data pointer";
EXPECT_EQ(B.getContent().size(), BlockContent.size())
<< "Unexpected block content size";
#ifndef NDEBUG
EXPECT_DEATH({ (void)B.getAlreadyMutableContent(); },
"Content is not mutable")
<< "Unexpected mutable access allowed to immutable data";
#endif
auto MutableContent = B.getMutableContent(G);
EXPECT_TRUE(B.isContentMutable()) << "Content unexpectedly immutable";
EXPECT_NE(MutableContent.data(), BlockContent.data())
<< "Unexpected mutable content data pointer";
EXPECT_EQ(MutableContent.size(), BlockContent.size())
<< "Unexpected mutable content size";
EXPECT_TRUE(std::equal(MutableContent.begin(), MutableContent.end(),
BlockContent.begin()))
<< "Unexpected mutable content value";
auto MutableContent2 = B.getMutableContent(G);
EXPECT_TRUE(B.isContentMutable()) << "Content unexpectedly immutable";
EXPECT_EQ(MutableContent2.data(), MutableContent.data())
<< "Unexpected mutable content 2 data pointer";
EXPECT_EQ(MutableContent2.size(), MutableContent.size())
<< "Unexpected mutable content 2 size";
auto MutableContent3 = B.getMutableContent(G);
EXPECT_TRUE(B.isContentMutable()) << "Content unexpectedly immutable";
EXPECT_EQ(MutableContent3.data(), MutableContent.data())
<< "Unexpected mutable content 2 data pointer";
EXPECT_EQ(MutableContent3.size(), MutableContent.size())
<< "Unexpected mutable content 2 size";
B.setContent(BlockContent);
EXPECT_FALSE(B.isContentMutable()) << "Content unexpectedly mutable";
EXPECT_EQ(B.getContent().data(), BlockContent.data())
<< "Unexpected block content data pointer";
EXPECT_EQ(B.getContent().size(), BlockContent.size())
<< "Unexpected block content size";
auto &B2 = G.createMutableContentBlock(Sec, MutableContent,
orc::ExecutorAddr(0x10000), 8, 0);
EXPECT_TRUE(B2.isContentMutable()) << "Expected B2 content to be mutable";
}
TEST(LinkGraphTest, MakeExternal) {
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
getGenericEdgeKindName);
auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write);
auto &B1 =
G.createContentBlock(Sec, BlockContent, orc::ExecutorAddr(0x1000), 8, 0);
auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default,
false, false);
EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined";
EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external";
EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block";
EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr(0x1000))
<< "Unexpected symbol address";
EXPECT_EQ(
std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U)
<< "Unexpected number of defined symbols";
EXPECT_EQ(
std::distance(G.external_symbols().begin(), G.external_symbols().end()),
0U)
<< "Unexpected number of external symbols";
G.makeExternal(S1);
EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined";
EXPECT_TRUE(S1.isExternal()) << "Symbol should be external";
EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr())
<< "Unexpected symbol address";
EXPECT_EQ(
std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U)
<< "Unexpected number of defined symbols";
EXPECT_EQ(
std::distance(G.external_symbols().begin(), G.external_symbols().end()),
1U)
<< "Unexpected number of external symbols";
}
TEST(LinkGraphTest, MakeDefined) {
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
getGenericEdgeKindName);
auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write);
orc::ExecutorAddr B1Addr(0x1000);
auto &B1 = G.createContentBlock(Sec, BlockContent, B1Addr, 8, 0);
auto &S1 = G.addExternalSymbol("S1", 4, Linkage::Strong);
EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined";
EXPECT_TRUE(S1.isExternal()) << "Symbol should be external";
EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr())
<< "Unexpected symbol address";
EXPECT_EQ(
std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U)
<< "Unexpected number of defined symbols";
EXPECT_EQ(
std::distance(G.external_symbols().begin(), G.external_symbols().end()),
1U)
<< "Unexpected number of external symbols";
G.makeDefined(S1, B1, 0, 4, Linkage::Strong, Scope::Default, false);
EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined";
EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external";
EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block";
EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr(0x1000U))
<< "Unexpected symbol address";
EXPECT_EQ(
std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U)
<< "Unexpected number of defined symbols";
EXPECT_EQ(
std::distance(G.external_symbols().begin(), G.external_symbols().end()),
0U)
<< "Unexpected number of external symbols";
}
TEST(LinkGraphTest, TransferDefinedSymbol) {
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
getGenericEdgeKindName);
auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write);
orc::ExecutorAddr B1Addr(0x1000);
auto &B1 = G.createContentBlock(Sec, BlockContent, B1Addr, 8, 0);
orc::ExecutorAddr B2Addr(0x2000);
auto &B2 = G.createContentBlock(Sec, BlockContent, B2Addr, 8, 0);
orc::ExecutorAddr B3Addr(0x3000);
auto &B3 = G.createContentBlock(Sec, BlockContent.slice(0, 32), B3Addr, 8, 0);
auto &S1 = G.addDefinedSymbol(B1, 0, "S1", B1.getSize(), Linkage::Strong,
Scope::Default, false, false);
G.transferDefinedSymbol(S1, B2, 0, 64);
EXPECT_EQ(&S1.getBlock(), &B2) << "Block was not updated";
EXPECT_EQ(S1.getOffset(), 0U) << "Unexpected offset";
EXPECT_EQ(S1.getSize(), 64U) << "Size was not updated";
G.transferDefinedSymbol(S1, B3, 16, None);
EXPECT_EQ(&S1.getBlock(), &B3) << "Block was not updated";
EXPECT_EQ(S1.getOffset(), 16U) << "Offset was not updated";
EXPECT_EQ(S1.getSize(), 16U) << "Size was not updated";
}
TEST(LinkGraphTest, TransferDefinedSymbolAcrossSections) {
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
getGenericEdgeKindName);
auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write);
auto &Sec2 = G.createSection("__data.2", MemProt::Read | MemProt::Write);
orc::ExecutorAddr B1Addr(0x1000);
auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0);
orc::ExecutorAddr B2Addr(0x2000);
auto &B2 = G.createContentBlock(Sec2, BlockContent, B2Addr, 8, 0);
auto &S1 = G.addDefinedSymbol(B1, 0, "S1", B1.getSize(), Linkage::Strong,
Scope::Default, false, false);
G.transferDefinedSymbol(S1, B2, 0, 64);
EXPECT_EQ(&S1.getBlock(), &B2) << "Block was not updated";
EXPECT_EQ(S1.getOffset(), 0U) << "Unexpected offset";
EXPECT_EQ(S1.getSize(), 64U) << "Size was not updated";
EXPECT_EQ(Sec1.symbols_size(), 0u) << "Symbol was not removed from Sec1";
EXPECT_EQ(Sec2.symbols_size(), 1u) << "Symbol was not added to Sec2";
if (Sec2.symbols_size() == 1) {
EXPECT_EQ(*Sec2.symbols().begin(), &S1) << "Unexpected symbol";
}
}
TEST(LinkGraphTest, TransferBlock) {
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
getGenericEdgeKindName);
auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write);
auto &Sec2 = G.createSection("__data.2", MemProt::Read | MemProt::Write);
orc::ExecutorAddr B1Addr(0x1000);
auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0);
orc::ExecutorAddr B2Addr(0x2000);
auto &B2 = G.createContentBlock(Sec1, BlockContent, B2Addr, 8, 0);
G.addDefinedSymbol(B1, 0, "S1", B1.getSize(), Linkage::Strong, Scope::Default,
false, false);
G.addDefinedSymbol(B1, 1, "S2", B1.getSize() - 1, Linkage::Strong,
Scope::Default, false, false);
G.addDefinedSymbol(B2, 0, "S3", B2.getSize(), Linkage::Strong, Scope::Default,
false, false);
G.addDefinedSymbol(B2, 1, "S4", B2.getSize() - 1, Linkage::Strong,
Scope::Default, false, false);
EXPECT_EQ(Sec1.blocks_size(), 2U) << "Expected two blocks in Sec1 initially";
EXPECT_EQ(Sec1.symbols_size(), 4U)
<< "Expected four symbols in Sec1 initially";
EXPECT_EQ(Sec2.blocks_size(), 0U) << "Expected zero blocks in Sec2 initially";
EXPECT_EQ(Sec2.symbols_size(), 0U)
<< "Expected zero symbols in Sec2 initially";
G.transferBlock(B1, Sec2);
EXPECT_EQ(Sec1.blocks_size(), 1U)
<< "Expected one blocks in Sec1 after transfer";
EXPECT_EQ(Sec1.symbols_size(), 2U)
<< "Expected two symbols in Sec1 after transfer";
EXPECT_EQ(Sec2.blocks_size(), 1U)
<< "Expected one blocks in Sec2 after transfer";
EXPECT_EQ(Sec2.symbols_size(), 2U)
<< "Expected two symbols in Sec2 after transfer";
}
TEST(LinkGraphTest, MergeSections) {
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
getGenericEdgeKindName);
auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write);
auto &Sec2 = G.createSection("__data.2", MemProt::Read | MemProt::Write);
auto &Sec3 = G.createSection("__data.3", MemProt::Read | MemProt::Write);
orc::ExecutorAddr B1Addr(0x1000);
auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0);
orc::ExecutorAddr B2Addr(0x2000);
auto &B2 = G.createContentBlock(Sec2, BlockContent, B2Addr, 8, 0);
orc::ExecutorAddr B3Addr(0x3000);
auto &B3 = G.createContentBlock(Sec3, BlockContent, B3Addr, 8, 0);
G.addDefinedSymbol(B1, 0, "S1", B1.getSize(), Linkage::Strong, Scope::Default,
false, false);
G.addDefinedSymbol(B2, 0, "S2", B2.getSize(), Linkage::Strong, Scope::Default,
false, false);
G.addDefinedSymbol(B3, 0, "S3", B2.getSize(), Linkage::Strong, Scope::Default,
false, false);
EXPECT_EQ(&B1.getSection(), &Sec1);
EXPECT_EQ(&B2.getSection(), &Sec2);
EXPECT_EQ(G.sections_size(), 3U) << "Expected three sections initially";
EXPECT_EQ(Sec1.blocks_size(), 1U) << "Expected one block in Sec1 initially";
EXPECT_EQ(Sec1.symbols_size(), 1U) << "Expected one symbol in Sec1 initially";
EXPECT_EQ(Sec2.blocks_size(), 1U) << "Expected one block in Sec2 initially";
EXPECT_EQ(Sec2.symbols_size(), 1U) << "Expected one symbol in Sec2 initially";
EXPECT_EQ(Sec3.blocks_size(), 1U) << "Expected one block in Sec3 initially";
EXPECT_EQ(Sec3.symbols_size(), 1U) << "Expected one symbol in Sec3 initially";
G.mergeSections(Sec1, Sec1);
EXPECT_EQ(&B1.getSection(), &Sec1)
<< "Expected B1.getSection() to remain unchanged";
EXPECT_EQ(G.sections_size(), 3U)
<< "Expected three sections after first merge";
EXPECT_EQ(Sec1.blocks_size(), 1U)
<< "Expected one block in Sec1 after first merge";
EXPECT_EQ(Sec1.symbols_size(), 1U)
<< "Expected one symbol in Sec1 after first merge";
EXPECT_EQ(Sec2.blocks_size(), 1U)
<< "Expected one block in Sec2 after first merge";
EXPECT_EQ(Sec2.symbols_size(), 1U)
<< "Expected one symbol in Sec2 after first merge";
EXPECT_EQ(Sec3.blocks_size(), 1U)
<< "Expected one block in Sec3 after first merge";
EXPECT_EQ(Sec3.symbols_size(), 1U)
<< "Expected one symbol in Sec3 after first merge";
G.mergeSections(Sec1, Sec2);
EXPECT_EQ(&B2.getSection(), &Sec1)
<< "Expected B2.getSection() to have been changed to &Sec1";
EXPECT_EQ(G.sections_size(), 2U)
<< "Expected two sections after section merge";
EXPECT_EQ(Sec1.blocks_size(), 2U)
<< "Expected two blocks in Sec1 after section merge";
EXPECT_EQ(Sec1.symbols_size(), 2U)
<< "Expected two symbols in Sec1 after section merge";
EXPECT_EQ(Sec3.blocks_size(), 1U)
<< "Expected one block in Sec3 after section merge";
EXPECT_EQ(Sec3.symbols_size(), 1U)
<< "Expected one symbol in Sec3 after section merge";
G.mergeSections(Sec1, Sec3, true);
EXPECT_EQ(G.sections_size(), 2U) << "Expected two sections after third merge";
EXPECT_EQ(Sec1.blocks_size(), 3U)
<< "Expected three blocks in Sec1 after third merge";
EXPECT_EQ(Sec1.symbols_size(), 3U)
<< "Expected three symbols in Sec1 after third merge";
EXPECT_EQ(Sec3.blocks_size(), 0U)
<< "Expected one block in Sec3 after third merge";
EXPECT_EQ(Sec3.symbols_size(), 0U)
<< "Expected one symbol in Sec3 after third merge";
}
TEST(LinkGraphTest, SplitBlock) {
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
getGenericEdgeKindName);
auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write);
orc::ExecutorAddr B1Addr(0x1000);
auto &B1 = G.createContentBlock(Sec, BlockContent, B1Addr, 8, 0);
auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default,
false, false);
auto &S2 = G.addDefinedSymbol(B1, 4, "S2", 4, Linkage::Strong, Scope::Default,
false, false);
auto &S3 = G.addDefinedSymbol(B1, 8, "S3", 4, Linkage::Strong, Scope::Default,
false, false);
auto &S4 = G.addDefinedSymbol(B1, 12, "S4", 4, Linkage::Strong,
Scope::Default, false, false);
auto &S5 = G.addDefinedSymbol(B1, 0, "S5", 16, Linkage::Strong,
Scope::Default, false, false);
orc::ExecutorAddr EBAddr(0x2000);
auto &EB = G.createContentBlock(Sec, BlockContent, EBAddr, 8, 0);
auto &ES1 = G.addDefinedSymbol(EB, 0, "TS1", 4, Linkage::Strong,
Scope::Default, false, false);
auto &ES2 = G.addDefinedSymbol(EB, 4, "TS2", 4, Linkage::Strong,
Scope::Default, false, false);
auto &ES3 = G.addDefinedSymbol(EB, 8, "TS3", 4, Linkage::Strong,
Scope::Default, false, false);
auto &ES4 = G.addDefinedSymbol(EB, 12, "TS4", 4, Linkage::Strong,
Scope::Default, false, false);
B1.addEdge(Edge::FirstRelocation, 0, ES1, 0);
B1.addEdge(Edge::FirstRelocation, 4, ES2, 0);
B1.addEdge(Edge::FirstRelocation, 8, ES3, 0);
B1.addEdge(Edge::FirstRelocation, 12, ES4, 0);
auto &B2 = G.splitBlock(B1, 8);
EXPECT_EQ(B1.getAddress(), B1Addr + 8);
EXPECT_EQ(B1.getContent(), BlockContent.slice(8));
EXPECT_EQ(B2.getAddress(), B1Addr);
EXPECT_EQ(B2.getContent(), BlockContent.slice(0, 8));
EXPECT_EQ(&S1.getBlock(), &B2);
EXPECT_EQ(S1.getOffset(), 0U);
EXPECT_EQ(&S2.getBlock(), &B2);
EXPECT_EQ(S2.getOffset(), 4U);
EXPECT_EQ(&S3.getBlock(), &B1);
EXPECT_EQ(S3.getOffset(), 0U);
EXPECT_EQ(&S4.getBlock(), &B1);
EXPECT_EQ(S4.getOffset(), 4U);
EXPECT_EQ(&S5.getBlock(), &B2);
EXPECT_EQ(S5.getOffset(), 0U);
EXPECT_EQ(S5.getSize(), 8U);
EXPECT_EQ(llvm::size(B1.edges()), 2);
if (size(B1.edges()) == 2) {
auto *E1 = &*B1.edges().begin();
auto *E2 = &*(B1.edges().begin() + 1);
if (E2->getOffset() < E1->getOffset())
std::swap(E1, E2);
EXPECT_EQ(E1->getOffset(), 0U);
EXPECT_EQ(E2->getOffset(), 4U);
}
EXPECT_EQ(llvm::size(B2.edges()), 2);
if (size(B2.edges()) == 2) {
auto *E1 = &*B2.edges().begin();
auto *E2 = &*(B2.edges().begin() + 1);
if (E2->getOffset() < E1->getOffset())
std::swap(E1, E2);
EXPECT_EQ(E1->getOffset(), 0U);
EXPECT_EQ(E2->getOffset(), 4U);
}
}