183 lines · cpp
1//===------ StubsTests.cpp - Unit tests for generic stub generation -------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/STLExtras.h"10#include "llvm/ExecutionEngine/JITLink/JITLink.h"11#include "llvm/ExecutionEngine/JITLink/aarch64.h"12#include "llvm/ExecutionEngine/JITLink/loongarch.h"13#include "llvm/ExecutionEngine/JITLink/x86.h"14#include "llvm/ExecutionEngine/JITLink/x86_64.h"15#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"16#include "llvm/Support/Memory.h"17 18#include "llvm/Testing/Support/Error.h"19#include "gtest/gtest.h"20 21using namespace llvm;22using namespace llvm::jitlink;23 24static std::pair<Symbol &, Symbol &>25GenerateStub(LinkGraph &G, size_t PointerSize, Edge::Kind PointerEdgeKind) {26 auto &FuncSymbol = G.addAbsoluteSymbol("Func", orc::ExecutorAddr(0x2000), 0,27 Linkage::Strong, Scope::Default, true);28 29 // Create a section for pointer symbols.30 auto &PointersSec =31 G.createSection("__pointers", orc::MemProt::Read | orc::MemProt::Write);32 33 // Create a section for jump stubs symbols.34 auto &StubsSec =35 G.createSection("__stubs", orc::MemProt::Read | orc::MemProt::Write);36 37 auto AnonymousPtrCreator = getAnonymousPointerCreator(G.getTargetTriple());38 EXPECT_TRUE(AnonymousPtrCreator);39 40 auto &PointerSym = AnonymousPtrCreator(G, PointersSec, &FuncSymbol, 0);41 EXPECT_EQ(std::distance(PointerSym.getBlock().edges().begin(),42 PointerSym.getBlock().edges().end()),43 1U);44 auto &DeltaEdge = *PointerSym.getBlock().edges().begin();45 EXPECT_EQ(DeltaEdge.getKind(), PointerEdgeKind);46 EXPECT_EQ(&DeltaEdge.getTarget(), &FuncSymbol);47 EXPECT_EQ(PointerSym.getBlock().getSize(), PointerSize);48 EXPECT_TRUE(all_of(PointerSym.getBlock().getContent(),49 [](char x) { return x == 0; }));50 51 auto PtrJumpStubCreator = getPointerJumpStubCreator(G.getTargetTriple());52 EXPECT_TRUE(PtrJumpStubCreator);53 auto &StubSym = PtrJumpStubCreator(G, StubsSec, PointerSym);54 return {PointerSym, StubSym};55}56 57TEST(StubsTest, StubsGeneration_x86_64) {58 const char PointerJumpStubContent[6] = {59 static_cast<char>(0xFFu), 0x25, 0x00, 0x00, 0x00, 0x00};60 LinkGraph G("foo", std::make_shared<orc::SymbolStringPool>(),61 Triple("x86_64-apple-darwin"), SubtargetFeatures(),62 getGenericEdgeKindName);63 auto [PointerSym, StubSym] = GenerateStub(G, 8U, x86_64::Pointer64);64 65 EXPECT_EQ(std::distance(StubSym.getBlock().edges().begin(),66 StubSym.getBlock().edges().end()),67 1U);68 auto &JumpEdge = *StubSym.getBlock().edges().begin();69 EXPECT_EQ(JumpEdge.getKind(), x86_64::BranchPCRel32);70 EXPECT_EQ(&JumpEdge.getTarget(), &PointerSym);71 EXPECT_EQ(StubSym.getBlock().getContent(),72 ArrayRef<char>(PointerJumpStubContent));73}74 75TEST(StubsTest, StubsGeneration_aarch64) {76 const char PointerJumpStubContent[12] = {77 0x10, 0x00, 0x00, (char)0x90u, // ADRP x16, <imm>@page2178 0x10, 0x02, 0x40, (char)0xf9u, // LDR x16, [x16, <imm>@pageoff12]79 0x00, 0x02, 0x1f, (char)0xd6u // BR x1680 };81 LinkGraph G("foo", std::make_shared<orc::SymbolStringPool>(),82 Triple("aarch64-linux-gnu"), SubtargetFeatures(),83 getGenericEdgeKindName);84 auto [PointerSym, StubSym] = GenerateStub(G, 8U, aarch64::Pointer64);85 86 EXPECT_EQ(std::distance(StubSym.getBlock().edges().begin(),87 StubSym.getBlock().edges().end()),88 2U);89 auto &AdrpHighEdge = *StubSym.getBlock().edges().begin();90 auto &LdrEdge = *++StubSym.getBlock().edges().begin();91 EXPECT_EQ(AdrpHighEdge.getKind(), aarch64::Page21);92 EXPECT_EQ(&AdrpHighEdge.getTarget(), &PointerSym);93 EXPECT_EQ(LdrEdge.getKind(), aarch64::PageOffset12);94 EXPECT_EQ(&LdrEdge.getTarget(), &PointerSym);95 EXPECT_EQ(StubSym.getBlock().getContent(),96 ArrayRef<char>(PointerJumpStubContent));97}98 99TEST(StubsTest, StubsGeneration_x86) {100 const char PointerJumpStubContent[6] = {101 static_cast<char>(0xFFu), 0x25, 0x00, 0x00, 0x00, 0x00};102 LinkGraph G("foo", std::make_shared<orc::SymbolStringPool>(),103 Triple("i386-unknown-linux-gnu"), SubtargetFeatures(),104 getGenericEdgeKindName);105 auto [PointerSym, StubSym] = GenerateStub(G, 4U, x86::Pointer32);106 107 EXPECT_EQ(std::distance(StubSym.getBlock().edges().begin(),108 StubSym.getBlock().edges().end()),109 1U);110 auto &JumpEdge = *StubSym.getBlock().edges().begin();111 EXPECT_EQ(JumpEdge.getKind(), x86::Pointer32);112 EXPECT_EQ(&JumpEdge.getTarget(), &PointerSym);113 EXPECT_EQ(StubSym.getBlock().getContent(),114 ArrayRef<char>(PointerJumpStubContent));115}116 117TEST(StubsTest, StubsGeneration_loongarch32) {118 const char PointerJumpStubContent[12] = {119 0x14,120 0x00,121 0x00,122 0x1a, // pcalau12i $t8, %page20(imm)123 static_cast<char>(0x94),124 0x02,125 static_cast<char>(0x80),126 0x28, // ld.d $t8, $t8, %pageoff12(imm)127 static_cast<char>(0x80),128 0x02,129 0x00,130 0x4c // jr $t8131 };132 LinkGraph G("foo", std::make_shared<orc::SymbolStringPool>(),133 Triple("loongarch32"), SubtargetFeatures(),134 getGenericEdgeKindName);135 auto [PointerSym, StubSym] = GenerateStub(G, 4U, loongarch::Pointer32);136 137 EXPECT_EQ(std::distance(StubSym.getBlock().edges().begin(),138 StubSym.getBlock().edges().end()),139 2U);140 auto &PageHighEdge = *StubSym.getBlock().edges().begin();141 auto &PageLowEdge = *++StubSym.getBlock().edges().begin();142 EXPECT_EQ(PageHighEdge.getKind(), loongarch::Page20);143 EXPECT_EQ(&PageHighEdge.getTarget(), &PointerSym);144 EXPECT_EQ(PageLowEdge.getKind(), loongarch::PageOffset12);145 EXPECT_EQ(&PageLowEdge.getTarget(), &PointerSym);146 EXPECT_EQ(StubSym.getBlock().getContent(),147 ArrayRef<char>(PointerJumpStubContent));148}149 150TEST(StubsTest, StubsGeneration_loongarch64) {151 const char PointerJumpStubContent[12] = {152 0x14,153 0x00,154 0x00,155 0x1a, // pcalau12i $t8, %page20(imm)156 static_cast<char>(0x94),157 0x02,158 static_cast<char>(0xc0),159 0x28, // ld.d $t8, $t8, %pageoff12(imm)160 static_cast<char>(0x80),161 0x02,162 0x00,163 0x4c // jr $t8164 };165 166 LinkGraph G("foo", std::make_shared<orc::SymbolStringPool>(),167 Triple("loongarch64"), SubtargetFeatures(),168 getGenericEdgeKindName);169 auto [PointerSym, StubSym] = GenerateStub(G, 8U, loongarch::Pointer64);170 171 EXPECT_EQ(std::distance(StubSym.getBlock().edges().begin(),172 StubSym.getBlock().edges().end()),173 2U);174 auto &PageHighEdge = *StubSym.getBlock().edges().begin();175 auto &PageLowEdge = *++StubSym.getBlock().edges().begin();176 EXPECT_EQ(PageHighEdge.getKind(), loongarch::Page20);177 EXPECT_EQ(&PageHighEdge.getTarget(), &PointerSym);178 EXPECT_EQ(PageLowEdge.getKind(), loongarch::PageOffset12);179 EXPECT_EQ(&PageLowEdge.getTarget(), &PointerSym);180 EXPECT_EQ(StubSym.getBlock().getContent(),181 ArrayRef<char>(PointerJumpStubContent));182}183