1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
//===-- RuntimeDyldELF.h - Run-time dynamic linker for MC-JIT ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// ELF support for MC-JIT runtime dynamic linker.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDELF_H
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDELF_H
#include "RuntimeDyldImpl.h"
#include "llvm/ADT/DenseMap.h"
using namespace llvm;
namespace llvm {
namespace object {
class ELFObjectFileBase;
}
class RuntimeDyldELF : public RuntimeDyldImpl {
void resolveRelocation(const SectionEntry &Section, uint64_t Offset,
uint64_t Value, uint32_t Type, int64_t Addend,
uint64_t SymOffset = 0, SID SectionID = 0);
void resolveX86_64Relocation(const SectionEntry &Section, uint64_t Offset,
uint64_t Value, uint32_t Type, int64_t Addend,
uint64_t SymOffset);
void resolveX86Relocation(const SectionEntry &Section, uint64_t Offset,
uint32_t Value, uint32_t Type, int32_t Addend);
void resolveAArch64Relocation(const SectionEntry &Section, uint64_t Offset,
uint64_t Value, uint32_t Type, int64_t Addend);
bool resolveAArch64ShortBranch(unsigned SectionID, relocation_iterator RelI,
const RelocationValueRef &Value);
void resolveAArch64Branch(unsigned SectionID, const RelocationValueRef &Value,
relocation_iterator RelI, StubMap &Stubs);
void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset,
uint32_t Value, uint32_t Type, int32_t Addend);
void resolvePPC32Relocation(const SectionEntry &Section, uint64_t Offset,
uint64_t Value, uint32_t Type, int64_t Addend);
void resolvePPC64Relocation(const SectionEntry &Section, uint64_t Offset,
uint64_t Value, uint32_t Type, int64_t Addend);
void resolveSystemZRelocation(const SectionEntry &Section, uint64_t Offset,
uint64_t Value, uint32_t Type, int64_t Addend);
void resolveBPFRelocation(const SectionEntry &Section, uint64_t Offset,
uint64_t Value, uint32_t Type, int64_t Addend);
unsigned getMaxStubSize() const override {
if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be)
return 20; // movz; movk; movk; movk; br
if (Arch == Triple::arm || Arch == Triple::thumb)
return 8; // 32-bit instruction and 32-bit address
else if (IsMipsO32ABI || IsMipsN32ABI)
return 16;
else if (IsMipsN64ABI)
return 32;
else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le)
return 44;
else if (Arch == Triple::x86_64)
return 6; // 2-byte jmp instruction + 32-bit relative address
else if (Arch == Triple::systemz)
return 16;
else
return 0;
}
unsigned getStubAlignment() override {
if (Arch == Triple::systemz)
return 8;
else
return 1;
}
void setMipsABI(const ObjectFile &Obj) override;
Error findPPC64TOCSection(const object::ELFObjectFileBase &Obj,
ObjSectionToIDMap &LocalSections,
RelocationValueRef &Rel);
Error findOPDEntrySection(const object::ELFObjectFileBase &Obj,
ObjSectionToIDMap &LocalSections,
RelocationValueRef &Rel);
protected:
size_t getGOTEntrySize() override;
private:
SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; }
// Allocate no GOT entries for use in the given section.
uint64_t allocateGOTEntries(unsigned no);
// Find GOT entry corresponding to relocation or create new one.
uint64_t findOrAllocGOTEntry(const RelocationValueRef &Value,
unsigned GOTRelType);
// Resolve the relvative address of GOTOffset in Section ID and place
// it at the given Offset
void resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset,
uint64_t GOTOffset, uint32_t Type);
// For a GOT entry referenced from SectionID, compute a relocation entry
// that will place the final resolved value in the GOT slot
RelocationEntry computeGOTOffsetRE(uint64_t GOTOffset, uint64_t SymbolOffset,
unsigned Type);
// Compute the address in memory where we can find the placeholder
void *computePlaceholderAddress(unsigned SectionID, uint64_t Offset) const;
// Split out common case for createing the RelocationEntry for when the relocation requires
// no particular advanced processing.
void processSimpleRelocation(unsigned SectionID, uint64_t Offset, unsigned RelType, RelocationValueRef Value);
// Return matching *LO16 relocation (Mips specific)
uint32_t getMatchingLoRelocation(uint32_t RelType,
bool IsLocal = false) const;
// The tentative ID for the GOT section
unsigned GOTSectionID;
// Records the current number of allocated slots in the GOT
// (This would be equivalent to GOTEntries.size() were it not for relocations
// that consume more than one slot)
unsigned CurrentGOTIndex;
protected:
// A map from section to a GOT section that has entries for section's GOT
// relocations. (Mips64 specific)
DenseMap<SID, SID> SectionToGOTMap;
private:
// A map to avoid duplicate got entries (Mips64 specific)
StringMap<uint64_t> GOTSymbolOffsets;
// *HI16 relocations will be added for resolving when we find matching
// *LO16 part. (Mips specific)
SmallVector<std::pair<RelocationValueRef, RelocationEntry>, 8> PendingRelocs;
// When a module is loaded we save the SectionID of the EH frame section
// in a table until we receive a request to register all unregistered
// EH frame sections with the memory manager.
SmallVector<SID, 2> UnregisteredEHFrameSections;
// Map between GOT relocation value and corresponding GOT offset
std::map<RelocationValueRef, uint64_t> GOTOffsetMap;
bool relocationNeedsGot(const RelocationRef &R) const override;
bool relocationNeedsStub(const RelocationRef &R) const override;
// Process a GOTTPOFF TLS relocation for x86-64
// NOLINTNEXTLINE(readability-identifier-naming)
void processX86_64GOTTPOFFRelocation(unsigned SectionID, uint64_t Offset,
RelocationValueRef Value,
int64_t Addend);
// Process a TLSLD/TLSGD relocation for x86-64
// NOLINTNEXTLINE(readability-identifier-naming)
void processX86_64TLSRelocation(unsigned SectionID, uint64_t Offset,
uint64_t RelType, RelocationValueRef Value,
int64_t Addend,
const RelocationRef &GetAddrRelocation);
public:
RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr,
JITSymbolResolver &Resolver);
~RuntimeDyldELF() override;
static std::unique_ptr<RuntimeDyldELF>
create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr,
JITSymbolResolver &Resolver);
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
loadObject(const object::ObjectFile &O) override;
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override;
Expected<relocation_iterator>
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
const ObjectFile &Obj,
ObjSectionToIDMap &ObjSectionToID,
StubMap &Stubs) override;
bool isCompatibleFile(const object::ObjectFile &Obj) const override;
void registerEHFrames() override;
Error finalizeLoad(const ObjectFile &Obj,
ObjSectionToIDMap &SectionMap) override;
};
} // end namespace llvm
#endif
|