LLVM  4.0.0
RuntimeDyldCOFFThumb.h
Go to the documentation of this file.
1 //===--- RuntimeDyldCOFFThumb.h --- COFF/Thumb 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 thumb support for MC-JIT runtime dynamic linker.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H
15 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_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 
23 namespace llvm {
24 
25 static bool isThumbFunc(symbol_iterator Symbol, const ObjectFile &Obj,
27  Expected<SymbolRef::Type> SymTypeOrErr = Symbol->getType();
28  if (!SymTypeOrErr) {
29  std::string Buf;
30  raw_string_ostream OS(Buf);
31  logAllUnhandledErrors(SymTypeOrErr.takeError(), OS, "");
32  OS.flush();
33  report_fatal_error(Buf);
34  }
35 
36  if (*SymTypeOrErr != SymbolRef::ST_Function)
37  return false;
38 
39  // We check the IMAGE_SCN_MEM_16BIT flag in the section of the symbol to tell
40  // if it's thumb or not
41  return cast<COFFObjectFile>(Obj).getCOFFSection(*Section)->Characteristics &
43 }
44 
46 public:
49  : RuntimeDyldCOFF(MM, Resolver) {}
50 
51  unsigned getMaxStubSize() override {
52  return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding
53  }
54 
55  unsigned getStubAlignment() override { return 1; }
56 
58  processRelocationRef(unsigned SectionID,
60  const ObjectFile &Obj,
61  ObjSectionToIDMap &ObjSectionToID,
62  StubMap &Stubs) override {
63  auto Symbol = RelI->getSymbol();
64  if (Symbol == Obj.symbol_end())
65  report_fatal_error("Unknown symbol in relocation");
66 
67  Expected<StringRef> TargetNameOrErr = Symbol->getName();
68  if (!TargetNameOrErr)
69  return TargetNameOrErr.takeError();
70  StringRef TargetName = *TargetNameOrErr;
71 
72  auto SectionOrErr = Symbol->getSection();
73  if (!SectionOrErr)
74  return SectionOrErr.takeError();
75  auto Section = *SectionOrErr;
76 
77  uint64_t RelType = RelI->getType();
78  uint64_t Offset = RelI->getOffset();
79 
80  // Determine the Addend used to adjust the relocation value.
81  uint64_t Addend = 0;
82  SectionEntry &AddendSection = Sections[SectionID];
83  uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
84  uint8_t *Displacement = (uint8_t *)ObjTarget;
85 
86  switch (RelType) {
90  Addend = readBytesUnaligned(Displacement, 4);
91  break;
92  default:
93  break;
94  }
95 
96 #if !defined(NDEBUG)
97  SmallString<32> RelTypeName;
98  RelI->getTypeName(RelTypeName);
99 #endif
100  DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
101  << " RelType: " << RelTypeName << " TargetName: " << TargetName
102  << " Addend " << Addend << "\n");
103 
104  unsigned TargetSectionID = -1;
105  if (Section == Obj.section_end()) {
106  RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
107  addRelocationForSymbol(RE, TargetName);
108  } else {
109  if (auto TargetSectionIDOrErr =
110  findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
111  TargetSectionID = *TargetSectionIDOrErr;
112  else
113  return TargetSectionIDOrErr.takeError();
114 
115  // We need to find out if the relocation is relative to a thumb function
116  // so that we include the ISA selection bit when resolve the relocation
117  bool IsTargetThumbFunc = isThumbFunc(Symbol, Obj, Section);
118 
119  switch (RelType) {
120  default: llvm_unreachable("unsupported relocation type");
122  // This relocation is ignored.
123  break;
126  SectionID, Offset, RelType, Addend, TargetSectionID,
127  getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc);
128  addRelocationForSection(RE, TargetSectionID);
129  break;
130  }
132  RelocationEntry RE =
133  RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
134  getSymbolOffset(*Symbol), 0, 0, false, 0);
135  addRelocationForSection(RE, TargetSectionID);
136  break;
137  }
139  RelocationEntry RE =
140  RelocationEntry(TargetSectionID, Offset, RelType, 0);
141  addRelocationForSection(RE, TargetSectionID);
142  break;
143  }
145  RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
146  getSymbolOffset(*Symbol) + Addend);
147  addRelocationForSection(RE, TargetSectionID);
148  break;
149  }
152  SectionID, Offset, RelType, Addend, TargetSectionID,
153  getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc);
154  addRelocationForSection(RE, TargetSectionID);
155  break;
156  }
160  RelocationEntry RE =
161  RelocationEntry(SectionID, Offset, RelType,
162  getSymbolOffset(*Symbol) + Addend, true, 0);
163  addRelocationForSection(RE, TargetSectionID);
164  break;
165  }
166  }
167  }
168 
169  return ++RelI;
170  }
171 
172  void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
173  const auto Section = Sections[RE.SectionID];
174  uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
175  int ISASelectionBit = RE.IsTargetThumbFunc ? 1 : 0;
176 
177  switch (RE.RelType) {
178  default: llvm_unreachable("unsupported relocation type");
180  // This relocation is ignored.
181  break;
183  // The target's 32-bit VA.
184  uint64_t Result =
185  RE.Sections.SectionA == static_cast<uint32_t>(-1)
186  ? Value
187  : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
188  Result |= ISASelectionBit;
189  assert(static_cast<int32_t>(Result) <= INT32_MAX &&
190  "relocation overflow");
191  assert(static_cast<int32_t>(Result) >= INT32_MIN &&
192  "relocation underflow");
193  DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
194  << " RelType: IMAGE_REL_ARM_ADDR32"
195  << " TargetSection: " << RE.Sections.SectionA
196  << " Value: " << format("0x%08" PRIx32, Result) << '\n');
197  writeBytesUnaligned(Result, Target, 4);
198  break;
199  }
201  // The target's 32-bit RVA.
202  // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
203  uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() -
204  Sections[0].getLoadAddress() + RE.Addend;
205  assert(static_cast<int32_t>(Result) <= INT32_MAX &&
206  "relocation overflow");
207  assert(static_cast<int32_t>(Result) >= INT32_MIN &&
208  "relocation underflow");
209  DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
210  << " RelType: IMAGE_REL_ARM_ADDR32NB"
211  << " TargetSection: " << RE.Sections.SectionA
212  << " Value: " << format("0x%08" PRIx32, Result) << '\n');
213  Result |= ISASelectionBit;
214  writeBytesUnaligned(Result, Target, 4);
215  break;
216  }
218  // 16-bit section index of the section that contains the target.
219  assert(static_cast<int32_t>(RE.SectionID) <= INT16_MAX &&
220  "relocation overflow");
221  assert(static_cast<int32_t>(RE.SectionID) >= INT16_MIN &&
222  "relocation underflow");
223  DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
224  << " RelType: IMAGE_REL_ARM_SECTION Value: " << RE.SectionID
225  << '\n');
226  writeBytesUnaligned(RE.SectionID, Target, 2);
227  break;
229  // 32-bit offset of the target from the beginning of its section.
230  assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX &&
231  "relocation overflow");
232  assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN &&
233  "relocation underflow");
234  DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
235  << " RelType: IMAGE_REL_ARM_SECREL Value: " << RE.Addend
236  << '\n');
237  writeBytesUnaligned(RE.Addend, Target, 2);
238  break;
240  // 32-bit VA of the target applied to a contiguous MOVW+MOVT pair.
241  uint64_t Result =
242  Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
243  assert(static_cast<int32_t>(Result) <= INT32_MAX &&
244  "relocation overflow");
245  assert(static_cast<int32_t>(Result) >= INT32_MIN &&
246  "relocation underflow");
247  DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
248  << " RelType: IMAGE_REL_ARM_MOV32T"
249  << " TargetSection: " << RE.Sections.SectionA
250  << " Value: " << format("0x%08" PRIx32, Result) << '\n');
251 
252  // MOVW(T3): |11110|i|10|0|1|0|0|imm4|0|imm3|Rd|imm8|
253  // imm32 = zext imm4:i:imm3:imm8
254  // MOVT(T1): |11110|i|10|1|1|0|0|imm4|0|imm3|Rd|imm8|
255  // imm16 = imm4:i:imm3:imm8
256 
257  auto EncodeImmediate = [](uint8_t *Bytes, uint16_t Immediate) {
258  Bytes[0] |= ((Immediate & 0xf000) >> 12);
259  Bytes[1] |= ((Immediate & 0x0800) >> 11);
260  Bytes[2] |= ((Immediate & 0x00ff) >> 0);
261  Bytes[3] |= (((Immediate & 0x0700) >> 8) << 4);
262  };
263 
264  EncodeImmediate(&Target[0],
265  (static_cast<uint32_t>(Result) >> 00) | ISASelectionBit);
266  EncodeImmediate(&Target[4], static_cast<uint32_t>(Result) >> 16);
267 
268  break;
269  }
271  // The most significant 20-bits of the signed 21-bit relative displacement
272  uint64_t Value =
273  RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
274  assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX &&
275  "relocation overflow");
276  assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN &&
277  "relocation underflow");
278  DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
279  << " RelType: IMAGE_REL_ARM_BRANCH20T"
280  << " Value: " << static_cast<int32_t>(Value) << '\n');
281  static_cast<void>(Value);
282  llvm_unreachable("unimplemented relocation");
283  break;
284  }
286  // The most significant 24-bits of the signed 25-bit relative displacement
287  uint64_t Value =
288  RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
289  assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX &&
290  "relocation overflow");
291  assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN &&
292  "relocation underflow");
293  DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
294  << " RelType: IMAGE_REL_ARM_BRANCH24T"
295  << " Value: " << static_cast<int32_t>(Value) << '\n');
296  static_cast<void>(Value);
297  llvm_unreachable("unimplemented relocation");
298  break;
299  }
301  // The most significant 24-bits of the signed 25-bit relative displacement
302  uint64_t Value =
303  RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
304  assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX &&
305  "relocation overflow");
306  assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN &&
307  "relocation underflow");
308  DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
309  << " RelType: IMAGE_REL_ARM_BLX23T"
310  << " Value: " << static_cast<int32_t>(Value) << '\n');
311  static_cast<void>(Value);
312  llvm_unreachable("unimplemented relocation");
313  break;
314  }
315  }
316  }
317 
318  void registerEHFrames() override {}
319  void deregisterEHFrames() override {}
320 };
321 
322 }
323 
324 #endif
325 
RelocationEntry - used to represent relocations internally in the dynamic linker. ...
void writeBytesUnaligned(uint64_t Value, uint8_t *Dst, unsigned Size) const
Endian-aware write.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner)
Log all errors (if any) in E to OS.
uintptr_t getObjAddress() const
This class is the base class for all object file types.
Definition: ObjectFile.h:178
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 ...
uint64_t getSymbolOffset(const SymbolRef &Sym)
Error takeError()
Take ownership of the stored error.
unsigned SectionID
SectionID - the section this relocation points to.
std::map< RelocationValueRef, uintptr_t > StubMap
Tagged union holding either a T or a Error.
Expected< SymbolRef::Type > getType() const
Definition: ObjectFile.h:340
RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver)
format_object< Ts...> format(const char *Fmt, const Ts &...Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
void addRelocationForSymbol(const RelocationEntry &RE, StringRef SymbolName)
void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID)
uint64_t readBytesUnaligned(uint8_t *Src, unsigned Size) const
Endian-aware read Read the least significant Size bytes from Src.
uint32_t Offset
Symbol resolution.
Definition: JITSymbol.h:165
virtual basic_symbol_iterator symbol_end() const =0
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.
unsigned getMaxStubSize() override
static bool isThumbFunc(symbol_iterator Symbol, const ObjectFile &Obj, section_iterator Section)
int64_t Addend
Addend - the relocation addend encoded in the instruction itself.
uint32_t RelType
RelType - relocation type.
JITSymbolResolver & Resolver
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
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
unsigned getStubAlignment() override
SectionEntry - represents a section emitted into memory by the dynamic linker.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:463
LLVM Value Representation.
Definition: Value.h:71
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override
A object file specific relocation resolver.
#define DEBUG(X)
Definition: Debug.h:100
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47