]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / ExecutionEngine / RuntimeDyld / Targets / RuntimeDyldCOFFX86_64.h
1 //===-- RuntimeDyldCOFFX86_64.h --- COFF/X86_64 specific code ---*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // COFF x86_x64 support for MC-JIT runtime dynamic linker.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H
15 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFF86_64_H
16
17 #include "../RuntimeDyldCOFF.h"
18 #include "llvm/BinaryFormat/COFF.h"
19 #include "llvm/Object/COFF.h"
20
21 #define DEBUG_TYPE "dyld"
22
23 namespace llvm {
24
25 class RuntimeDyldCOFFX86_64 : public RuntimeDyldCOFF {
26
27 private:
28   // When a module is loaded we save the SectionID of the unwind
29   // sections in a table until we receive a request to register all
30   // unregisteredEH frame sections with the memory manager.
31   SmallVector<SID, 2> UnregisteredEHFrameSections;
32   SmallVector<SID, 2> RegisteredEHFrameSections;
33   uint64_t ImageBase;
34
35   // Fake an __ImageBase pointer by returning the section with the lowest adress
36   uint64_t getImageBase() {
37     if (!ImageBase) {
38       ImageBase = std::numeric_limits<uint64_t>::max();
39       for (const SectionEntry &Section : Sections)
40         ImageBase = std::min(ImageBase, Section.getLoadAddress());
41     }
42     return ImageBase;
43   }
44
45   void write32BitOffset(uint8_t *Target, int64_t Addend, uint64_t Delta) {
46     uint64_t Result = Addend + Delta;
47     assert(Result <= UINT32_MAX && "Relocation overflow");
48     writeBytesUnaligned(Result, Target, 4);
49   }
50
51 public:
52   RuntimeDyldCOFFX86_64(RuntimeDyld::MemoryManager &MM,
53                         JITSymbolResolver &Resolver)
54     : RuntimeDyldCOFF(MM, Resolver), ImageBase(0) {}
55
56   unsigned getStubAlignment() override { return 1; }
57
58   // 2-byte jmp instruction + 32-bit relative address + 64-bit absolute jump
59   unsigned getMaxStubSize() override { return 14; }
60
61   // The target location for the relocation is described by RE.SectionID and
62   // RE.Offset.  RE.SectionID can be used to find the SectionEntry.  Each
63   // SectionEntry has three members describing its location.
64   // SectionEntry::Address is the address at which the section has been loaded
65   // into memory in the current (host) process.  SectionEntry::LoadAddress is
66   // the address that the section will have in the target process.
67   // SectionEntry::ObjAddress is the address of the bits for this section in the
68   // original emitted object image (also in the current address space).
69   //
70   // Relocations will be applied as if the section were loaded at
71   // SectionEntry::LoadAddress, but they will be applied at an address based
72   // on SectionEntry::Address.  SectionEntry::ObjAddress will be used to refer
73   // to Target memory contents if they are required for value calculations.
74   //
75   // The Value parameter here is the load address of the symbol for the
76   // relocation to be applied.  For relocations which refer to symbols in the
77   // current object Value will be the LoadAddress of the section in which
78   // the symbol resides (RE.Addend provides additional information about the
79   // symbol location).  For external symbols, Value will be the address of the
80   // symbol in the target address space.
81   void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
82     const SectionEntry &Section = Sections[RE.SectionID];
83     uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
84
85     switch (RE.RelType) {
86
87     case COFF::IMAGE_REL_AMD64_REL32:
88     case COFF::IMAGE_REL_AMD64_REL32_1:
89     case COFF::IMAGE_REL_AMD64_REL32_2:
90     case COFF::IMAGE_REL_AMD64_REL32_3:
91     case COFF::IMAGE_REL_AMD64_REL32_4:
92     case COFF::IMAGE_REL_AMD64_REL32_5: {
93       uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
94       // Delta is the distance from the start of the reloc to the end of the
95       // instruction with the reloc.
96       uint64_t Delta = 4 + (RE.RelType - COFF::IMAGE_REL_AMD64_REL32);
97       Value -= FinalAddress + Delta;
98       uint64_t Result = Value + RE.Addend;
99       assert(((int64_t)Result <= INT32_MAX) && "Relocation overflow");
100       assert(((int64_t)Result >= INT32_MIN) && "Relocation underflow");
101       writeBytesUnaligned(Result, Target, 4);
102       break;
103     }
104
105     case COFF::IMAGE_REL_AMD64_ADDR32NB: {
106       // ADDR32NB requires an offset less than 2GB from 'ImageBase'.
107       // The MemoryManager can make sure this is always true by forcing the
108       // memory layout to be: CodeSection < ReadOnlySection < ReadWriteSection.
109       const uint64_t ImageBase = getImageBase();
110       if (Value < ImageBase || ((Value - ImageBase) > UINT32_MAX)) {
111         llvm::errs() << "IMAGE_REL_AMD64_ADDR32NB relocation requires an"
112                      << "ordered section layout.\n";
113         write32BitOffset(Target, 0, 0);
114       } else {
115         write32BitOffset(Target, RE.Addend, Value - ImageBase);
116       }
117       break;
118     }
119
120     case COFF::IMAGE_REL_AMD64_ADDR64: {
121       writeBytesUnaligned(Value + RE.Addend, Target, 8);
122       break;
123     }
124
125     default:
126       llvm_unreachable("Relocation type not implemented yet!");
127       break;
128     }
129   }
130
131   std::tuple<uint64_t, uint64_t, uint64_t>
132   generateRelocationStub(unsigned SectionID, StringRef TargetName,
133                          uint64_t Offset, uint64_t RelType, uint64_t Addend,
134                          StubMap &Stubs) {
135     uintptr_t StubOffset;
136     SectionEntry &Section = Sections[SectionID];
137
138     RelocationValueRef OriginalRelValueRef;
139     OriginalRelValueRef.SectionID = SectionID;
140     OriginalRelValueRef.Offset = Offset;
141     OriginalRelValueRef.Addend = Addend;
142     OriginalRelValueRef.SymbolName = TargetName.data();
143
144     auto Stub = Stubs.find(OriginalRelValueRef);
145     if (Stub == Stubs.end()) {
146       LLVM_DEBUG(dbgs() << " Create a new stub function for "
147                         << TargetName.data() << "\n");
148
149       StubOffset = Section.getStubOffset();
150       Stubs[OriginalRelValueRef] = StubOffset;
151       createStubFunction(Section.getAddressWithOffset(StubOffset));
152       Section.advanceStubOffset(getMaxStubSize());
153     } else {
154       LLVM_DEBUG(dbgs() << " Stub function found for " << TargetName.data()
155                         << "\n");
156       StubOffset = Stub->second;
157     }
158
159     // FIXME: If RelType == COFF::IMAGE_REL_AMD64_ADDR32NB we should be able
160     // to ignore the __ImageBase requirement and just forward to the stub
161     // directly as an offset of this section:
162     // write32BitOffset(Section.getAddressWithOffset(Offset), 0, StubOffset);
163     // .xdata exception handler's aren't having this though.
164
165     // Resolve original relocation to stub function.
166     const RelocationEntry RE(SectionID, Offset, RelType, Addend);
167     resolveRelocation(RE, Section.getLoadAddressWithOffset(StubOffset));
168
169     // adjust relocation info so resolution writes to the stub function
170     Addend = 0;
171     Offset = StubOffset + 6;
172     RelType = COFF::IMAGE_REL_AMD64_ADDR64;
173
174     return std::make_tuple(Offset, RelType, Addend);
175   }
176
177   Expected<relocation_iterator>
178   processRelocationRef(unsigned SectionID,
179                        relocation_iterator RelI,
180                        const ObjectFile &Obj,
181                        ObjSectionToIDMap &ObjSectionToID,
182                        StubMap &Stubs) override {
183     // If possible, find the symbol referred to in the relocation,
184     // and the section that contains it.
185     symbol_iterator Symbol = RelI->getSymbol();
186     if (Symbol == Obj.symbol_end())
187       report_fatal_error("Unknown symbol in relocation");
188     auto SectionOrError = Symbol->getSection();
189     if (!SectionOrError)
190       return SectionOrError.takeError();
191     section_iterator SecI = *SectionOrError;
192     // If there is no section, this must be an external reference.
193     const bool IsExtern = SecI == Obj.section_end();
194
195     // Determine the Addend used to adjust the relocation value.
196     uint64_t RelType = RelI->getType();
197     uint64_t Offset = RelI->getOffset();
198     uint64_t Addend = 0;
199     SectionEntry &Section = Sections[SectionID];
200     uintptr_t ObjTarget = Section.getObjAddress() + Offset;
201
202     Expected<StringRef> TargetNameOrErr = Symbol->getName();
203     if (!TargetNameOrErr)
204       return TargetNameOrErr.takeError();
205     StringRef TargetName = *TargetNameOrErr;
206
207     switch (RelType) {
208
209     case COFF::IMAGE_REL_AMD64_REL32:
210     case COFF::IMAGE_REL_AMD64_REL32_1:
211     case COFF::IMAGE_REL_AMD64_REL32_2:
212     case COFF::IMAGE_REL_AMD64_REL32_3:
213     case COFF::IMAGE_REL_AMD64_REL32_4:
214     case COFF::IMAGE_REL_AMD64_REL32_5:
215     case COFF::IMAGE_REL_AMD64_ADDR32NB: {
216       uint8_t *Displacement = (uint8_t *)ObjTarget;
217       Addend = readBytesUnaligned(Displacement, 4);
218
219       if (IsExtern)
220         std::tie(Offset, RelType, Addend) = generateRelocationStub(
221           SectionID, TargetName, Offset, RelType, Addend, Stubs);
222
223       break;
224     }
225
226     case COFF::IMAGE_REL_AMD64_ADDR64: {
227       uint8_t *Displacement = (uint8_t *)ObjTarget;
228       Addend = readBytesUnaligned(Displacement, 8);
229       break;
230     }
231
232     default:
233       break;
234     }
235
236     LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
237                       << " RelType: " << RelType << " TargetName: "
238                       << TargetName << " Addend " << Addend << "\n");
239
240     if (IsExtern) {
241       RelocationEntry RE(SectionID, Offset, RelType, Addend);
242       addRelocationForSymbol(RE, TargetName);
243     } else {
244       bool IsCode = SecI->isText();
245       unsigned TargetSectionID;
246       if (auto TargetSectionIDOrErr =
247           findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID))
248         TargetSectionID = *TargetSectionIDOrErr;
249       else
250         return TargetSectionIDOrErr.takeError();
251       uint64_t TargetOffset = getSymbolOffset(*Symbol);
252       RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend);
253       addRelocationForSection(RE, TargetSectionID);
254     }
255
256     return ++RelI;
257   }
258
259   void registerEHFrames() override {
260     for (auto const &EHFrameSID : UnregisteredEHFrameSections) {
261       uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress();
262       uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress();
263       size_t EHFrameSize = Sections[EHFrameSID].getSize();
264       MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
265       RegisteredEHFrameSections.push_back(EHFrameSID);
266     }
267     UnregisteredEHFrameSections.clear();
268   }
269
270   Error finalizeLoad(const ObjectFile &Obj,
271                      ObjSectionToIDMap &SectionMap) override {
272     // Look for and record the EH frame section IDs.
273     for (const auto &SectionPair : SectionMap) {
274       const SectionRef &Section = SectionPair.first;
275       StringRef Name;
276       if (auto EC = Section.getName(Name))
277         return errorCodeToError(EC);
278
279       // Note unwind info is stored in .pdata but often points to .xdata
280       // with an IMAGE_REL_AMD64_ADDR32NB relocation. Using a memory manager
281       // that keeps sections ordered in relation to __ImageBase is necessary.
282       if (Name == ".pdata")
283         UnregisteredEHFrameSections.push_back(SectionPair.second);
284     }
285     return Error::success();
286   }
287 };
288
289 } // end namespace llvm
290
291 #undef DEBUG_TYPE
292
293 #endif