LLVM  3.7.0
RuntimeDyldMachOARM.h
Go to the documentation of this file.
1 //===----- RuntimeDyldMachOARM.h ---- MachO/ARM 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 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H
11 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H
12 
13 #include "../RuntimeDyldMachO.h"
14 
15 #define DEBUG_TYPE "dyld"
16 
17 namespace llvm {
18 
20  : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> {
21 private:
23 
24 public:
25 
26  typedef uint32_t TargetPtrT;
27 
30  : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
31 
32  unsigned getMaxStubSize() override { return 8; }
33 
34  unsigned getStubAlignment() override { return 4; }
35 
36  int64_t decodeAddend(const RelocationEntry &RE) const {
38  uint8_t *LocalAddress = Section.Address + RE.Offset;
39 
40  switch (RE.RelType) {
41  default:
42  return memcpyAddend(RE);
43  case MachO::ARM_RELOC_BR24: {
44  uint32_t Temp = readBytesUnaligned(LocalAddress, 4);
45  Temp &= 0x00ffffff; // Mask out the opcode.
46  // Now we've got the shifted immediate, shift by 2, sign extend and ret.
47  return SignExtend32<26>(Temp << 2);
48  }
49  }
50  }
51 
53  processRelocationRef(unsigned SectionID, relocation_iterator RelI,
54  const ObjectFile &BaseObjT,
55  ObjSectionToIDMap &ObjSectionToID,
56  StubMap &Stubs) override {
57  const MachOObjectFile &Obj =
58  static_cast<const MachOObjectFile &>(BaseObjT);
60  Obj.getRelocation(RelI->getRawDataRefImpl());
61  uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
62 
63  if (Obj.isRelocationScattered(RelInfo)) {
64  if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF)
65  return processHALFSECTDIFFRelocation(SectionID, RelI, Obj,
66  ObjSectionToID);
67  else
68  return ++++RelI;
69  }
70 
71  RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
72  RE.Addend = decodeAddend(RE);
74  getRelocationValueRef(Obj, RelI, RE, ObjSectionToID));
75 
76  if (RE.IsPCRel)
77  makeValueAddendPCRel(Value, RelI, 8);
78 
79  if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24)
80  processBranchRelocation(RE, Value, Stubs);
81  else {
82  RE.Addend = Value.Offset;
83  if (Value.SymbolName)
85  else
87  }
88 
89  return ++RelI;
90  }
91 
92  void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
93  DEBUG(dumpRelocationToResolve(RE, Value));
95  uint8_t *LocalAddress = Section.Address + RE.Offset;
96 
97  // If the relocation is PC-relative, the value to be encoded is the
98  // pointer difference.
99  if (RE.IsPCRel) {
100  uint64_t FinalAddress = Section.LoadAddress + RE.Offset;
101  Value -= FinalAddress;
102  // ARM PCRel relocations have an effective-PC offset of two instructions
103  // (four bytes in Thumb mode, 8 bytes in ARM mode).
104  // FIXME: For now, assume ARM mode.
105  Value -= 8;
106  }
107 
108  switch (RE.RelType) {
109  default:
110  llvm_unreachable("Invalid relocation type!");
112  writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size);
113  break;
114  case MachO::ARM_RELOC_BR24: {
115  // Mask the value into the target address. We know instructions are
116  // 32-bit aligned, so we can do it all at once.
117  Value += RE.Addend;
118  // The low two bits of the value are not encoded.
119  Value >>= 2;
120  // Mask the value to 24 bits.
121  uint64_t FinalValue = Value & 0xffffff;
122  // FIXME: If the destination is a Thumb function (and the instruction
123  // is a non-predicated BL instruction), we need to change it to a BLX
124  // instruction instead.
125 
126  // Insert the value into the instruction.
127  uint32_t Temp = readBytesUnaligned(LocalAddress, 4);
128  writeBytesUnaligned((Temp & ~0xffffff) | FinalValue, LocalAddress, 4);
129 
130  break;
131  }
133  uint64_t SectionABase = Sections[RE.Sections.SectionA].LoadAddress;
134  uint64_t SectionBBase = Sections[RE.Sections.SectionB].LoadAddress;
135  assert((Value == SectionABase || Value == SectionBBase) &&
136  "Unexpected HALFSECTDIFF relocation value.");
137  Value = SectionABase - SectionBBase + RE.Addend;
138  if (RE.Size & 0x1) // :upper16:
139  Value = (Value >> 16);
140  Value &= 0xffff;
141 
142  uint32_t Insn = readBytesUnaligned(LocalAddress, 4);
143  Insn = (Insn & 0xfff0f000) | ((Value & 0xf000) << 4) | (Value & 0x0fff);
144  writeBytesUnaligned(Insn, LocalAddress, 4);
145  break;
146  }
147 
155  Error("Relocation type not implemented yet!");
156  return;
157  }
158  }
159 
160  void finalizeSection(const ObjectFile &Obj, unsigned SectionID,
161  const SectionRef &Section) {
162  StringRef Name;
163  Section.getName(Name);
164 
165  if (Name == "__nl_symbol_ptr")
166  populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj),
167  Section, SectionID);
168  }
169 
170 private:
171 
172  void processBranchRelocation(const RelocationEntry &RE,
173  const RelocationValueRef &Value,
174  StubMap &Stubs) {
175  // This is an ARM branch relocation, need to use a stub function.
176  // Look up for existing stub.
178  RuntimeDyldMachO::StubMap::const_iterator i = Stubs.find(Value);
179  uint8_t *Addr;
180  if (i != Stubs.end()) {
181  Addr = Section.Address + i->second;
182  } else {
183  // Create a new stub function.
184  Stubs[Value] = Section.StubOffset;
185  uint8_t *StubTargetAddr =
186  createStubFunction(Section.Address + Section.StubOffset);
187  RelocationEntry StubRE(RE.SectionID, StubTargetAddr - Section.Address,
188  MachO::GENERIC_RELOC_VANILLA, Value.Offset, false,
189  2);
190  if (Value.SymbolName)
191  addRelocationForSymbol(StubRE, Value.SymbolName);
192  else
193  addRelocationForSection(StubRE, Value.SectionID);
194  Addr = Section.Address + Section.StubOffset;
195  Section.StubOffset += getMaxStubSize();
196  }
197  RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, 0,
198  RE.IsPCRel, RE.Size);
199  resolveRelocation(TargetRE, (uint64_t)Addr);
200  }
201 
203  processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
204  const ObjectFile &BaseTObj,
205  ObjSectionToIDMap &ObjSectionToID) {
206  const MachOObjectFile &MachO =
207  static_cast<const MachOObjectFile&>(BaseTObj);
209  MachO.getRelocation(RelI->getRawDataRefImpl());
210 
211 
212  // For a half-diff relocation the length bits actually record whether this
213  // is a movw/movt, and whether this is arm or thumb.
214  // Bit 0 indicates movw (b0 == 0) or movt (b0 == 1).
215  // Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1).
216  unsigned HalfDiffKindBits = MachO.getAnyRelocationLength(RE);
217  if (HalfDiffKindBits & 0x2)
218  llvm_unreachable("Thumb not yet supported.");
219 
220  SectionEntry &Section = Sections[SectionID];
221  uint32_t RelocType = MachO.getAnyRelocationType(RE);
222  bool IsPCRel = MachO.getAnyRelocationPCRel(RE);
223  uint64_t Offset = RelI->getOffset();
224  uint8_t *LocalAddress = Section.Address + Offset;
225  int64_t Immediate = readBytesUnaligned(LocalAddress, 4); // Copy the whole instruction out.
226  Immediate = ((Immediate >> 4) & 0xf000) | (Immediate & 0xfff);
227 
228  ++RelI;
230  MachO.getRelocation(RelI->getRawDataRefImpl());
231  uint32_t AddrA = MachO.getScatteredRelocationValue(RE);
232  section_iterator SAI = getSectionByAddress(MachO, AddrA);
233  assert(SAI != MachO.section_end() && "Can't find section for address A");
234  uint64_t SectionABase = SAI->getAddress();
235  uint64_t SectionAOffset = AddrA - SectionABase;
236  SectionRef SectionA = *SAI;
237  bool IsCode = SectionA.isText();
238  uint32_t SectionAID =
239  findOrEmitSection(MachO, SectionA, IsCode, ObjSectionToID);
240 
241  uint32_t AddrB = MachO.getScatteredRelocationValue(RE2);
242  section_iterator SBI = getSectionByAddress(MachO, AddrB);
243  assert(SBI != MachO.section_end() && "Can't find section for address B");
244  uint64_t SectionBBase = SBI->getAddress();
245  uint64_t SectionBOffset = AddrB - SectionBBase;
246  SectionRef SectionB = *SBI;
247  uint32_t SectionBID =
248  findOrEmitSection(MachO, SectionB, IsCode, ObjSectionToID);
249 
250  uint32_t OtherHalf = MachO.getAnyRelocationAddress(RE2) & 0xffff;
251  unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0;
252  uint32_t FullImmVal = (Immediate << Shift) | (OtherHalf << (16 - Shift));
253  int64_t Addend = FullImmVal - (AddrA - AddrB);
254 
255  // addend = Encoded - Expected
256  // = Encoded - (AddrA - AddrB)
257 
258  DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB
259  << ", Addend: " << Addend << ", SectionA ID: " << SectionAID
260  << ", SectionAOffset: " << SectionAOffset
261  << ", SectionB ID: " << SectionBID
262  << ", SectionBOffset: " << SectionBOffset << "\n");
263  RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID,
264  SectionAOffset, SectionBID, SectionBOffset, IsPCRel,
265  HalfDiffKindBits);
266 
267  addRelocationForSection(R, SectionAID);
268  addRelocationForSection(R, SectionBID);
269 
270  return ++RelI;
271  }
272 
273 };
274 }
275 
276 #undef DEBUG_TYPE
277 
278 #endif
unsigned getStubAlignment() override
RelocationEntry - used to represent relocations internally in the dynamic linker. ...
void writeBytesUnaligned(uint64_t Value, uint8_t *Dst, unsigned Size) const
Endian-aware write.
unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const
This class is the base class for all object file types.
Definition: ObjectFile.h:176
uint8_t * Address
Address - address in the linker's memory where the section resides.
relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, const ObjectFile &BaseObjT, ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) override
Parses one or more object file relocations (some object files use relocation pairs) and stores it to ...
unsigned getMaxStubSize() override
unsigned findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode, ObjSectionToIDMap &LocalSections)
Find Section in LocalSections.
void populateIndirectSymbolPointersSection(const MachOObjectFile &Obj, const SectionRef &PTSection, unsigned PTSectionID)
bool IsPCRel
True if this is a PCRel relocation (MachO specific).
unsigned SectionID
SectionID - the section this relocation points to.
int64_t decodeAddend(const RelocationEntry &RE) const
RelocationEntry getRelocationEntry(unsigned SectionID, const ObjectFile &BaseTObj, const relocation_iterator &RI) const
Given a relocation_iterator for a non-scattered relocation, construct a RelocationEntry and fill in t...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
int64_t memcpyAddend(const RelocationEntry &RE) const
This convenience method uses memcpy to extract a contiguous addend (the addend size and offset are ta...
std::map< RelocationValueRef, uintptr_t > StubMap
uintptr_t StubOffset
StubOffset - used for architectures with stub functions for far relocations (like ARM)...
uint32_t getScatteredRelocationValue(const MachO::any_relocation_info &RE) const
std::error_code getName(StringRef &Result) const
Definition: ObjectFile.h:362
void dumpRelocationToResolve(const RelocationEntry &RE, uint64_t Value) const
Dump information about the relocation entry (RE) and resolved value.
RuntimeDyldMachOTarget - Templated base class for generic MachO linker algorithms and data structures...
bool Error(const Twine &Msg)
void addRelocationForSymbol(const RelocationEntry &RE, StringRef SymbolName)
unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const
RuntimeDyldMachOARM(RuntimeDyld::MemoryManager &MM, RuntimeDyld::SymbolResolver &Resolver)
MachO::any_relocation_info getRelocation(DataRefImpl Rel) const
RuntimeDyld::SymbolResolver & Resolver
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.
bool isText() const
Definition: ObjectFile.h:382
unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const
static section_iterator getSectionByAddress(const MachOObjectFile &Obj, uint64_t Addr)
unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const
int64_t Addend
Addend - the relocation addend encoded in the instruction itself.
uint32_t RelType
RelType - relocation type.
uint8_t * createStubFunction(uint8_t *Addr, unsigned AbiVariant=0)
Emits long jump instruction to Addr.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:123
uint64_t Offset
Offset - offset into the section.
void finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section)
std::map< SectionRef, unsigned > ObjSectionToIDMap
RelocationValueRef getRelocationValueRef(const ObjectFile &BaseTObj, const relocation_iterator &RI, const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID)
Construct a RelocationValueRef representing the relocation target.
uint64_t LoadAddress
LoadAddress - the address of the section in the target process's memory.
SectionEntry - represents a section emitted into memory by the dynamic linker.
LLVM Value Representation.
Definition: Value.h:69
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override
A object file specific relocation resolver.
unsigned Size
The size of this relocation (MachO specific).
section_iterator section_end() const override
#define DEBUG(X)
Definition: Debug.h:92
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
void makeValueAddendPCRel(RelocationValueRef &Value, const relocation_iterator &RI, unsigned OffsetToNextPC)
Make the RelocationValueRef addend PC-relative.
bool isRelocationScattered(const MachO::any_relocation_info &RE) const
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:69