diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 | 
| commit | c0981da47d5696fe36474fcf86b4ce03ae3ff818 (patch) | |
| tree | f42add1021b9f2ac6a69ac7cf6c4499962739a45 /llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp | |
| parent | 344a3780b2e33f6ca763666c380202b18aab72a3 (diff) | |
Diffstat (limited to 'llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp')
| -rw-r--r-- | llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp | 77 | 
1 files changed, 77 insertions, 0 deletions
diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp index e8dd1bb90c9a..ee1630a2ffa8 100644 --- a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -9,12 +9,17 @@  #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"  #include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/JITLink/x86_64.h"  #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"  #include "llvm/IR/IRBuilder.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCInstrAnalysis.h"  #include "llvm/Support/Format.h"  #include "llvm/Transforms/Utils/Cloning.h"  #include <sstream> +#define DEBUG_TYPE "orc" +  using namespace llvm;  using namespace llvm::orc; @@ -372,5 +377,77 @@ void cloneModuleFlagsMetadata(Module &Dst, const Module &Src,      Dst.addModuleFlag(MapMetadata(MF, VMap));  } +Error addFunctionPointerRelocationsToCurrentSymbol(jitlink::Symbol &Sym, +                                                   jitlink::LinkGraph &G, +                                                   MCDisassembler &Disassembler, +                                                   MCInstrAnalysis &MIA) { +  // AArch64 appears to already come with the necessary relocations. Among other +  // architectures, only x86_64 is currently implemented here. +  if (G.getTargetTriple().getArch() != Triple::x86_64) +    return Error::success(); + +  raw_null_ostream CommentStream; +  auto &STI = Disassembler.getSubtargetInfo(); + +  // Determine the function bounds +  auto &B = Sym.getBlock(); +  assert(!B.isZeroFill() && "expected content block"); +  auto SymAddress = Sym.getAddress(); +  auto SymStartInBlock = +      (const uint8_t *)B.getContent().data() + Sym.getOffset(); +  auto SymSize = Sym.getSize() ? Sym.getSize() : B.getSize() - Sym.getOffset(); +  auto Content = makeArrayRef(SymStartInBlock, SymSize); + +  LLVM_DEBUG(dbgs() << "Adding self-relocations to " << Sym.getName() << "\n"); + +  SmallDenseSet<uintptr_t, 8> ExistingRelocations; +  for (auto &E : B.edges()) { +    if (E.isRelocation()) +      ExistingRelocations.insert(E.getOffset()); +  } + +  size_t I = 0; +  while (I < Content.size()) { +    MCInst Instr; +    uint64_t InstrSize = 0; +    uint64_t InstrStart = SymAddress + I; +    auto DecodeStatus = Disassembler.getInstruction( +        Instr, InstrSize, Content.drop_front(I), InstrStart, CommentStream); +    if (DecodeStatus != MCDisassembler::Success) { +      LLVM_DEBUG(dbgs() << "Aborting due to disassembly failure at address " +                        << InstrStart); +      return make_error<StringError>( +          formatv("failed to disassemble at address {0:x16}", InstrStart), +          inconvertibleErrorCode()); +    } +    // Advance to the next instruction. +    I += InstrSize; + +    // Check for a PC-relative address equal to the symbol itself. +    auto PCRelAddr = +        MIA.evaluateMemoryOperandAddress(Instr, &STI, InstrStart, InstrSize); +    if (!PCRelAddr.hasValue() || PCRelAddr.getValue() != SymAddress) +      continue; + +    auto RelocOffInInstr = +        MIA.getMemoryOperandRelocationOffset(Instr, InstrSize); +    if (!RelocOffInInstr.hasValue() || +        InstrSize - RelocOffInInstr.getValue() != 4) { +      LLVM_DEBUG(dbgs() << "Skipping unknown self-relocation at " +                        << InstrStart); +      continue; +    } + +    auto RelocOffInBlock = +        InstrStart + *RelocOffInInstr - SymAddress + Sym.getOffset(); +    if (ExistingRelocations.contains(RelocOffInBlock)) +      continue; + +    LLVM_DEBUG(dbgs() << "Adding delta32 self-relocation at " << InstrStart); +    B.addEdge(jitlink::x86_64::Delta32, RelocOffInBlock, Sym, /*Addend=*/-4); +  } +  return Error::success(); +} +  } // End namespace orc.  } // End namespace llvm.  | 
