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