1 //===-- RuntimeDyldELF.h - Run-time dynamic linker for MC-JIT ---*- C++ -*-===//
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-exception
7 //===----------------------------------------------------------------------===//
9 // ELF support for MC-JIT runtime dynamic linker.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDELF_H
14 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDELF_H
16 #include "RuntimeDyldImpl.h"
17 #include "llvm/ADT/DenseMap.h"
21 class ELFObjectFileBase
;
24 class RuntimeDyldELF
: public RuntimeDyldImpl
{
26 void resolveRelocation(const SectionEntry
&Section
, uint64_t Offset
,
27 uint64_t Value
, uint32_t Type
, int64_t Addend
,
28 uint64_t SymOffset
= 0, SID SectionID
= 0);
30 void resolveX86_64Relocation(const SectionEntry
&Section
, uint64_t Offset
,
31 uint64_t Value
, uint32_t Type
, int64_t Addend
,
34 void resolveX86Relocation(const SectionEntry
&Section
, uint64_t Offset
,
35 uint32_t Value
, uint32_t Type
, int32_t Addend
);
37 void resolveAArch64Relocation(const SectionEntry
&Section
, uint64_t Offset
,
38 uint64_t Value
, uint32_t Type
, int64_t Addend
);
40 bool resolveAArch64ShortBranch(unsigned SectionID
, relocation_iterator RelI
,
41 const RelocationValueRef
&Value
);
43 void resolveAArch64Branch(unsigned SectionID
, const RelocationValueRef
&Value
,
44 relocation_iterator RelI
, StubMap
&Stubs
);
46 void resolveARMRelocation(const SectionEntry
&Section
, uint64_t Offset
,
47 uint32_t Value
, uint32_t Type
, int32_t Addend
);
49 void resolveLoongArch64Relocation(const SectionEntry
&Section
,
50 uint64_t Offset
, uint64_t Value
,
51 uint32_t Type
, int64_t Addend
);
53 bool resolveLoongArch64ShortBranch(unsigned SectionID
,
54 relocation_iterator RelI
,
55 const RelocationValueRef
&Value
);
57 void resolveLoongArch64Branch(unsigned SectionID
,
58 const RelocationValueRef
&Value
,
59 relocation_iterator RelI
, StubMap
&Stubs
);
61 void resolvePPC32Relocation(const SectionEntry
&Section
, uint64_t Offset
,
62 uint64_t Value
, uint32_t Type
, int64_t Addend
);
64 void resolvePPC64Relocation(const SectionEntry
&Section
, uint64_t Offset
,
65 uint64_t Value
, uint32_t Type
, int64_t Addend
);
67 void resolveSystemZRelocation(const SectionEntry
&Section
, uint64_t Offset
,
68 uint64_t Value
, uint32_t Type
, int64_t Addend
);
70 void resolveBPFRelocation(const SectionEntry
&Section
, uint64_t Offset
,
71 uint64_t Value
, uint32_t Type
, int64_t Addend
);
73 void resolveRISCVRelocation(const SectionEntry
&Section
, uint64_t Offset
,
74 uint64_t Value
, uint32_t Type
, int64_t Addend
,
77 unsigned getMaxStubSize() const override
{
78 if (Arch
== Triple::aarch64
|| Arch
== Triple::aarch64_be
)
79 return 20; // movz; movk; movk; movk; br
80 if (Arch
== Triple::arm
|| Arch
== Triple::thumb
)
81 return 8; // 32-bit instruction and 32-bit address
82 else if (IsMipsO32ABI
|| IsMipsN32ABI
)
84 else if (IsMipsN64ABI
)
86 if (Arch
== Triple::loongarch64
)
87 return 20; // lu12i.w; ori; lu32i.d; lu52i.d; jr
88 else if (Arch
== Triple::ppc64
|| Arch
== Triple::ppc64le
)
90 else if (Arch
== Triple::x86_64
)
91 return 6; // 2-byte jmp instruction + 32-bit relative address
92 else if (Arch
== Triple::systemz
)
98 Align
getStubAlignment() override
{
99 if (Arch
== Triple::systemz
)
105 void setMipsABI(const ObjectFile
&Obj
) override
;
107 Error
findPPC64TOCSection(const object::ELFObjectFileBase
&Obj
,
108 ObjSectionToIDMap
&LocalSections
,
109 RelocationValueRef
&Rel
);
110 Error
findOPDEntrySection(const object::ELFObjectFileBase
&Obj
,
111 ObjSectionToIDMap
&LocalSections
,
112 RelocationValueRef
&Rel
);
115 size_t getGOTEntrySize() override
;
118 SectionEntry
&getSection(unsigned SectionID
) { return Sections
[SectionID
]; }
120 // Allocate no GOT entries for use in the given section.
121 uint64_t allocateGOTEntries(unsigned no
);
123 // Find GOT entry corresponding to relocation or create new one.
124 uint64_t findOrAllocGOTEntry(const RelocationValueRef
&Value
,
125 unsigned GOTRelType
);
127 // Resolve the relative address of GOTOffset in Section ID and place
128 // it at the given Offset
129 void resolveGOTOffsetRelocation(unsigned SectionID
, uint64_t Offset
,
130 uint64_t GOTOffset
, uint32_t Type
);
132 // For a GOT entry referenced from SectionID, compute a relocation entry
133 // that will place the final resolved value in the GOT slot
134 RelocationEntry
computeGOTOffsetRE(uint64_t GOTOffset
, uint64_t SymbolOffset
,
137 // Compute the address in memory where we can find the placeholder
138 void *computePlaceholderAddress(unsigned SectionID
, uint64_t Offset
) const;
140 // Split out common case for creating the RelocationEntry for when the
141 // relocation requires no particular advanced processing.
142 void processSimpleRelocation(unsigned SectionID
, uint64_t Offset
, unsigned RelType
, RelocationValueRef Value
);
144 // Return matching *LO16 relocation (Mips specific)
145 uint32_t getMatchingLoRelocation(uint32_t RelType
,
146 bool IsLocal
= false) const;
148 // The tentative ID for the GOT section
149 unsigned GOTSectionID
;
151 // Records the current number of allocated slots in the GOT
152 // (This would be equivalent to GOTEntries.size() were it not for relocations
153 // that consume more than one slot)
154 unsigned CurrentGOTIndex
;
157 // A map from section to a GOT section that has entries for section's GOT
158 // relocations. (Mips64 specific)
159 DenseMap
<SID
, SID
> SectionToGOTMap
;
162 // A map to avoid duplicate got entries (Mips64 specific)
163 StringMap
<uint64_t> GOTSymbolOffsets
;
165 // *HI16 relocations will be added for resolving when we find matching
166 // *LO16 part. (Mips specific)
168 // *HI20 relocations will be added for resolving when we find matching
169 // *LO12 part. (RISC-V specific)
170 SmallVector
<std::pair
<RelocationValueRef
, RelocationEntry
>, 8> PendingRelocs
;
172 // When a module is loaded we save the SectionID of the EH frame section
173 // in a table until we receive a request to register all unregistered
174 // EH frame sections with the memory manager.
175 SmallVector
<SID
, 2> UnregisteredEHFrameSections
;
177 // Map between GOT relocation value and corresponding GOT offset
178 std::map
<RelocationValueRef
, uint64_t> GOTOffsetMap
;
180 /// The ID of the current IFunc stub section
181 unsigned IFuncStubSectionID
= 0;
182 /// The current offset into the IFunc stub section
183 uint64_t IFuncStubOffset
= 0;
185 /// A IFunc stub and its original symbol
187 /// The offset of this stub in the IFunc stub section
189 /// The symbol table entry of the original symbol
190 SymbolTableEntry OriginalSymbol
;
194 SmallVector
<IFuncStub
, 2> IFuncStubs
;
196 /// Create the code for the IFunc resolver at the given address. This code
197 /// works together with the stubs created in createIFuncStub() to call the
198 /// resolver function and then jump to the real function address.
199 /// It must not be larger than 64B.
200 void createIFuncResolver(uint8_t *Addr
) const;
201 /// Create the code for an IFunc stub for the IFunc that is defined in
202 /// section IFuncSectionID at offset IFuncOffset. The IFunc resolver created
203 /// by createIFuncResolver() is defined in the section IFuncStubSectionID at
204 /// offset IFuncResolverOffset. The code should be written into the section
205 /// with the id IFuncStubSectionID at the offset IFuncStubOffset.
206 void createIFuncStub(unsigned IFuncStubSectionID
,
207 uint64_t IFuncResolverOffset
, uint64_t IFuncStubOffset
,
208 unsigned IFuncSectionID
, uint64_t IFuncOffset
);
209 /// Return the maximum size of a stub created by createIFuncStub()
210 unsigned getMaxIFuncStubSize() const;
212 void processNewSymbol(const SymbolRef
&ObjSymbol
,
213 SymbolTableEntry
&Entry
) override
;
214 bool relocationNeedsGot(const RelocationRef
&R
) const override
;
215 bool relocationNeedsStub(const RelocationRef
&R
) const override
;
217 // Process a GOTTPOFF TLS relocation for x86-64
218 // NOLINTNEXTLINE(readability-identifier-naming)
219 void processX86_64GOTTPOFFRelocation(unsigned SectionID
, uint64_t Offset
,
220 RelocationValueRef Value
,
222 // Process a TLSLD/TLSGD relocation for x86-64
223 // NOLINTNEXTLINE(readability-identifier-naming)
224 void processX86_64TLSRelocation(unsigned SectionID
, uint64_t Offset
,
225 uint64_t RelType
, RelocationValueRef Value
,
227 const RelocationRef
&GetAddrRelocation
);
230 RuntimeDyldELF(RuntimeDyld::MemoryManager
&MemMgr
,
231 JITSymbolResolver
&Resolver
);
232 ~RuntimeDyldELF() override
;
234 static std::unique_ptr
<RuntimeDyldELF
>
235 create(Triple::ArchType Arch
, RuntimeDyld::MemoryManager
&MemMgr
,
236 JITSymbolResolver
&Resolver
);
238 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
>
239 loadObject(const object::ObjectFile
&O
) override
;
241 void resolveRelocation(const RelocationEntry
&RE
, uint64_t Value
) override
;
242 Expected
<relocation_iterator
>
243 processRelocationRef(unsigned SectionID
, relocation_iterator RelI
,
244 const ObjectFile
&Obj
,
245 ObjSectionToIDMap
&ObjSectionToID
,
246 StubMap
&Stubs
) override
;
247 bool isCompatibleFile(const object::ObjectFile
&Obj
) const override
;
248 void registerEHFrames() override
;
249 Error
finalizeLoad(const ObjectFile
&Obj
,
250 ObjSectionToIDMap
&SectionMap
) override
;
253 } // end namespace llvm
255 #endif // LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDELF_H