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