LLVM  8.0.1
RuntimeDyldCOFFI386.h
Go to the documentation of this file.
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 "../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 
26 public:
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 
38  processRelocationRef(unsigned SectionID,
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) {
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  LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
84  << " RelType: " << RelTypeName << " TargetName: "
85  << TargetName << " 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) {
100  // This relocation is ignored.
101  break;
105  RelocationEntry RE =
106  RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
107  getSymbolOffset(*Symbol), 0, 0, false, 0);
108  addRelocationForSection(RE, TargetSectionID);
109  break;
110  }
112  RelocationEntry RE =
113  RelocationEntry(TargetSectionID, Offset, RelType, 0);
114  addRelocationForSection(RE, TargetSectionID);
115  break;
116  }
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) {
138  // This relocation is ignored.
139  break;
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(Result <= UINT32_MAX && "relocation overflow");
148  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
149  << " RelType: IMAGE_REL_I386_DIR32"
150  << " TargetSection: " << RE.Sections.SectionA
151  << " Value: " << format("0x%08" PRIx32, Result)
152  << '\n');
153  writeBytesUnaligned(Result, Target, 4);
154  break;
155  }
157  // The target's 32-bit RVA.
158  // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
159  uint64_t Result =
160  Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend) -
161  Sections[0].getLoadAddress();
162  assert(Result <= UINT32_MAX && "relocation overflow");
163  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
164  << " RelType: IMAGE_REL_I386_DIR32NB"
165  << " TargetSection: " << RE.Sections.SectionA
166  << " Value: " << format("0x%08" PRIx32, Result)
167  << '\n');
168  writeBytesUnaligned(Result, Target, 4);
169  break;
170  }
172  // 32-bit relative displacement to the target.
173  uint64_t Result = RE.Sections.SectionA == static_cast<uint32_t>(-1)
174  ? Value
175  : Sections[RE.Sections.SectionA].getLoadAddress();
176  Result = Result - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset;
177  assert(static_cast<int64_t>(Result) <= INT32_MAX &&
178  "relocation overflow");
179  assert(static_cast<int64_t>(Result) >= INT32_MIN &&
180  "relocation underflow");
181  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
182  << " RelType: IMAGE_REL_I386_REL32"
183  << " TargetSection: " << RE.Sections.SectionA
184  << " Value: " << format("0x%08" PRIx32, Result)
185  << '\n');
186  writeBytesUnaligned(Result, Target, 4);
187  break;
188  }
190  // 16-bit section index of the section that contains the target.
191  assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX &&
192  "relocation overflow");
193  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
194  << " RelType: IMAGE_REL_I386_SECTION Value: "
195  << RE.SectionID << '\n');
196  writeBytesUnaligned(RE.SectionID, Target, 2);
197  break;
199  // 32-bit offset of the target from the beginning of its section.
200  assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX &&
201  "relocation overflow");
202  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
203  << " RelType: IMAGE_REL_I386_SECREL Value: "
204  << RE.Addend << '\n');
205  writeBytesUnaligned(RE.Addend, Target, 4);
206  break;
207  default:
208  llvm_unreachable("unsupported relocation type");
209  }
210  }
211 
212  void registerEHFrames() override {}
213 };
214 
215 }
216 
217 #endif
218 
RelocationEntry - used to represent relocations internally in the dynamic linker. ...
Expected< relocation_iterator > processRelocationRef(unsigned SectionID, relocation_iterator RelI, const ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) override
Parses one or more object file relocations (some object files use relocation pairs) and stores it to ...
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
This class represents lattice values for constants.
Definition: AllocatorList.h:24
uint64_t readBytesUnaligned(uint8_t *Src, unsigned Size) const
Endian-aware read Read the least significant Size bytes from Src.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
This class is the base class for all object file types.
Definition: ObjectFile.h:202
uint64_t getSymbolOffset(const SymbolRef &Sym)
Error takeError()
Take ownership of the stored error.
Definition: Error.h:553
unsigned getStubAlignment() override
void writeBytesUnaligned(uint64_t Value, uint8_t *Dst, unsigned Size) const
Endian-aware write.
unsigned SectionID
SectionID - the section this relocation points to.
std::map< RelocationValueRef, uintptr_t > StubMap
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override
A object file specific relocation resolver.
void addRelocationForSymbol(const RelocationEntry &RE, StringRef SymbolName)
RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver)
void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID)
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
Definition: Record.h:1774
unsigned getMaxStubSize() override
Symbol resolution interface.
Definition: JITSymbol.h:344
virtual basic_symbol_iterator symbol_end() const =0
uintptr_t getObjAddress() const
Expected< unsigned > findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode, ObjSectionToIDMap &LocalSections)
Find Section in LocalSections.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
int64_t Addend
Addend - the relocation addend encoded in the instruction itself.
uint32_t RelType
RelType - relocation type.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
Target - Wrapper for Target specific information.
uint64_t Offset
Offset - offset into the section.
virtual section_iterator section_end() const =0
std::map< SectionRef, unsigned > ObjSectionToIDMap
SectionEntry - represents a section emitted into memory by the dynamic linker.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:73
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
#define LLVM_DEBUG(X)
Definition: Debug.h:123