xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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