LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RuntimeDyldMachO.cpp
Go to the documentation of this file.
1 //===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- 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 // Implementation of the MC-JIT runtime dynamic linker.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #define DEBUG_TYPE "dyld"
15 #include "RuntimeDyldMachO.h"
16 #include "llvm/ADT/OwningPtr.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/StringRef.h"
19 using namespace llvm;
20 using namespace llvm::object;
21 
22 namespace llvm {
23 
24 static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, intptr_t DeltaForEH) {
25  uint32_t Length = *((uint32_t*)P);
26  P += 4;
27  unsigned char *Ret = P + Length;
28  uint32_t Offset = *((uint32_t*)P);
29  if (Offset == 0) // is a CIE
30  return Ret;
31 
32  P += 4;
33  intptr_t FDELocation = *((intptr_t*)P);
34  intptr_t NewLocation = FDELocation - DeltaForText;
35  *((intptr_t*)P) = NewLocation;
36  P += sizeof(intptr_t);
37 
38  // Skip the FDE address range
39  P += sizeof(intptr_t);
40 
41  uint8_t Augmentationsize = *P;
42  P += 1;
43  if (Augmentationsize != 0) {
44  intptr_t LSDA = *((intptr_t*)P);
45  intptr_t NewLSDA = LSDA - DeltaForEH;
46  *((intptr_t*)P) = NewLSDA;
47  }
48 
49  return Ret;
50 }
51 
53  intptr_t ObjDistance = A->ObjAddress - B->ObjAddress;
54  intptr_t MemDistance = A->LoadAddress - B->LoadAddress;
55  return ObjDistance - MemDistance;
56 }
57 
59 
60  if (!MemMgr)
61  return;
62  for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) {
63  EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i];
64  if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID ||
65  SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID)
66  continue;
67  SectionEntry *Text = &Sections[SectionInfo.TextSID];
68  SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID];
69  SectionEntry *ExceptTab = NULL;
70  if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID)
71  ExceptTab = &Sections[SectionInfo.ExceptTabSID];
72 
73  intptr_t DeltaForText = computeDelta(Text, EHFrame);
74  intptr_t DeltaForEH = 0;
75  if (ExceptTab)
76  DeltaForEH = computeDelta(ExceptTab, EHFrame);
77 
78  unsigned char *P = EHFrame->Address;
79  unsigned char *End = P + EHFrame->Size;
80  do {
81  P = processFDE(P, DeltaForText, DeltaForEH);
82  } while(P != End);
83 
84  MemMgr->registerEHFrames(EHFrame->Address,
85  EHFrame->LoadAddress,
86  EHFrame->Size);
87  }
88  UnregisteredEHFrameSections.clear();
89 }
90 
92  unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
93  unsigned TextSID = RTDYLD_INVALID_SECTION_ID;
94  unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID;
95  ObjSectionToIDMap::iterator i, e;
96  for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) {
97  const SectionRef &Section = i->first;
99  Section.getName(Name);
100  if (Name == "__eh_frame")
101  EHFrameSID = i->second;
102  else if (Name == "__text")
103  TextSID = i->second;
104  else if (Name == "__gcc_except_tab")
105  ExceptTabSID = i->second;
106  }
107  UnregisteredEHFrameSections.push_back(EHFrameRelatedSections(EHFrameSID,
108  TextSID,
109  ExceptTabSID));
110 }
111 
112 // The target location for the relocation is described by RE.SectionID and
113 // RE.Offset. RE.SectionID can be used to find the SectionEntry. Each
114 // SectionEntry has three members describing its location.
115 // SectionEntry::Address is the address at which the section has been loaded
116 // into memory in the current (host) process. SectionEntry::LoadAddress is the
117 // address that the section will have in the target process.
118 // SectionEntry::ObjAddress is the address of the bits for this section in the
119 // original emitted object image (also in the current address space).
120 //
121 // Relocations will be applied as if the section were loaded at
122 // SectionEntry::LoadAddress, but they will be applied at an address based
123 // on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer to
124 // Target memory contents if they are required for value calculations.
125 //
126 // The Value parameter here is the load address of the symbol for the
127 // relocation to be applied. For relocations which refer to symbols in the
128 // current object Value will be the LoadAddress of the section in which
129 // the symbol resides (RE.Addend provides additional information about the
130 // symbol location). For external symbols, Value will be the address of the
131 // symbol in the target address space.
132 void RuntimeDyldMachO::resolveRelocation(const RelocationEntry &RE,
133  uint64_t Value) {
134  const SectionEntry &Section = Sections[RE.SectionID];
135  return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
136  RE.IsPCRel, RE.Size);
137 }
138 
139 void RuntimeDyldMachO::resolveRelocation(const SectionEntry &Section,
140  uint64_t Offset,
141  uint64_t Value,
142  uint32_t Type,
143  int64_t Addend,
144  bool isPCRel,
145  unsigned LogSize) {
146  uint8_t *LocalAddress = Section.Address + Offset;
147  uint64_t FinalAddress = Section.LoadAddress + Offset;
148  unsigned MachoType = Type;
149  unsigned Size = 1 << LogSize;
150 
151  DEBUG(dbgs() << "resolveRelocation LocalAddress: "
152  << format("%p", LocalAddress)
153  << " FinalAddress: " << format("%p", FinalAddress)
154  << " Value: " << format("%p", Value)
155  << " Addend: " << Addend
156  << " isPCRel: " << isPCRel
157  << " MachoType: " << MachoType
158  << " Size: " << Size
159  << "\n");
160 
161  // This just dispatches to the proper target specific routine.
162  switch (Arch) {
163  default: llvm_unreachable("Unsupported CPU type!");
164  case Triple::x86_64:
165  resolveX86_64Relocation(LocalAddress,
166  FinalAddress,
167  (uintptr_t)Value,
168  isPCRel,
169  MachoType,
170  Size,
171  Addend);
172  break;
173  case Triple::x86:
174  resolveI386Relocation(LocalAddress,
175  FinalAddress,
176  (uintptr_t)Value,
177  isPCRel,
178  MachoType,
179  Size,
180  Addend);
181  break;
182  case Triple::arm: // Fall through.
183  case Triple::thumb:
184  resolveARMRelocation(LocalAddress,
185  FinalAddress,
186  (uintptr_t)Value,
187  isPCRel,
188  MachoType,
189  Size,
190  Addend);
191  break;
192  }
193 }
194 
195 bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress,
196  uint64_t FinalAddress,
197  uint64_t Value,
198  bool isPCRel,
199  unsigned Type,
200  unsigned Size,
201  int64_t Addend) {
202  if (isPCRel)
203  Value -= FinalAddress + 4; // see resolveX86_64Relocation
204 
205  switch (Type) {
206  default:
207  llvm_unreachable("Invalid relocation type!");
209  uint8_t *p = LocalAddress;
210  uint64_t ValueToWrite = Value + Addend;
211  for (unsigned i = 0; i < Size; ++i) {
212  *p++ = (uint8_t)(ValueToWrite & 0xff);
213  ValueToWrite >>= 8;
214  }
215  return false;
216  }
220  return Error("Relocation type not implemented yet!");
221  }
222 }
223 
224 bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress,
225  uint64_t FinalAddress,
226  uint64_t Value,
227  bool isPCRel,
228  unsigned Type,
229  unsigned Size,
230  int64_t Addend) {
231  // If the relocation is PC-relative, the value to be encoded is the
232  // pointer difference.
233  if (isPCRel)
234  // FIXME: It seems this value needs to be adjusted by 4 for an effective PC
235  // address. Is that expected? Only for branches, perhaps?
236  Value -= FinalAddress + 4;
237 
238  switch(Type) {
239  default:
240  llvm_unreachable("Invalid relocation type!");
247  Value += Addend;
248  // Mask in the target value a byte at a time (we don't have an alignment
249  // guarantee for the target address, so this is safest).
250  uint8_t *p = (uint8_t*)LocalAddress;
251  for (unsigned i = 0; i < Size; ++i) {
252  *p++ = (uint8_t)Value;
253  Value >>= 8;
254  }
255  return false;
256  }
261  return Error("Relocation type not implemented yet!");
262  }
263 }
264 
265 bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress,
266  uint64_t FinalAddress,
267  uint64_t Value,
268  bool isPCRel,
269  unsigned Type,
270  unsigned Size,
271  int64_t Addend) {
272  // If the relocation is PC-relative, the value to be encoded is the
273  // pointer difference.
274  if (isPCRel) {
275  Value -= FinalAddress;
276  // ARM PCRel relocations have an effective-PC offset of two instructions
277  // (four bytes in Thumb mode, 8 bytes in ARM mode).
278  // FIXME: For now, assume ARM mode.
279  Value -= 8;
280  }
281 
282  switch(Type) {
283  default:
284  llvm_unreachable("Invalid relocation type!");
286  // Mask in the target value a byte at a time (we don't have an alignment
287  // guarantee for the target address, so this is safest).
288  uint8_t *p = (uint8_t*)LocalAddress;
289  for (unsigned i = 0; i < Size; ++i) {
290  *p++ = (uint8_t)Value;
291  Value >>= 8;
292  }
293  break;
294  }
295  case MachO::ARM_RELOC_BR24: {
296  // Mask the value into the target address. We know instructions are
297  // 32-bit aligned, so we can do it all at once.
298  uint32_t *p = (uint32_t*)LocalAddress;
299  // The low two bits of the value are not encoded.
300  Value >>= 2;
301  // Mask the value to 24 bits.
302  Value &= 0xffffff;
303  // FIXME: If the destination is a Thumb function (and the instruction
304  // is a non-predicated BL instruction), we need to change it to a BLX
305  // instruction instead.
306 
307  // Insert the value into the instruction.
308  *p = (*p & ~0xffffff) | Value;
309  break;
310  }
319  return Error("Relocation type not implemented yet!");
320  }
321  return false;
322 }
323 
325  RelocationRef RelI,
326  ObjectImage &Obj,
327  ObjSectionToIDMap &ObjSectionToID,
328  const SymbolTableMap &Symbols,
329  StubMap &Stubs) {
330  const ObjectFile *OF = Obj.getObjectFile();
331  const MachOObjectFile *MachO = static_cast<const MachOObjectFile*>(OF);
333 
334  uint32_t RelType = MachO->getAnyRelocationType(RE);
335 
336  // FIXME: Properly handle scattered relocations.
337  // For now, optimistically skip these: they can often be ignored, as
338  // the static linker will already have applied the relocation, and it
339  // only needs to be reapplied if symbols move relative to one another.
340  // Note: This will fail horribly where the relocations *do* need to be
341  // applied, but that was already the case.
342  if (MachO->isRelocationScattered(RE))
343  return;
344 
345  RelocationValueRef Value;
346  SectionEntry &Section = Sections[SectionID];
347 
348  bool isExtern = MachO->getPlainRelocationExternal(RE);
349  bool IsPCRel = MachO->getAnyRelocationPCRel(RE);
350  unsigned Size = MachO->getAnyRelocationLength(RE);
351  uint64_t Offset;
352  RelI.getOffset(Offset);
353  uint8_t *LocalAddress = Section.Address + Offset;
354  unsigned NumBytes = 1 << Size;
355  uint64_t Addend = 0;
356  memcpy(&Addend, LocalAddress, NumBytes);
357 
358  if (isExtern) {
359  // Obtain the symbol name which is referenced in the relocation
361  StringRef TargetName;
362  Symbol->getName(TargetName);
363  // First search for the symbol in the local symbol table
364  SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data());
365  if (lsi != Symbols.end()) {
366  Value.SectionID = lsi->second.first;
367  Value.Addend = lsi->second.second + Addend;
368  } else {
369  // Search for the symbol in the global symbol table
370  SymbolTableMap::const_iterator gsi = GlobalSymbolTable.find(TargetName.data());
371  if (gsi != GlobalSymbolTable.end()) {
372  Value.SectionID = gsi->second.first;
373  Value.Addend = gsi->second.second + Addend;
374  } else {
375  Value.SymbolName = TargetName.data();
376  Value.Addend = Addend;
377  }
378  }
379  } else {
380  SectionRef Sec = MachO->getRelocationSection(RE);
381  Value.SectionID = findOrEmitSection(Obj, Sec, true, ObjSectionToID);
382  uint64_t Addr;
383  Sec.getAddress(Addr);
384  Value.Addend = Addend - Addr;
385  }
386 
387  if (Arch == Triple::x86_64 && (RelType == MachO::X86_64_RELOC_GOT ||
388  RelType == MachO::X86_64_RELOC_GOT_LOAD)) {
389  assert(IsPCRel);
390  assert(Size == 2);
391  StubMap::const_iterator i = Stubs.find(Value);
392  uint8_t *Addr;
393  if (i != Stubs.end()) {
394  Addr = Section.Address + i->second;
395  } else {
396  Stubs[Value] = Section.StubOffset;
397  uint8_t *GOTEntry = Section.Address + Section.StubOffset;
398  RelocationEntry RE(SectionID, Section.StubOffset,
399  MachO::X86_64_RELOC_UNSIGNED, 0, false, 3);
400  if (Value.SymbolName)
401  addRelocationForSymbol(RE, Value.SymbolName);
402  else
403  addRelocationForSection(RE, Value.SectionID);
404  Section.StubOffset += 8;
405  Addr = GOTEntry;
406  }
407  resolveRelocation(Section, Offset, (uint64_t)Addr,
408  MachO::X86_64_RELOC_UNSIGNED, Value.Addend, true, 2);
409  } else if (Arch == Triple::arm &&
410  (RelType & 0xf) == MachO::ARM_RELOC_BR24) {
411  // This is an ARM branch relocation, need to use a stub function.
412 
413  // Look up for existing stub.
414  StubMap::const_iterator i = Stubs.find(Value);
415  if (i != Stubs.end())
416  resolveRelocation(Section, Offset,
417  (uint64_t)Section.Address + i->second,
418  RelType, 0, IsPCRel, Size);
419  else {
420  // Create a new stub function.
421  Stubs[Value] = Section.StubOffset;
422  uint8_t *StubTargetAddr = createStubFunction(Section.Address +
423  Section.StubOffset);
424  RelocationEntry RE(SectionID, StubTargetAddr - Section.Address,
426  if (Value.SymbolName)
427  addRelocationForSymbol(RE, Value.SymbolName);
428  else
429  addRelocationForSection(RE, Value.SectionID);
430  resolveRelocation(Section, Offset,
431  (uint64_t)Section.Address + Section.StubOffset,
432  RelType, 0, IsPCRel, Size);
433  Section.StubOffset += getMaxStubSize();
434  }
435  } else {
436  RelocationEntry RE(SectionID, Offset, RelType, Value.Addend,
437  IsPCRel, Size);
438  if (Value.SymbolName)
439  addRelocationForSymbol(RE, Value.SymbolName);
440  else
441  addRelocationForSection(RE, Value.SectionID);
442  }
443 }
444 
445 
447  const ObjectBuffer *InputBuffer) const {
448  if (InputBuffer->getBufferSize() < 4)
449  return false;
450  StringRef Magic(InputBuffer->getBufferStart(), 4);
451  if (Magic == "\xFE\xED\xFA\xCE") return true;
452  if (Magic == "\xCE\xFA\xED\xFE") return true;
453  if (Magic == "\xFE\xED\xFA\xCF") return true;
454  if (Magic == "\xCF\xFA\xED\xFE") return true;
455  return false;
456 }
457 
458 } // end namespace llvm
COFF::RelocationTypeX86 Type
Definition: COFFYAML.cpp:227
static intptr_t computeDelta(SectionEntry *A, SectionEntry *B)
size_t Size
Size - section size. Doesn't include the stubs.
size_t getBufferSize() const
Definition: ObjectBuffer.h:47
iterator find(StringRef Key)
Definition: StringMap.h:291
uint8_t * Address
Address - address in the linker's memory where the section resides.
virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const
virtual void finalizeLoad(ObjSectionToIDMap &SectionMap)
MachO::any_relocation_info getRelocation(DataRefImpl Rel) const
bool IsPCRel
True if this is a PCRel relocation (MachO specific).
unsigned SectionID
SectionID - the section this relocation points to.
const char * getBufferStart() const
Definition: ObjectBuffer.h:46
#define llvm_unreachable(msg)
std::map< RelocationValueRef, uintptr_t > StubMap
format_object1< T > format(const char *Fmt, const T &Val)
Definition: Format.h:180
SectionRef getRelocationSection(const MachO::any_relocation_info &RE) const
const char * data() const
Definition: StringRef.h:107
error_code getName(StringRef &Result) const
Definition: ObjectFile.h:468
#define P(N)
virtual void registerEHFrames()
unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const
error_code getAddress(uint64_t &Result) const
Definition: ObjectFile.h:472
symbol_iterator getSymbol() const
Definition: ObjectFile.h:559
static unsigned char * processFDE(unsigned char *P, intptr_t DeltaForText, intptr_t DeltaForEH)
bool isRelocationScattered(const MachO::any_relocation_info &RE) const
static const char *const Magic
Definition: Archive.cpp:24
uint32_t RelType
RelType - relocation type.
unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
Definition: Debug.cpp:101
virtual object::ObjectFile * getObjectFile() const =0
#define RTDYLD_INVALID_SECTION_ID
uint64_t Offset
Offset - offset into the section.
std::map< SectionRef, unsigned > ObjSectionToIDMap
virtual void processRelocationRef(unsigned SectionID, RelocationRef RelI, ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, StubMap &Stubs)
Parses the object file relocation and stores it to Relocations or SymbolRelocations (this depends on ...
unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const
LLVM Value Representation.
Definition: Value.h:66
unsigned Size
The size of this relocation (MachO specific).
#define DEBUG(X)
Definition: Debug.h:97
bool getPlainRelocationExternal(const MachO::any_relocation_info &RE) const
error_code getOffset(uint64_t &Result) const
Definition: ObjectFile.h:555
iterator end()
Definition: StringMap.h:281
DataRefImpl getRawDataRefImpl() const
Definition: ObjectFile.h:581