10b57cec5SDimitry Andric //===-- RuntimeDyldELF.h - Run-time dynamic linker for MC-JIT ---*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // ELF support for MC-JIT runtime dynamic linker. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDELF_H 140b57cec5SDimitry Andric #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDELF_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "RuntimeDyldImpl.h" 170b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric using namespace llvm; 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric namespace llvm { 220b57cec5SDimitry Andric namespace object { 230b57cec5SDimitry Andric class ELFObjectFileBase; 240b57cec5SDimitry Andric } 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric class RuntimeDyldELF : public RuntimeDyldImpl { 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric void resolveRelocation(const SectionEntry &Section, uint64_t Offset, 290b57cec5SDimitry Andric uint64_t Value, uint32_t Type, int64_t Addend, 300b57cec5SDimitry Andric uint64_t SymOffset = 0, SID SectionID = 0); 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric void resolveX86_64Relocation(const SectionEntry &Section, uint64_t Offset, 330b57cec5SDimitry Andric uint64_t Value, uint32_t Type, int64_t Addend, 340b57cec5SDimitry Andric uint64_t SymOffset); 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric void resolveX86Relocation(const SectionEntry &Section, uint64_t Offset, 370b57cec5SDimitry Andric uint32_t Value, uint32_t Type, int32_t Addend); 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric void resolveAArch64Relocation(const SectionEntry &Section, uint64_t Offset, 400b57cec5SDimitry Andric uint64_t Value, uint32_t Type, int64_t Addend); 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric bool resolveAArch64ShortBranch(unsigned SectionID, relocation_iterator RelI, 430b57cec5SDimitry Andric const RelocationValueRef &Value); 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric void resolveAArch64Branch(unsigned SectionID, const RelocationValueRef &Value, 460b57cec5SDimitry Andric relocation_iterator RelI, StubMap &Stubs); 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset, 490b57cec5SDimitry Andric uint32_t Value, uint32_t Type, int32_t Addend); 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric void resolvePPC32Relocation(const SectionEntry &Section, uint64_t Offset, 520b57cec5SDimitry Andric uint64_t Value, uint32_t Type, int64_t Addend); 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric void resolvePPC64Relocation(const SectionEntry &Section, uint64_t Offset, 550b57cec5SDimitry Andric uint64_t Value, uint32_t Type, int64_t Addend); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric void resolveSystemZRelocation(const SectionEntry &Section, uint64_t Offset, 580b57cec5SDimitry Andric uint64_t Value, uint32_t Type, int64_t Addend); 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric void resolveBPFRelocation(const SectionEntry &Section, uint64_t Offset, 610b57cec5SDimitry Andric uint64_t Value, uint32_t Type, int64_t Addend); 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric unsigned getMaxStubSize() const override { 640b57cec5SDimitry Andric if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) 650b57cec5SDimitry Andric return 20; // movz; movk; movk; movk; br 660b57cec5SDimitry Andric if (Arch == Triple::arm || Arch == Triple::thumb) 670b57cec5SDimitry Andric return 8; // 32-bit instruction and 32-bit address 680b57cec5SDimitry Andric else if (IsMipsO32ABI || IsMipsN32ABI) 690b57cec5SDimitry Andric return 16; 700b57cec5SDimitry Andric else if (IsMipsN64ABI) 710b57cec5SDimitry Andric return 32; 720b57cec5SDimitry Andric else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) 730b57cec5SDimitry Andric return 44; 740b57cec5SDimitry Andric else if (Arch == Triple::x86_64) 750b57cec5SDimitry Andric return 6; // 2-byte jmp instruction + 32-bit relative address 760b57cec5SDimitry Andric else if (Arch == Triple::systemz) 770b57cec5SDimitry Andric return 16; 780b57cec5SDimitry Andric else 790b57cec5SDimitry Andric return 0; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 82bdd1243dSDimitry Andric Align getStubAlignment() override { 830b57cec5SDimitry Andric if (Arch == Triple::systemz) 84bdd1243dSDimitry Andric return Align(8); 850b57cec5SDimitry Andric else 86bdd1243dSDimitry Andric return Align(1); 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric void setMipsABI(const ObjectFile &Obj) override; 900b57cec5SDimitry Andric 915ffd83dbSDimitry Andric Error findPPC64TOCSection(const object::ELFObjectFileBase &Obj, 920b57cec5SDimitry Andric ObjSectionToIDMap &LocalSections, 930b57cec5SDimitry Andric RelocationValueRef &Rel); 945ffd83dbSDimitry Andric Error findOPDEntrySection(const object::ELFObjectFileBase &Obj, 950b57cec5SDimitry Andric ObjSectionToIDMap &LocalSections, 960b57cec5SDimitry Andric RelocationValueRef &Rel); 975ffd83dbSDimitry Andric 980b57cec5SDimitry Andric protected: 990b57cec5SDimitry Andric size_t getGOTEntrySize() override; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric private: 1020b57cec5SDimitry Andric SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric // Allocate no GOT entries for use in the given section. 1050b57cec5SDimitry Andric uint64_t allocateGOTEntries(unsigned no); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric // Find GOT entry corresponding to relocation or create new one. 1080b57cec5SDimitry Andric uint64_t findOrAllocGOTEntry(const RelocationValueRef &Value, 1090b57cec5SDimitry Andric unsigned GOTRelType); 1100b57cec5SDimitry Andric 111*5f757f3fSDimitry Andric // Resolve the relative address of GOTOffset in Section ID and place 1120b57cec5SDimitry Andric // it at the given Offset 1130b57cec5SDimitry Andric void resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset, 1140b57cec5SDimitry Andric uint64_t GOTOffset, uint32_t Type); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // For a GOT entry referenced from SectionID, compute a relocation entry 1170b57cec5SDimitry Andric // that will place the final resolved value in the GOT slot 1180b57cec5SDimitry Andric RelocationEntry computeGOTOffsetRE(uint64_t GOTOffset, uint64_t SymbolOffset, 1190b57cec5SDimitry Andric unsigned Type); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric // Compute the address in memory where we can find the placeholder 1220b57cec5SDimitry Andric void *computePlaceholderAddress(unsigned SectionID, uint64_t Offset) const; 1230b57cec5SDimitry Andric 124*5f757f3fSDimitry Andric // Split out common case for creating the RelocationEntry for when the 125*5f757f3fSDimitry Andric // relocation requires no particular advanced processing. 1260b57cec5SDimitry Andric void processSimpleRelocation(unsigned SectionID, uint64_t Offset, unsigned RelType, RelocationValueRef Value); 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric // Return matching *LO16 relocation (Mips specific) 1290b57cec5SDimitry Andric uint32_t getMatchingLoRelocation(uint32_t RelType, 1300b57cec5SDimitry Andric bool IsLocal = false) const; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric // The tentative ID for the GOT section 1330b57cec5SDimitry Andric unsigned GOTSectionID; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric // Records the current number of allocated slots in the GOT 1360b57cec5SDimitry Andric // (This would be equivalent to GOTEntries.size() were it not for relocations 1370b57cec5SDimitry Andric // that consume more than one slot) 1380b57cec5SDimitry Andric unsigned CurrentGOTIndex; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric protected: 1410b57cec5SDimitry Andric // A map from section to a GOT section that has entries for section's GOT 1420b57cec5SDimitry Andric // relocations. (Mips64 specific) 1430b57cec5SDimitry Andric DenseMap<SID, SID> SectionToGOTMap; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric private: 1460b57cec5SDimitry Andric // A map to avoid duplicate got entries (Mips64 specific) 1470b57cec5SDimitry Andric StringMap<uint64_t> GOTSymbolOffsets; 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric // *HI16 relocations will be added for resolving when we find matching 1500b57cec5SDimitry Andric // *LO16 part. (Mips specific) 1510b57cec5SDimitry Andric SmallVector<std::pair<RelocationValueRef, RelocationEntry>, 8> PendingRelocs; 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric // When a module is loaded we save the SectionID of the EH frame section 1540b57cec5SDimitry Andric // in a table until we receive a request to register all unregistered 1550b57cec5SDimitry Andric // EH frame sections with the memory manager. 1560b57cec5SDimitry Andric SmallVector<SID, 2> UnregisteredEHFrameSections; 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric // Map between GOT relocation value and corresponding GOT offset 1590b57cec5SDimitry Andric std::map<RelocationValueRef, uint64_t> GOTOffsetMap; 1600b57cec5SDimitry Andric 161bdd1243dSDimitry Andric /// The ID of the current IFunc stub section 162bdd1243dSDimitry Andric unsigned IFuncStubSectionID = 0; 163bdd1243dSDimitry Andric /// The current offset into the IFunc stub section 164bdd1243dSDimitry Andric uint64_t IFuncStubOffset = 0; 165bdd1243dSDimitry Andric 166bdd1243dSDimitry Andric /// A IFunc stub and its original symbol 167bdd1243dSDimitry Andric struct IFuncStub { 168bdd1243dSDimitry Andric /// The offset of this stub in the IFunc stub section 169bdd1243dSDimitry Andric uint64_t StubOffset; 170bdd1243dSDimitry Andric /// The symbol table entry of the original symbol 171bdd1243dSDimitry Andric SymbolTableEntry OriginalSymbol; 172bdd1243dSDimitry Andric }; 173bdd1243dSDimitry Andric 174bdd1243dSDimitry Andric /// The IFunc stubs 175bdd1243dSDimitry Andric SmallVector<IFuncStub, 2> IFuncStubs; 176bdd1243dSDimitry Andric 177bdd1243dSDimitry Andric /// Create the code for the IFunc resolver at the given address. This code 178bdd1243dSDimitry Andric /// works together with the stubs created in createIFuncStub() to call the 179bdd1243dSDimitry Andric /// resolver function and then jump to the real function address. 180bdd1243dSDimitry Andric /// It must not be larger than 64B. 181bdd1243dSDimitry Andric void createIFuncResolver(uint8_t *Addr) const; 182bdd1243dSDimitry Andric /// Create the code for an IFunc stub for the IFunc that is defined in 183bdd1243dSDimitry Andric /// section IFuncSectionID at offset IFuncOffset. The IFunc resolver created 184bdd1243dSDimitry Andric /// by createIFuncResolver() is defined in the section IFuncStubSectionID at 185bdd1243dSDimitry Andric /// offset IFuncResolverOffset. The code should be written into the section 186bdd1243dSDimitry Andric /// with the id IFuncStubSectionID at the offset IFuncStubOffset. 187bdd1243dSDimitry Andric void createIFuncStub(unsigned IFuncStubSectionID, 188bdd1243dSDimitry Andric uint64_t IFuncResolverOffset, uint64_t IFuncStubOffset, 189bdd1243dSDimitry Andric unsigned IFuncSectionID, uint64_t IFuncOffset); 190bdd1243dSDimitry Andric /// Return the maximum size of a stub created by createIFuncStub() 191bdd1243dSDimitry Andric unsigned getMaxIFuncStubSize() const; 192bdd1243dSDimitry Andric 193bdd1243dSDimitry Andric void processNewSymbol(const SymbolRef &ObjSymbol, 194bdd1243dSDimitry Andric SymbolTableEntry &Entry) override; 1950b57cec5SDimitry Andric bool relocationNeedsGot(const RelocationRef &R) const override; 1960b57cec5SDimitry Andric bool relocationNeedsStub(const RelocationRef &R) const override; 1970b57cec5SDimitry Andric 198349cc55cSDimitry Andric // Process a GOTTPOFF TLS relocation for x86-64 199349cc55cSDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming) 200349cc55cSDimitry Andric void processX86_64GOTTPOFFRelocation(unsigned SectionID, uint64_t Offset, 201349cc55cSDimitry Andric RelocationValueRef Value, 202349cc55cSDimitry Andric int64_t Addend); 203349cc55cSDimitry Andric // Process a TLSLD/TLSGD relocation for x86-64 204349cc55cSDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming) 205349cc55cSDimitry Andric void processX86_64TLSRelocation(unsigned SectionID, uint64_t Offset, 206349cc55cSDimitry Andric uint64_t RelType, RelocationValueRef Value, 207349cc55cSDimitry Andric int64_t Addend, 208349cc55cSDimitry Andric const RelocationRef &GetAddrRelocation); 209349cc55cSDimitry Andric 2100b57cec5SDimitry Andric public: 2110b57cec5SDimitry Andric RuntimeDyldELF(RuntimeDyld::MemoryManager &MemMgr, 2120b57cec5SDimitry Andric JITSymbolResolver &Resolver); 2130b57cec5SDimitry Andric ~RuntimeDyldELF() override; 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric static std::unique_ptr<RuntimeDyldELF> 2160b57cec5SDimitry Andric create(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MemMgr, 2170b57cec5SDimitry Andric JITSymbolResolver &Resolver); 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric std::unique_ptr<RuntimeDyld::LoadedObjectInfo> 2200b57cec5SDimitry Andric loadObject(const object::ObjectFile &O) override; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override; 2230b57cec5SDimitry Andric Expected<relocation_iterator> 2240b57cec5SDimitry Andric processRelocationRef(unsigned SectionID, relocation_iterator RelI, 2250b57cec5SDimitry Andric const ObjectFile &Obj, 2260b57cec5SDimitry Andric ObjSectionToIDMap &ObjSectionToID, 2270b57cec5SDimitry Andric StubMap &Stubs) override; 2280b57cec5SDimitry Andric bool isCompatibleFile(const object::ObjectFile &Obj) const override; 2290b57cec5SDimitry Andric void registerEHFrames() override; 2300b57cec5SDimitry Andric Error finalizeLoad(const ObjectFile &Obj, 2310b57cec5SDimitry Andric ObjSectionToIDMap &SectionMap) override; 2320b57cec5SDimitry Andric }; 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric } // end namespace llvm 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric #endif 237