]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / ExecutionEngine / RuntimeDyld / Targets / RuntimeDyldCOFFI386.h
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"
17 #include "llvm/BinaryFormat/COFF.h"
18 #include "llvm/Object/COFF.h"
19
20 #define DEBUG_TYPE "dyld"
21
22 namespace llvm {
23
24 class RuntimeDyldCOFFI386 : public RuntimeDyldCOFF {
25 public:
26   RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM,
27                       JITSymbolResolver &Resolver)
28       : RuntimeDyldCOFF(MM, Resolver) {}
29
30   unsigned getMaxStubSize() const override {
31     return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
32   }
33
34   unsigned getStubAlignment() override { return 1; }
35
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 {
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
57     uint64_t RelType = RelI->getType();
58     uint64_t Offset = RelI->getOffset();
59
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;
65
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;
73     }
74     default:
75       break;
76     }
77
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");
85
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();
96
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;
109       }
110       case COFF::IMAGE_REL_I386_SECTION: {
111         RelocationEntry RE =
112             RelocationEntry(TargetSectionID, Offset, RelType, 0);
113         addRelocationForSection(RE, TargetSectionID);
114         break;
115       }
116       case COFF::IMAGE_REL_I386_SECREL: {
117         RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
118                                              getSymbolOffset(*Symbol) + Addend);
119         addRelocationForSection(RE, TargetSectionID);
120         break;
121       }
122       default:
123         llvm_unreachable("unsupported relocation type");
124       }
125
126     }
127
128     return ++RelI;
129   }
130
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);
134
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;
154     }
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;
169     }
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;
187     }
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");
208     }
209   }
210
211   void registerEHFrames() override {}
212 };
213
214 }
215
216 #endif
217