90 lines · cpp
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-exception6//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 17namespace llvm::jitlink::x86 {18 19const 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 46const char NullPointerContent[PointerSize] = {0x00, 0x00, 0x00, 0x00};47 48const char PointerJumpStubContent[6] = {49 static_cast<char>(0xFFu), 0x25, 0x00, 0x00, 0x00, 0x00};50 51Error 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::x8690