LLVM  13.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);
32  OS.flush();
33  report_fatal_error(Buf);
34  }
35 
36  if (*SymTypeOrErr != object::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<object::COFFObjectFile>(Obj)
42  .getCOFFSection(*Section)
43  ->Characteristics &
45 }
46 
48 public:
52 
53  unsigned getMaxStubSize() const override {
54  return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding
55  }
56 
57  unsigned getStubAlignment() override { return 1; }
58 
60  processRelocationRef(unsigned SectionID,
62  const object::ObjectFile &Obj,
63  ObjSectionToIDMap &ObjSectionToID,
64  StubMap &Stubs) override {
65  auto Symbol = RelI->getSymbol();
66  if (Symbol == Obj.symbol_end())
67  report_fatal_error("Unknown symbol in relocation");
68 
69  Expected<StringRef> TargetNameOrErr = Symbol->getName();
70  if (!TargetNameOrErr)
71  return TargetNameOrErr.takeError();
72  StringRef TargetName = *TargetNameOrErr;
73 
74  auto SectionOrErr = Symbol->getSection();
75  if (!SectionOrErr)
76  return SectionOrErr.takeError();
77  auto Section = *SectionOrErr;
78 
79  uint64_t RelType = RelI->getType();
80  uint64_t Offset = RelI->getOffset();
81 
82  // Determine the Addend used to adjust the relocation value.
83  uint64_t Addend = 0;
84  SectionEntry &AddendSection = Sections[SectionID];
85  uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
86  uint8_t *Displacement = (uint8_t *)ObjTarget;
87 
88  switch (RelType) {
92  Addend = readBytesUnaligned(Displacement, 4);
93  break;
94  default:
95  break;
96  }
97 
98 #if !defined(NDEBUG)
99  SmallString<32> RelTypeName;
100  RelI->getTypeName(RelTypeName);
101 #endif
102  LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
103  << " RelType: " << RelTypeName << " TargetName: "
104  << TargetName << " Addend " << Addend << "\n");
105 
106  bool IsExtern = Section == Obj.section_end();
107  unsigned TargetSectionID = -1;
108  uint64_t TargetOffset = -1;
109 
110  if (TargetName.startswith(getImportSymbolPrefix())) {
111  TargetSectionID = SectionID;
112  TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName, true);
113  TargetName = StringRef();
114  IsExtern = false;
115  } else if (!IsExtern) {
116  if (auto TargetSectionIDOrErr =
117  findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
118  TargetSectionID = *TargetSectionIDOrErr;
119  else
120  return TargetSectionIDOrErr.takeError();
121  if (RelType != COFF::IMAGE_REL_ARM_SECTION)
122  TargetOffset = getSymbolOffset(*Symbol);
123  }
124 
125  if (IsExtern) {
126  RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
127  addRelocationForSymbol(RE, TargetName);
128  } else {
129 
130  // We need to find out if the relocation is relative to a thumb function
131  // so that we include the ISA selection bit when resolve the relocation
132  bool IsTargetThumbFunc = isThumbFunc(Symbol, Obj, Section);
133 
134  switch (RelType) {
135  default: llvm_unreachable("unsupported relocation type");
137  // This relocation is ignored.
138  break;
140  RelocationEntry RE =
141  RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
142  TargetOffset, 0, 0, false, 0, IsTargetThumbFunc);
143  addRelocationForSection(RE, TargetSectionID);
144  break;
145  }
147  RelocationEntry RE =
148  RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
149  TargetOffset, 0, 0, false, 0);
150  addRelocationForSection(RE, TargetSectionID);
151  break;
152  }
154  RelocationEntry RE =
155  RelocationEntry(TargetSectionID, Offset, RelType, 0);
156  addRelocationForSection(RE, TargetSectionID);
157  break;
158  }
160  RelocationEntry RE =
161  RelocationEntry(SectionID, Offset, RelType, TargetOffset + Addend);
162  addRelocationForSection(RE, TargetSectionID);
163  break;
164  }
166  RelocationEntry RE =
167  RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
168  TargetOffset, 0, 0, false, 0, IsTargetThumbFunc);
169  addRelocationForSection(RE, TargetSectionID);
170  break;
171  }
175  RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
176  TargetOffset + Addend, true, 0);
177  addRelocationForSection(RE, TargetSectionID);
178  break;
179  }
180  }
181  }
182 
183  return ++RelI;
184  }
185 
186  void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
187  const auto Section = Sections[RE.SectionID];
188  uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
189  int ISASelectionBit = RE.IsTargetThumbFunc ? 1 : 0;
190 
191  switch (RE.RelType) {
192  default: llvm_unreachable("unsupported relocation type");
194  // This relocation is ignored.
195  break;
197  // The target's 32-bit VA.
198  uint64_t Result =
199  RE.Sections.SectionA == static_cast<uint32_t>(-1)
200  ? Value
201  : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
202  Result |= ISASelectionBit;
203  assert(Result <= UINT32_MAX && "relocation overflow");
204  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
205  << " RelType: IMAGE_REL_ARM_ADDR32"
206  << " TargetSection: " << RE.Sections.SectionA
207  << " Value: " << format("0x%08" PRIx32, Result)
208  << '\n');
209  writeBytesUnaligned(Result, Target, 4);
210  break;
211  }
213  // The target's 32-bit RVA.
214  // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
215  uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() -
216  Sections[0].getLoadAddress() + RE.Addend;
217  assert(Result <= UINT32_MAX && "relocation overflow");
218  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
219  << " RelType: IMAGE_REL_ARM_ADDR32NB"
220  << " TargetSection: " << RE.Sections.SectionA
221  << " Value: " << format("0x%08" PRIx32, Result)
222  << '\n');
223  Result |= ISASelectionBit;
224  writeBytesUnaligned(Result, Target, 4);
225  break;
226  }
228  // 16-bit section index of the section that contains the target.
229  assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX &&
230  "relocation overflow");
231  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
232  << " RelType: IMAGE_REL_ARM_SECTION Value: "
233  << RE.SectionID << '\n');
235  break;
237  // 32-bit offset of the target from the beginning of its section.
238  assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX &&
239  "relocation overflow");
240  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
241  << " RelType: IMAGE_REL_ARM_SECREL Value: " << RE.Addend
242  << '\n');
244  break;
246  // 32-bit VA of the target applied to a contiguous MOVW+MOVT pair.
247  uint64_t Result =
248  Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
249  assert(Result <= UINT32_MAX && "relocation overflow");
250  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
251  << " RelType: IMAGE_REL_ARM_MOV32T"
252  << " TargetSection: " << RE.Sections.SectionA
253  << " Value: " << format("0x%08" PRIx32, Result)
254  << '\n');
255 
256  // MOVW(T3): |11110|i|10|0|1|0|0|imm4|0|imm3|Rd|imm8|
257  // imm32 = zext imm4:i:imm3:imm8
258  // MOVT(T1): |11110|i|10|1|1|0|0|imm4|0|imm3|Rd|imm8|
259  // imm16 = imm4:i:imm3:imm8
260 
261  auto EncodeImmediate = [](uint8_t *Bytes, uint16_t Immediate) {
262  Bytes[0] |= ((Immediate & 0xf000) >> 12);
263  Bytes[1] |= ((Immediate & 0x0800) >> 11);
264  Bytes[2] |= ((Immediate & 0x00ff) >> 0);
265  Bytes[3] |= (((Immediate & 0x0700) >> 8) << 4);
266  };
267 
268  EncodeImmediate(&Target[0],
269  (static_cast<uint32_t>(Result) >> 00) | ISASelectionBit);
270  EncodeImmediate(&Target[4], static_cast<uint32_t>(Result) >> 16);
271  break;
272  }
274  // The most significant 20-bits of the signed 21-bit relative displacement
275  uint64_t Value =
276  RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
277  assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
278  "relocation overflow");
279  assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
280  "relocation underflow");
281  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
282  << " RelType: IMAGE_REL_ARM_BRANCH20T"
283  << " Value: " << static_cast<int32_t>(Value) << '\n');
284  static_cast<void>(Value);
285  llvm_unreachable("unimplemented relocation");
286  break;
287  }
289  // The most significant 24-bits of the signed 25-bit relative displacement
290  uint64_t Value =
291  RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
292  assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
293  "relocation overflow");
294  assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
295  "relocation underflow");
296  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
297  << " RelType: IMAGE_REL_ARM_BRANCH24T"
298  << " Value: " << static_cast<int32_t>(Value) << '\n');
299  static_cast<void>(Value);
300  llvm_unreachable("unimplemented relocation");
301  break;
302  }
304  // The most significant 24-bits of the signed 25-bit relative displacement
305  uint64_t Value =
306  RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
307  assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
308  "relocation overflow");
309  assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
310  "relocation underflow");
311  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
312  << " RelType: IMAGE_REL_ARM_BLX23T"
313  << " Value: " << static_cast<int32_t>(Value) << '\n');
314  static_cast<void>(Value);
315  llvm_unreachable("unimplemented relocation");
316  break;
317  }
318  }
319  }
320 
321  void registerEHFrames() override {}
322 };
323 
324 }
325 
326 #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
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:614
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:125
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:47
COFF.h
llvm::RuntimeDyldImpl::addRelocationForSection
void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID)
Definition: RuntimeDyld.cpp:927
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:932
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:122
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:57
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
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
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
llvm::raw_ostream::flush
void flush()
Definition: raw_ostream.h:183
llvm::RuntimeDyldImpl::writeBytesUnaligned
void writeBytesUnaligned(uint64_t Value, uint8_t *Dst, unsigned Size) const
Endian-aware write.
Definition: RuntimeDyld.cpp:713
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
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:186
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:321
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:136
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::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:60
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:908
uint16_t
llvm::RuntimeDyldCOFFThumb::RuntimeDyldCOFFThumb
RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM, JITSymbolResolver &Resolver)
Definition: RuntimeDyldCOFFThumb.h:49
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:53
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:79
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:557
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:699
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::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