LLVM  14.0.0git
RuntimeDyldCOFFThumb.h
Go to the documentation of this file.
1 //===--- RuntimeDyldCOFFThumb.h --- COFF/Thumb specific code ---*- C++ --*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // COFF thumb support for MC-JIT runtime dynamic linker.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H
14 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H
15 
16 #include "../RuntimeDyldCOFF.h"
17 #include "llvm/BinaryFormat/COFF.h"
18 #include "llvm/Object/COFF.h"
19 
20 #define DEBUG_TYPE "dyld"
21 
22 namespace llvm {
23 
25  const object::ObjectFile &Obj,
27  Expected<object::SymbolRef::Type> SymTypeOrErr = Symbol->getType();
28  if (!SymTypeOrErr) {
29  std::string Buf;
30  raw_string_ostream OS(Buf);
31  logAllUnhandledErrors(SymTypeOrErr.takeError(), OS);
33  }
34 
35  if (*SymTypeOrErr != object::SymbolRef::ST_Function)
36  return false;
37 
38  // We check the IMAGE_SCN_MEM_16BIT flag in the section of the symbol to tell
39  // if it's thumb or not
40  return cast<object::COFFObjectFile>(Obj)
41  .getCOFFSection(*Section)
42  ->Characteristics &
44 }
45 
47 public:
51 
52  unsigned getMaxStubSize() const override {
53  return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding
54  }
55 
56  unsigned getStubAlignment() override { return 1; }
57 
59  processRelocationRef(unsigned SectionID,
61  const object::ObjectFile &Obj,
62  ObjSectionToIDMap &ObjSectionToID,
63  StubMap &Stubs) override {
64  auto Symbol = RelI->getSymbol();
65  if (Symbol == Obj.symbol_end())
66  report_fatal_error("Unknown symbol in relocation");
67 
68  Expected<StringRef> TargetNameOrErr = Symbol->getName();
69  if (!TargetNameOrErr)
70  return TargetNameOrErr.takeError();
71  StringRef TargetName = *TargetNameOrErr;
72 
73  auto SectionOrErr = Symbol->getSection();
74  if (!SectionOrErr)
75  return SectionOrErr.takeError();
76  auto Section = *SectionOrErr;
77 
78  uint64_t RelType = RelI->getType();
79  uint64_t Offset = RelI->getOffset();
80 
81  // Determine the Addend used to adjust the relocation value.
82  uint64_t Addend = 0;
83  SectionEntry &AddendSection = Sections[SectionID];
84  uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
85  uint8_t *Displacement = (uint8_t *)ObjTarget;
86 
87  switch (RelType) {
91  Addend = readBytesUnaligned(Displacement, 4);
92  break;
93  default:
94  break;
95  }
96 
97 #if !defined(NDEBUG)
98  SmallString<32> RelTypeName;
99  RelI->getTypeName(RelTypeName);
100 #endif
101  LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
102  << " RelType: " << RelTypeName << " TargetName: "
103  << TargetName << " Addend " << Addend << "\n");
104 
105  bool IsExtern = Section == Obj.section_end();
106  unsigned TargetSectionID = -1;
107  uint64_t TargetOffset = -1;
108 
109  if (TargetName.startswith(getImportSymbolPrefix())) {
110  TargetSectionID = SectionID;
111  TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName, true);
112  TargetName = StringRef();
113  IsExtern = false;
114  } else if (!IsExtern) {
115  if (auto TargetSectionIDOrErr =
116  findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
117  TargetSectionID = *TargetSectionIDOrErr;
118  else
119  return TargetSectionIDOrErr.takeError();
120  if (RelType != COFF::IMAGE_REL_ARM_SECTION)
121  TargetOffset = getSymbolOffset(*Symbol);
122  }
123 
124  if (IsExtern) {
125  RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
126  addRelocationForSymbol(RE, TargetName);
127  } else {
128 
129  // We need to find out if the relocation is relative to a thumb function
130  // so that we include the ISA selection bit when resolve the relocation
131  bool IsTargetThumbFunc = isThumbFunc(Symbol, Obj, Section);
132 
133  switch (RelType) {
134  default: llvm_unreachable("unsupported relocation type");
136  // This relocation is ignored.
137  break;
139  RelocationEntry RE =
140  RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
141  TargetOffset, 0, 0, false, 0, IsTargetThumbFunc);
142  addRelocationForSection(RE, TargetSectionID);
143  break;
144  }
146  RelocationEntry RE =
147  RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
148  TargetOffset, 0, 0, false, 0);
149  addRelocationForSection(RE, TargetSectionID);
150  break;
151  }
153  RelocationEntry RE =
154  RelocationEntry(TargetSectionID, Offset, RelType, 0);
155  addRelocationForSection(RE, TargetSectionID);
156  break;
157  }
159  RelocationEntry RE =
160  RelocationEntry(SectionID, Offset, RelType, TargetOffset + Addend);
161  addRelocationForSection(RE, TargetSectionID);
162  break;
163  }
165  RelocationEntry RE =
166  RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
167  TargetOffset, 0, 0, false, 0, IsTargetThumbFunc);
168  addRelocationForSection(RE, TargetSectionID);
169  break;
170  }
174  RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
175  TargetOffset + Addend, true, 0);
176  addRelocationForSection(RE, TargetSectionID);
177  break;
178  }
179  }
180  }
181 
182  return ++RelI;
183  }
184 
185  void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
186  const auto Section = Sections[RE.SectionID];
187  uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
188  int ISASelectionBit = RE.IsTargetThumbFunc ? 1 : 0;
189 
190  switch (RE.RelType) {
191  default: llvm_unreachable("unsupported relocation type");
193  // This relocation is ignored.
194  break;
196  // The target's 32-bit VA.
197  uint64_t Result =
198  RE.Sections.SectionA == static_cast<uint32_t>(-1)
199  ? Value
200  : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
201  Result |= ISASelectionBit;
202  assert(Result <= UINT32_MAX && "relocation overflow");
203  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
204  << " RelType: IMAGE_REL_ARM_ADDR32"
205  << " TargetSection: " << RE.Sections.SectionA
206  << " Value: " << format("0x%08" PRIx32, Result)
207  << '\n');
208  writeBytesUnaligned(Result, Target, 4);
209  break;
210  }
212  // The target's 32-bit RVA.
213  // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
214  uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() -
215  Sections[0].getLoadAddress() + RE.Addend;
216  assert(Result <= UINT32_MAX && "relocation overflow");
217  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
218  << " RelType: IMAGE_REL_ARM_ADDR32NB"
219  << " TargetSection: " << RE.Sections.SectionA
220  << " Value: " << format("0x%08" PRIx32, Result)
221  << '\n');
222  Result |= ISASelectionBit;
223  writeBytesUnaligned(Result, Target, 4);
224  break;
225  }
227  // 16-bit section index of the section that contains the target.
228  assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX &&
229  "relocation overflow");
230  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
231  << " RelType: IMAGE_REL_ARM_SECTION Value: "
232  << RE.SectionID << '\n');
234  break;
236  // 32-bit offset of the target from the beginning of its section.
237  assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX &&
238  "relocation overflow");
239  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
240  << " RelType: IMAGE_REL_ARM_SECREL Value: " << RE.Addend
241  << '\n');
243  break;
245  // 32-bit VA of the target applied to a contiguous MOVW+MOVT pair.
246  uint64_t Result =
247  Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
248  assert(Result <= UINT32_MAX && "relocation overflow");
249  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
250  << " RelType: IMAGE_REL_ARM_MOV32T"
251  << " TargetSection: " << RE.Sections.SectionA
252  << " Value: " << format("0x%08" PRIx32, Result)
253  << '\n');
254 
255  // MOVW(T3): |11110|i|10|0|1|0|0|imm4|0|imm3|Rd|imm8|
256  // imm32 = zext imm4:i:imm3:imm8
257  // MOVT(T1): |11110|i|10|1|1|0|0|imm4|0|imm3|Rd|imm8|
258  // imm16 = imm4:i:imm3:imm8
259 
260  auto EncodeImmediate = [](uint8_t *Bytes, uint16_t Immediate) {
261  Bytes[0] |= ((Immediate & 0xf000) >> 12);
262  Bytes[1] |= ((Immediate & 0x0800) >> 11);
263  Bytes[2] |= ((Immediate & 0x00ff) >> 0);
264  Bytes[3] |= (((Immediate & 0x0700) >> 8) << 4);
265  };
266 
267  EncodeImmediate(&Target[0],
268  (static_cast<uint32_t>(Result) >> 00) | ISASelectionBit);
269  EncodeImmediate(&Target[4], static_cast<uint32_t>(Result) >> 16);
270  break;
271  }
273  // The most significant 20-bits of the signed 21-bit relative displacement
274  uint64_t Value =
275  RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
276  assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
277  "relocation overflow");
278  assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
279  "relocation underflow");
280  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
281  << " RelType: IMAGE_REL_ARM_BRANCH20T"
282  << " Value: " << static_cast<int32_t>(Value) << '\n');
283  static_cast<void>(Value);
284  llvm_unreachable("unimplemented relocation");
285  break;
286  }
288  // The most significant 24-bits of the signed 25-bit relative displacement
289  uint64_t Value =
290  RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
291  assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
292  "relocation overflow");
293  assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
294  "relocation underflow");
295  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
296  << " RelType: IMAGE_REL_ARM_BRANCH24T"
297  << " Value: " << static_cast<int32_t>(Value) << '\n');
298  static_cast<void>(Value);
299  llvm_unreachable("unimplemented relocation");
300  break;
301  }
303  // The most significant 24-bits of the signed 25-bit relative displacement
304  uint64_t Value =
305  RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
306  assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
307  "relocation overflow");
308  assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
309  "relocation underflow");
310  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
311  << " RelType: IMAGE_REL_ARM_BLX23T"
312  << " Value: " << static_cast<int32_t>(Value) << '\n');
313  static_cast<void>(Value);
314  llvm_unreachable("unimplemented relocation");
315  break;
316  }
317  }
318  }
319 
320  void registerEHFrames() override {}
321 };
322 
323 }
324 
325 #endif
llvm::StringRef::startswith
LLVM_NODISCARD bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:286
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
llvm::RelocationEntry::SectionPair::SectionA
uint32_t SectionA
Definition: RuntimeDyldImpl.h:133
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:625
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:137
llvm::RuntimeDyldImpl::Sections
SectionList Sections
Definition: RuntimeDyldImpl.h:254
llvm::isThumbFunc
static bool isThumbFunc(object::symbol_iterator Symbol, const object::ObjectFile &Obj, object::section_iterator Section)
Definition: RuntimeDyldCOFFThumb.h:24
llvm::RuntimeDyldCOFFThumb
Definition: RuntimeDyldCOFFThumb.h:46
COFF.h
llvm::RuntimeDyldImpl::addRelocationForSection
void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID)
Definition: RuntimeDyld.cpp:948
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
llvm::COFF::IMAGE_REL_ARM_BRANCH20T
@ IMAGE_REL_ARM_BRANCH20T
Definition: COFF.h:379
llvm::RuntimeDyldImpl::addRelocationForSymbol
void addRelocationForSymbol(const RelocationEntry &RE, StringRef SymbolName)
Definition: RuntimeDyld.cpp:953
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::RelocationEntry::SectionID
unsigned SectionID
SectionID - the section this relocation points to.
Definition: RuntimeDyldImpl.h:120
llvm::RuntimeDyldCOFFThumb::getStubAlignment
unsigned getStubAlignment() override
Definition: RuntimeDyldCOFFThumb.h:56
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::ARMBuildAttrs::Section
@ Section
Legacy Tags.
Definition: ARMBuildAttributes.h:78
llvm::Resolver
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
Definition: Record.h:2000
llvm::object::SymbolicFile::symbol_end
virtual basic_symbol_iterator symbol_end() const =0
llvm::RelocationEntry::Offset
uint64_t Offset
Offset - offset into the section.
Definition: RuntimeDyldImpl.h:123
llvm::COFF::IMAGE_REL_ARM_SECREL
@ IMAGE_REL_ARM_SECREL
Definition: COFF.h:376
llvm::COFF::IMAGE_REL_ARM_MOV32T
@ IMAGE_REL_ARM_MOV32T
Definition: COFF.h:378
llvm::object::ObjectFile::section_end
virtual section_iterator section_end() const =0
llvm::COFF::IMAGE_REL_ARM_ADDR32NB
@ IMAGE_REL_ARM_ADDR32NB
Definition: COFF.h:368
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
llvm::RuntimeDyldImpl::writeBytesUnaligned
void writeBytesUnaligned(uint64_t Value, uint8_t *Dst, unsigned Size) const
Endian-aware write.
Definition: RuntimeDyld.cpp:721
llvm::SectionEntry::getObjAddress
uintptr_t getObjAddress() const
Definition: RuntimeDyldImpl.h:112
llvm::SmallString< 32 >
llvm::RelocationEntry::Addend
int64_t Addend
Addend - the relocation addend encoded in the instruction itself.
Definition: RuntimeDyldImpl.h:130
llvm::RelocationEntry
RelocationEntry - used to represent relocations internally in the dynamic linker.
Definition: RuntimeDyldImpl.h:117
uint64_t
llvm::object::symbol_iterator
Definition: ObjectFile.h:207
llvm::object::SymbolRef::ST_Function
@ ST_Function
Definition: ObjectFile.h:176
llvm::COFF::IMAGE_REL_ARM_BRANCH24T
@ IMAGE_REL_ARM_BRANCH24T
Definition: COFF.h:380
llvm::RuntimeDyldCOFFThumb::resolveRelocation
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override
A object file specific relocation resolver.
Definition: RuntimeDyldCOFFThumb.h:185
llvm::SectionEntry
SectionEntry - represents a section emitted into memory by the dynamic linker.
Definition: RuntimeDyldImpl.h:45
llvm::RuntimeDyldCOFFThumb::registerEHFrames
void registerEHFrames() override
Definition: RuntimeDyldCOFFThumb.h:320
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::object::content_iterator
Definition: SymbolicFile.h:67
llvm::COFF::IMAGE_REL_ARM_ABSOLUTE
@ IMAGE_REL_ARM_ABSOLUTE
Definition: COFF.h:366
llvm::RuntimeDyldCOFF::getDLLImportOffset
uint64_t getDLLImportOffset(unsigned SectionID, StubMap &Stubs, StringRef Name, bool SetSectionIDMinus1=false)
Definition: RuntimeDyldCOFF.cpp:82
llvm::RuntimeDyldCOFF::getImportSymbolPrefix
static constexpr StringRef getImportSymbolPrefix()
Definition: RuntimeDyldCOFF.h:50
llvm::RuntimeDyldCOFF::getSymbolOffset
uint64_t getSymbolOffset(const SymbolRef &Sym)
Definition: RuntimeDyldCOFF.cpp:77
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::object::ObjectFile
This class is the base class for all object file types.
Definition: ObjectFile.h:228
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
uint32_t
llvm::RelocationEntry::IsTargetThumbFunc
bool IsTargetThumbFunc
Definition: RuntimeDyldImpl.h:151
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::logAllUnhandledErrors
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition: Error.cpp:61
llvm::COFF::IMAGE_REL_ARM_SECTION
@ IMAGE_REL_ARM_SECTION
Definition: COFF.h:375
llvm::JITSymbolResolver
Symbol resolution interface.
Definition: JITSymbol.h:371
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::RuntimeDyldCOFFThumb::processRelocationRef
Expected< object::relocation_iterator > processRelocationRef(unsigned SectionID, object::relocation_iterator RelI, const object::ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) override
Parses one or more object file relocations (some object files use relocation pairs) and stores it to ...
Definition: RuntimeDyldCOFFThumb.h:59
llvm::RuntimeDyldCOFF
Definition: RuntimeDyldCOFF.h:26
llvm::RuntimeDyldImpl::findOrEmitSection
Expected< unsigned > findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode, ObjSectionToIDMap &LocalSections)
Find Section in LocalSections.
Definition: RuntimeDyld.cpp:929
uint16_t
llvm::RuntimeDyldCOFFThumb::RuntimeDyldCOFFThumb
RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver)
Definition: RuntimeDyldCOFFThumb.h:48
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::COFF::IMAGE_REL_ARM_BLX23T
@ IMAGE_REL_ARM_BLX23T
Definition: COFF.h:381
llvm::RuntimeDyldCOFFThumb::getMaxStubSize
unsigned getMaxStubSize() const override
Definition: RuntimeDyldCOFFThumb.h:52
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:79
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:589
COFF.h
llvm::RelocationEntry::Sections
SectionPair Sections
Definition: RuntimeDyldImpl.h:141
llvm::RuntimeDyldImpl::readBytesUnaligned
uint64_t readBytesUnaligned(uint8_t *Src, unsigned Size) const
Endian-aware read Read the least significant Size bytes from Src.
Definition: RuntimeDyld.cpp:707
llvm::RuntimeDyldImpl::StubMap
std::map< RelocationValueRef, uintptr_t > StubMap
Definition: RuntimeDyldImpl.h:286
llvm::COFF::IMAGE_SCN_MEM_16BIT
@ IMAGE_SCN_MEM_16BIT
Definition: COFF.h:297
llvm::COFF::IMAGE_REL_ARM_ADDR32
@ IMAGE_REL_ARM_ADDR32
Definition: COFF.h:367
llvm::raw_string_ostream::str
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
Definition: raw_ostream.h:643
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::RelocationEntry::RelType
uint32_t RelType
RelType - relocation type.
Definition: RuntimeDyldImpl.h:126
llvm::RuntimeDyldImpl::ObjSectionToIDMap
std::map< SectionRef, unsigned > ObjSectionToIDMap
Definition: RuntimeDyldImpl.h:261
llvm::RuntimeDyld::MemoryManager
Memory Management.
Definition: RuntimeDyld.h:92