[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / lib / ExecutionEngine / RuntimeDyld / Targets / RuntimeDyldCOFFI386.h
blob40910bea0c364493c85bc6f68f20374558cb9378
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.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
14 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
16 #include "../RuntimeDyldCOFF.h"
17 #include "llvm/BinaryFormat/COFF.h"
18 #include "llvm/Object/COFF.h"
20 #define DEBUG_TYPE "dyld"
22 namespace llvm {
24 class RuntimeDyldCOFFI386 : public RuntimeDyldCOFF {
25 public:
26 RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM,
27 JITSymbolResolver &Resolver)
28 : RuntimeDyldCOFF(MM, Resolver) {}
30 unsigned getMaxStubSize() const override {
31 return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
34 unsigned getStubAlignment() override { return 1; }
36 Expected<object::relocation_iterator>
37 processRelocationRef(unsigned SectionID,
38 object::relocation_iterator RelI,
39 const object::ObjectFile &Obj,
40 ObjSectionToIDMap &ObjSectionToID,
41 StubMap &Stubs) override {
43 auto Symbol = RelI->getSymbol();
44 if (Symbol == Obj.symbol_end())
45 report_fatal_error("Unknown symbol in relocation");
47 Expected<StringRef> TargetNameOrErr = Symbol->getName();
48 if (!TargetNameOrErr)
49 return TargetNameOrErr.takeError();
50 StringRef TargetName = *TargetNameOrErr;
52 auto SectionOrErr = Symbol->getSection();
53 if (!SectionOrErr)
54 return SectionOrErr.takeError();
55 auto Section = *SectionOrErr;
57 uint64_t RelType = RelI->getType();
58 uint64_t Offset = RelI->getOffset();
60 // Determine the Addend used to adjust the relocation value.
61 uint64_t Addend = 0;
62 SectionEntry &AddendSection = Sections[SectionID];
63 uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
64 uint8_t *Displacement = (uint8_t *)ObjTarget;
66 switch (RelType) {
67 case COFF::IMAGE_REL_I386_DIR32:
68 case COFF::IMAGE_REL_I386_DIR32NB:
69 case COFF::IMAGE_REL_I386_SECREL:
70 case COFF::IMAGE_REL_I386_REL32: {
71 Addend = readBytesUnaligned(Displacement, 4);
72 break;
74 default:
75 break;
78 #if !defined(NDEBUG)
79 SmallString<32> RelTypeName;
80 RelI->getTypeName(RelTypeName);
81 #endif
82 LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
83 << " RelType: " << RelTypeName << " TargetName: "
84 << TargetName << " Addend " << Addend << "\n");
86 unsigned TargetSectionID = -1;
87 if (Section == Obj.section_end()) {
88 RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
89 addRelocationForSymbol(RE, TargetName);
90 } else {
91 if (auto TargetSectionIDOrErr =
92 findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
93 TargetSectionID = *TargetSectionIDOrErr;
94 else
95 return TargetSectionIDOrErr.takeError();
97 switch (RelType) {
98 case COFF::IMAGE_REL_I386_ABSOLUTE:
99 // This relocation is ignored.
100 break;
101 case COFF::IMAGE_REL_I386_DIR32:
102 case COFF::IMAGE_REL_I386_DIR32NB:
103 case COFF::IMAGE_REL_I386_REL32: {
104 RelocationEntry RE =
105 RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
106 getSymbolOffset(*Symbol), 0, 0, false, 0);
107 addRelocationForSection(RE, TargetSectionID);
108 break;
110 case COFF::IMAGE_REL_I386_SECTION: {
111 RelocationEntry RE =
112 RelocationEntry(TargetSectionID, Offset, RelType, 0);
113 addRelocationForSection(RE, TargetSectionID);
114 break;
116 case COFF::IMAGE_REL_I386_SECREL: {
117 RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
118 getSymbolOffset(*Symbol) + Addend);
119 addRelocationForSection(RE, TargetSectionID);
120 break;
122 default:
123 llvm_unreachable("unsupported relocation type");
128 return ++RelI;
131 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
132 const auto Section = Sections[RE.SectionID];
133 uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
135 switch (RE.RelType) {
136 case COFF::IMAGE_REL_I386_ABSOLUTE:
137 // This relocation is ignored.
138 break;
139 case COFF::IMAGE_REL_I386_DIR32: {
140 // The target's 32-bit VA.
141 uint64_t Result =
142 RE.Sections.SectionA == static_cast<uint32_t>(-1)
143 ? Value
144 : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(
145 RE.Addend);
146 assert(Result <= UINT32_MAX && "relocation overflow");
147 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
148 << " RelType: IMAGE_REL_I386_DIR32"
149 << " TargetSection: " << RE.Sections.SectionA
150 << " Value: " << format("0x%08" PRIx32, Result)
151 << '\n');
152 writeBytesUnaligned(Result, Target, 4);
153 break;
155 case COFF::IMAGE_REL_I386_DIR32NB: {
156 // The target's 32-bit RVA.
157 // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
158 uint64_t Result =
159 Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend) -
160 Sections[0].getLoadAddress();
161 assert(Result <= UINT32_MAX && "relocation overflow");
162 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
163 << " RelType: IMAGE_REL_I386_DIR32NB"
164 << " TargetSection: " << RE.Sections.SectionA
165 << " Value: " << format("0x%08" PRIx32, Result)
166 << '\n');
167 writeBytesUnaligned(Result, Target, 4);
168 break;
170 case COFF::IMAGE_REL_I386_REL32: {
171 // 32-bit relative displacement to the target.
172 uint64_t Result = RE.Sections.SectionA == static_cast<uint32_t>(-1)
173 ? Value
174 : Sections[RE.Sections.SectionA].getLoadAddress();
175 Result = Result - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset;
176 assert(static_cast<int64_t>(Result) <= INT32_MAX &&
177 "relocation overflow");
178 assert(static_cast<int64_t>(Result) >= INT32_MIN &&
179 "relocation underflow");
180 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
181 << " RelType: IMAGE_REL_I386_REL32"
182 << " TargetSection: " << RE.Sections.SectionA
183 << " Value: " << format("0x%08" PRIx32, Result)
184 << '\n');
185 writeBytesUnaligned(Result, Target, 4);
186 break;
188 case COFF::IMAGE_REL_I386_SECTION:
189 // 16-bit section index of the section that contains the target.
190 assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX &&
191 "relocation overflow");
192 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
193 << " RelType: IMAGE_REL_I386_SECTION Value: "
194 << RE.SectionID << '\n');
195 writeBytesUnaligned(RE.SectionID, Target, 2);
196 break;
197 case COFF::IMAGE_REL_I386_SECREL:
198 // 32-bit offset of the target from the beginning of its section.
199 assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX &&
200 "relocation overflow");
201 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
202 << " RelType: IMAGE_REL_I386_SECREL Value: "
203 << RE.Addend << '\n');
204 writeBytesUnaligned(RE.Addend, Target, 4);
205 break;
206 default:
207 llvm_unreachable("unsupported relocation type");
211 void registerEHFrames() override {}
216 #endif