LLVM 19.0.0git
RuntimeDyldCOFFI386.h
Go to the documentation of this file.
1//===--- RuntimeDyldCOFFI386.h --- COFF/X86_64 specific code ---*- C++ --*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// COFF x86 support for MC-JIT runtime dynamic linker.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
14#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
15
16#include "../RuntimeDyldCOFF.h"
18#include "llvm/Object/COFF.h"
19
20#define DEBUG_TYPE "dyld"
21
22namespace llvm {
23
25public:
28 : RuntimeDyldCOFF(MM, Resolver, 4, COFF::IMAGE_REL_I386_DIR32) {}
29
30 unsigned getMaxStubSize() const override {
31 return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
32 }
33
34 Align getStubAlignment() override { return Align(1); }
35
37 processRelocationRef(unsigned SectionID,
39 const object::ObjectFile &Obj,
40 ObjSectionToIDMap &ObjSectionToID,
41 StubMap &Stubs) override {
42
43 auto Symbol = RelI->getSymbol();
44 if (Symbol == Obj.symbol_end())
45 report_fatal_error("Unknown symbol in relocation");
46
47 Expected<StringRef> TargetNameOrErr = Symbol->getName();
48 if (!TargetNameOrErr)
49 return TargetNameOrErr.takeError();
50 StringRef TargetName = *TargetNameOrErr;
51
52 auto SectionOrErr = Symbol->getSection();
53 if (!SectionOrErr)
54 return SectionOrErr.takeError();
55 auto Section = *SectionOrErr;
56 bool IsExtern = Section == Obj.section_end();
57
58 uint64_t RelType = RelI->getType();
59 uint64_t Offset = RelI->getOffset();
60
61 unsigned TargetSectionID = -1;
62 uint64_t TargetOffset = -1;
63 if (TargetName.starts_with(getImportSymbolPrefix())) {
64 TargetSectionID = SectionID;
65 TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName, true);
66 TargetName = StringRef();
67 IsExtern = false;
68 } else if (!IsExtern) {
69 if (auto TargetSectionIDOrErr = findOrEmitSection(
70 Obj, *Section, Section->isText(), ObjSectionToID))
71 TargetSectionID = *TargetSectionIDOrErr;
72 else
73 return TargetSectionIDOrErr.takeError();
74 if (RelType != COFF::IMAGE_REL_I386_SECTION)
75 TargetOffset = getSymbolOffset(*Symbol);
76 }
77
78 // Determine the Addend used to adjust the relocation value.
79 uint64_t Addend = 0;
80 SectionEntry &AddendSection = Sections[SectionID];
81 uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
82 uint8_t *Displacement = (uint8_t *)ObjTarget;
83
84 switch (RelType) {
89 Addend = readBytesUnaligned(Displacement, 4);
90 break;
91 }
92 default:
93 break;
94 }
95
96#if !defined(NDEBUG)
97 SmallString<32> RelTypeName;
98 RelI->getTypeName(RelTypeName);
99#endif
100 LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
101 << " RelType: " << RelTypeName << " TargetName: "
102 << TargetName << " Addend " << Addend << "\n");
103
104 if (IsExtern) {
105 RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
106 addRelocationForSymbol(RE, TargetName);
107 } else {
108
109 switch (RelType) {
111 // This relocation is ignored.
112 break;
116 RelocationEntry RE =
117 RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
118 TargetOffset, 0, 0, false, 0);
119 addRelocationForSection(RE, TargetSectionID);
120 break;
121 }
123 RelocationEntry RE =
124 RelocationEntry(TargetSectionID, Offset, RelType, 0);
125 addRelocationForSection(RE, TargetSectionID);
126 break;
127 }
129 RelocationEntry RE =
130 RelocationEntry(SectionID, Offset, RelType, TargetOffset + Addend);
131 addRelocationForSection(RE, TargetSectionID);
132 break;
133 }
134 default:
135 llvm_unreachable("unsupported relocation type");
136 }
137 }
138
139 return ++RelI;
140 }
141
143 const auto Section = Sections[RE.SectionID];
144 uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
145
146 switch (RE.RelType) {
148 // This relocation is ignored.
149 break;
151 // The target's 32-bit VA.
152 uint64_t Result =
153 RE.Sections.SectionA == static_cast<uint32_t>(-1)
154 ? Value
155 : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(
156 RE.Addend);
157 assert(Result <= UINT32_MAX && "relocation overflow");
158 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
159 << " RelType: IMAGE_REL_I386_DIR32"
160 << " TargetSection: " << RE.Sections.SectionA
161 << " Value: " << format("0x%08" PRIx32, Result)
162 << '\n');
163 writeBytesUnaligned(Result, Target, 4);
164 break;
165 }
167 // The target's 32-bit RVA.
168 // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
169 uint64_t Result =
170 Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend) -
171 Sections[0].getLoadAddress();
172 assert(Result <= UINT32_MAX && "relocation overflow");
173 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
174 << " RelType: IMAGE_REL_I386_DIR32NB"
175 << " TargetSection: " << RE.Sections.SectionA
176 << " Value: " << format("0x%08" PRIx32, Result)
177 << '\n');
178 writeBytesUnaligned(Result, Target, 4);
179 break;
180 }
182 // 32-bit relative displacement to the target.
183 uint64_t Result = RE.Sections.SectionA == static_cast<uint32_t>(-1)
184 ? Value
185 : Sections[RE.Sections.SectionA].getLoadAddress();
186 Result = Result - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset;
187 assert(static_cast<int64_t>(Result) <= INT32_MAX &&
188 "relocation overflow");
189 assert(static_cast<int64_t>(Result) >= INT32_MIN &&
190 "relocation underflow");
191 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
192 << " RelType: IMAGE_REL_I386_REL32"
193 << " TargetSection: " << RE.Sections.SectionA
194 << " Value: " << format("0x%08" PRIx32, Result)
195 << '\n');
196 writeBytesUnaligned(Result, Target, 4);
197 break;
198 }
200 // 16-bit section index of the section that contains the target.
201 assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX &&
202 "relocation overflow");
203 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
204 << " RelType: IMAGE_REL_I386_SECTION Value: "
205 << RE.SectionID << '\n');
207 break;
209 // 32-bit offset of the target from the beginning of its section.
210 assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX &&
211 "relocation overflow");
212 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
213 << " RelType: IMAGE_REL_I386_SECREL Value: "
214 << RE.Addend << '\n');
216 break;
217 default:
218 llvm_unreachable("unsupported relocation type");
219 }
220 }
221
222 void registerEHFrames() override {}
223};
224
225}
226
227#endif
228
#define LLVM_DEBUG(X)
Definition: Debug.h:101
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Tagged union holding either a T or a Error.
Definition: Error.h:474
Error takeError()
Take ownership of the stored error.
Definition: Error.h:601
Symbol resolution interface.
Definition: JITSymbol.h:371
RelocationEntry - used to represent relocations internally in the dynamic linker.
uint32_t RelType
RelType - relocation type.
uint64_t Offset
Offset - offset into the section.
int64_t Addend
Addend - the relocation addend encoded in the instruction itself.
unsigned SectionID
SectionID - the section this relocation points to.
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
Definition: Record.h:2213
Align getStubAlignment() override
Expected< object::relocation_iterator > processRelocationRef(unsigned SectionID, object::relocation_iterator RelI, const object::ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) override
Parses one or more object file relocations (some object files use relocation pairs) and stores it to ...
RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver)
unsigned getMaxStubSize() const override
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override
A object file specific relocation resolver.
uint64_t getSymbolOffset(const SymbolRef &Sym)
static constexpr StringRef getImportSymbolPrefix()
uint64_t getDLLImportOffset(unsigned SectionID, StubMap &Stubs, StringRef Name, bool SetSectionIDMinus1=false)
std::map< SectionRef, unsigned > ObjSectionToIDMap
std::map< RelocationValueRef, uintptr_t > StubMap
void addRelocationForSymbol(const RelocationEntry &RE, StringRef SymbolName)
void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID)
Expected< unsigned > findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode, ObjSectionToIDMap &LocalSections)
Find Section in LocalSections.
void writeBytesUnaligned(uint64_t Value, uint8_t *Dst, unsigned Size) const
Endian-aware write.
uint64_t readBytesUnaligned(uint8_t *Src, unsigned Size) const
Endian-aware read Read the least significant Size bytes from Src.
SectionEntry - represents a section emitted into memory by the dynamic linker.
uintptr_t getObjAddress() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:257
Target - Wrapper for Target specific information.
LLVM Value Representation.
Definition: Value.h:74
This class is the base class for all object file types.
Definition: ObjectFile.h:229
virtual section_iterator section_end() const =0
virtual basic_symbol_iterator symbol_end() const =0
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ IMAGE_REL_I386_SECTION
Definition: COFF.h:352
@ IMAGE_REL_I386_REL32
Definition: COFF.h:356
@ IMAGE_REL_I386_SECREL
Definition: COFF.h:353
@ IMAGE_REL_I386_DIR32
Definition: COFF.h:349
@ IMAGE_REL_I386_ABSOLUTE
Definition: COFF.h:346
@ IMAGE_REL_I386_DIR32NB
Definition: COFF.h:350
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:156
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39