1 //===-------- x86.cpp - Generic JITLink x86 edge kinds, utilities ---------===// 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 //===----------------------------------------------------------------------===// 8 // 9 // Generic utilities for graphs representing x86 objects. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ExecutionEngine/JITLink/x86.h" 14 15 #define DEBUG_TYPE "jitlink" 16 17 namespace llvm::jitlink::x86 { 18 19 const char *getEdgeKindName(Edge::Kind K) { 20 switch (K) { 21 case Pointer32: 22 return "Pointer32"; 23 case PCRel32: 24 return "PCRel32"; 25 case Pointer16: 26 return "Pointer16"; 27 case PCRel16: 28 return "PCRel16"; 29 case Delta32: 30 return "Delta32"; 31 case Delta32FromGOT: 32 return "Delta32FromGOT"; 33 case RequestGOTAndTransformToDelta32FromGOT: 34 return "RequestGOTAndTransformToDelta32FromGOT"; 35 case BranchPCRel32: 36 return "BranchPCRel32"; 37 case BranchPCRel32ToPtrJumpStub: 38 return "BranchPCRel32ToPtrJumpStub"; 39 case BranchPCRel32ToPtrJumpStubBypassable: 40 return "BranchPCRel32ToPtrJumpStubBypassable"; 41 } 42 43 return getGenericEdgeKindName(K); 44 } 45 46 const char NullPointerContent[PointerSize] = {0x00, 0x00, 0x00, 0x00}; 47 48 const char PointerJumpStubContent[6] = { 49 static_cast<char>(0xFFu), 0x25, 0x00, 0x00, 0x00, 0x00}; 50 51 Error optimizeGOTAndStubAccesses(LinkGraph &G) { 52 LLVM_DEBUG(dbgs() << "Optimizing GOT entries and stubs:\n"); 53 54 for (auto *B : G.blocks()) 55 for (auto &E : B->edges()) { 56 if (E.getKind() == BranchPCRel32ToPtrJumpStubBypassable) { 57 auto &StubBlock = E.getTarget().getBlock(); 58 assert(StubBlock.getSize() == sizeof(PointerJumpStubContent) && 59 "Stub block should be stub sized"); 60 assert(StubBlock.edges_size() == 1 && 61 "Stub block should only have one outgoing edge"); 62 63 auto &GOTBlock = StubBlock.edges().begin()->getTarget().getBlock(); 64 assert(GOTBlock.getSize() == G.getPointerSize() && 65 "GOT block should be pointer sized"); 66 assert(GOTBlock.edges_size() == 1 && 67 "GOT block should only have one outgoing edge"); 68 69 auto &GOTTarget = GOTBlock.edges().begin()->getTarget(); 70 orc::ExecutorAddr EdgeAddr = B->getAddress() + E.getOffset(); 71 orc::ExecutorAddr TargetAddr = GOTTarget.getAddress(); 72 73 int64_t Displacement = TargetAddr - EdgeAddr + 4; 74 if (isInt<32>(Displacement)) { 75 E.setKind(BranchPCRel32); 76 E.setTarget(GOTTarget); 77 LLVM_DEBUG({ 78 dbgs() << " Replaced stub branch with direct branch:\n "; 79 printEdge(dbgs(), *B, E, getEdgeKindName(E.getKind())); 80 dbgs() << "\n"; 81 }); 82 } 83 } 84 } 85 86 return Error::success(); 87 } 88 89 } // namespace llvm::jitlink::x86 90