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