LLVM  12.0.0git
RuntimeDyldCOFFI386.h
Go to the documentation of this file.
1 //===--- RuntimeDyldCOFFI386.h --- COFF/X86_64 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 x86 support for MC-JIT runtime dynamic linker.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
14 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_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 public:
28  : RuntimeDyldCOFF(MM, Resolver, 4, COFF::IMAGE_REL_I386_DIR32) {}
29 
30  unsigned getMaxStubSize() const override {
31  return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
32  }
33 
34  unsigned getStubAlignment() override { return 1; }
35 
37  processRelocationRef(unsigned SectionID,
39  const object::ObjectFile &Obj,
40  ObjSectionToIDMap &ObjSectionToID,
41  StubMap &Stubs) override {
42 
43  auto Symbol = RelI->getSymbol();
44  if (Symbol == Obj.symbol_end())
45  report_fatal_error("Unknown symbol in relocation");
46 
47  Expected<StringRef> TargetNameOrErr = Symbol->getName();
48  if (!TargetNameOrErr)
49  return TargetNameOrErr.takeError();
50  StringRef TargetName = *TargetNameOrErr;
51 
52  auto SectionOrErr = Symbol->getSection();
53  if (!SectionOrErr)
54  return SectionOrErr.takeError();
55  auto Section = *SectionOrErr;
56  bool IsExtern = Section == Obj.section_end();
57 
58  uint64_t RelType = RelI->getType();
59  uint64_t Offset = RelI->getOffset();
60 
61  unsigned TargetSectionID = -1;
62  uint64_t TargetOffset = -1;
63  if (TargetName.startswith(getImportSymbolPrefix())) {
64  TargetSectionID = SectionID;
65  TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName, true);
66  TargetName = StringRef();
67  IsExtern = false;
68  } else if (!IsExtern) {
69  if (auto TargetSectionIDOrErr = findOrEmitSection(
70  Obj, *Section, Section->isText(), ObjSectionToID))
71  TargetSectionID = *TargetSectionIDOrErr;
72  else
73  return TargetSectionIDOrErr.takeError();
74  if (RelType != COFF::IMAGE_REL_I386_SECTION)
75  TargetOffset = getSymbolOffset(*Symbol);
76  }
77 
78  // Determine the Addend used to adjust the relocation value.
79  uint64_t Addend = 0;
80  SectionEntry &AddendSection = Sections[SectionID];
81  uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
82  uint8_t *Displacement = (uint8_t *)ObjTarget;
83 
84  switch (RelType) {
89  Addend = readBytesUnaligned(Displacement, 4);
90  break;
91  }
92  default:
93  break;
94  }
95 
96 #if !defined(NDEBUG)
97  SmallString<32> RelTypeName;
98  RelI->getTypeName(RelTypeName);
99 #endif
100  LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
101  << " RelType: " << RelTypeName << " TargetName: "
102  << TargetName << " Addend " << Addend << "\n");
103 
104  if (IsExtern) {
105  RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
106  addRelocationForSymbol(RE, TargetName);
107  } else {
108 
109  switch (RelType) {
111  // This relocation is ignored.
112  break;
116  RelocationEntry RE =
117  RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
118  TargetOffset, 0, 0, false, 0);
119  addRelocationForSection(RE, TargetSectionID);
120  break;
121  }
123  RelocationEntry RE =
124  RelocationEntry(TargetSectionID, Offset, RelType, 0);
125  addRelocationForSection(RE, TargetSectionID);
126  break;
127  }
129  RelocationEntry RE =
130  RelocationEntry(SectionID, Offset, RelType, TargetOffset + Addend);
131  addRelocationForSection(RE, TargetSectionID);
132  break;
133  }
134  default:
135  llvm_unreachable("unsupported relocation type");
136  }
137  }
138 
139  return ++RelI;
140  }
141 
142  void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
143  const auto Section = Sections[RE.SectionID];
144  uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
145 
146  switch (RE.RelType) {
148  // This relocation is ignored.
149  break;
151  // The target's 32-bit VA.
152  uint64_t Result =
153  RE.Sections.SectionA == static_cast<uint32_t>(-1)
154  ? Value
155  : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(
156  RE.Addend);
157  assert(Result <= UINT32_MAX && "relocation overflow");
158  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
159  << " RelType: IMAGE_REL_I386_DIR32"
160  << " TargetSection: " << RE.Sections.SectionA
161  << " Value: " << format("0x%08" PRIx32, Result)
162  << '\n');
163  writeBytesUnaligned(Result, Target, 4);
164  break;
165  }
167  // The target's 32-bit RVA.
168  // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
169  uint64_t Result =
170  Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend) -
171  Sections[0].getLoadAddress();
172  assert(Result <= UINT32_MAX && "relocation overflow");
173  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
174  << " RelType: IMAGE_REL_I386_DIR32NB"
175  << " TargetSection: " << RE.Sections.SectionA
176  << " Value: " << format("0x%08" PRIx32, Result)
177  << '\n');
178  writeBytesUnaligned(Result, Target, 4);
179  break;
180  }
182  // 32-bit relative displacement to the target.
183  uint64_t Result = RE.Sections.SectionA == static_cast<uint32_t>(-1)
184  ? Value
185  : Sections[RE.Sections.SectionA].getLoadAddress();
186  Result = Result - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset;
187  assert(static_cast<int64_t>(Result) <= INT32_MAX &&
188  "relocation overflow");
189  assert(static_cast<int64_t>(Result) >= INT32_MIN &&
190  "relocation underflow");
191  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
192  << " RelType: IMAGE_REL_I386_REL32"
193  << " TargetSection: " << RE.Sections.SectionA
194  << " Value: " << format("0x%08" PRIx32, Result)
195  << '\n');
196  writeBytesUnaligned(Result, Target, 4);
197  break;
198  }
200  // 16-bit section index of the section that contains the target.
201  assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX &&
202  "relocation overflow");
203  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
204  << " RelType: IMAGE_REL_I386_SECTION Value: "
205  << RE.SectionID << '\n');
206  writeBytesUnaligned(RE.SectionID, Target, 2);
207  break;
209  // 32-bit offset of the target from the beginning of its section.
210  assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX &&
211  "relocation overflow");
212  LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
213  << " RelType: IMAGE_REL_I386_SECREL Value: "
214  << RE.Addend << '\n');
215  writeBytesUnaligned(RE.Addend, Target, 4);
216  break;
217  default:
218  llvm_unreachable("unsupported relocation type");
219  }
220  }
221 
222  void registerEHFrames() override {}
223 };
224 
225 }
226 
227 #endif
228 
RelocationEntry - used to represent relocations internally in the dynamic linker. ...
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:23
LLVM_NODISCARD bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:289
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:225
uint64_t getSymbolOffset(const SymbolRef &Sym)
Error takeError()
Take ownership of the stored error.
Definition: Error.h:557
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.
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 ...
static constexpr StringRef getImportSymbolPrefix()
std::map< RelocationValueRef, uintptr_t > StubMap
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
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:1870
Symbol resolution interface.
Definition: JITSymbol.h:371
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.
uint64_t getDLLImportOffset(unsigned SectionID, StubMap &Stubs, StringRef Name, bool SetSectionIDMinus1=false)
int64_t Addend
Addend - the relocation addend encoded in the instruction itself.
uint32_t RelType
RelType - relocation type.
unsigned getMaxStubSize() const override
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
SectionEntry - represents a section emitted into memory by the dynamic linker.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:74
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
#define LLVM_DEBUG(X)
Definition: Debug.h:122