OSDN Git Service

68c85d6b4d7633fdb2b22c7d632140d70d7e1d91
[android-x86/external-llvm.git] / lib / ExecutionEngine / RuntimeDyld / RuntimeDyldMachO.cpp
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 #include "RuntimeDyldMachO.h"
15 #include "Targets/RuntimeDyldMachOAArch64.h"
16 #include "Targets/RuntimeDyldMachOARM.h"
17 #include "Targets/RuntimeDyldMachOI386.h"
18 #include "Targets/RuntimeDyldMachOX86_64.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/StringRef.h"
21
22 using namespace llvm;
23 using namespace llvm::object;
24
25 #define DEBUG_TYPE "dyld"
26
27 namespace {
28
29 class LoadedMachOObjectInfo final
30     : public RuntimeDyld::LoadedObjectInfoHelper<LoadedMachOObjectInfo> {
31 public:
32   LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld,
33                         ObjSectionToIDMap ObjSecToIDMap)
34       : LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {}
35
36   OwningBinary<ObjectFile>
37   getObjectForDebug(const ObjectFile &Obj) const override {
38     return OwningBinary<ObjectFile>();
39   }
40 };
41
42 }
43
44 namespace llvm {
45
46 int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const {
47   unsigned NumBytes = 1 << RE.Size;
48   uint8_t *Src = Sections[RE.SectionID].getAddress() + RE.Offset;
49
50   return static_cast<int64_t>(readBytesUnaligned(Src, NumBytes));
51 }
52
53 relocation_iterator RuntimeDyldMachO::processScatteredVANILLA(
54                           unsigned SectionID, relocation_iterator RelI,
55                           const ObjectFile &BaseObjT,
56                           RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) {
57   const MachOObjectFile &Obj =
58     static_cast<const MachOObjectFile&>(BaseObjT);
59   MachO::any_relocation_info RE =
60     Obj.getRelocation(RelI->getRawDataRefImpl());
61
62   SectionEntry &Section = Sections[SectionID];
63   uint32_t RelocType = Obj.getAnyRelocationType(RE);
64   bool IsPCRel = Obj.getAnyRelocationPCRel(RE);
65   unsigned Size = Obj.getAnyRelocationLength(RE);
66   uint64_t Offset = RelI->getOffset();
67   uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);
68   unsigned NumBytes = 1 << Size;
69   int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes);
70
71   unsigned SymbolBaseAddr = Obj.getScatteredRelocationValue(RE);
72   section_iterator TargetSI = getSectionByAddress(Obj, SymbolBaseAddr);
73   assert(TargetSI != Obj.section_end() && "Can't find section for symbol");
74   uint64_t SectionBaseAddr = TargetSI->getAddress();
75   SectionRef TargetSection = *TargetSI;
76   bool IsCode = TargetSection.isText();
77   uint32_t TargetSectionID =
78     findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID);
79
80   Addend -= SectionBaseAddr;
81   RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size);
82
83   addRelocationForSection(R, TargetSectionID);
84
85   return ++RelI;
86 }
87
88
89 RelocationValueRef RuntimeDyldMachO::getRelocationValueRef(
90     const ObjectFile &BaseTObj, const relocation_iterator &RI,
91     const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) {
92
93   const MachOObjectFile &Obj =
94       static_cast<const MachOObjectFile &>(BaseTObj);
95   MachO::any_relocation_info RelInfo =
96       Obj.getRelocation(RI->getRawDataRefImpl());
97   RelocationValueRef Value;
98
99   bool IsExternal = Obj.getPlainRelocationExternal(RelInfo);
100   if (IsExternal) {
101     symbol_iterator Symbol = RI->getSymbol();
102     Expected<StringRef> TargetNameOrErr = Symbol->getName();
103     if (!TargetNameOrErr) {
104       std::string Buf;
105       raw_string_ostream OS(Buf);
106       logAllUnhandledErrors(TargetNameOrErr.takeError(), OS, "");
107       OS.flush();
108       report_fatal_error(Buf);
109     }
110     StringRef TargetName = *TargetNameOrErr;
111     RTDyldSymbolTable::const_iterator SI =
112       GlobalSymbolTable.find(TargetName.data());
113     if (SI != GlobalSymbolTable.end()) {
114       const auto &SymInfo = SI->second;
115       Value.SectionID = SymInfo.getSectionID();
116       Value.Offset = SymInfo.getOffset() + RE.Addend;
117     } else {
118       Value.SymbolName = TargetName.data();
119       Value.Offset = RE.Addend;
120     }
121   } else {
122     SectionRef Sec = Obj.getAnyRelocationSection(RelInfo);
123     bool IsCode = Sec.isText();
124     Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID);
125     uint64_t Addr = Sec.getAddress();
126     Value.Offset = RE.Addend - Addr;
127   }
128
129   return Value;
130 }
131
132 void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value,
133                                             const relocation_iterator &RI,
134                                             unsigned OffsetToNextPC) {
135   auto &O = *cast<MachOObjectFile>(RI->getObject());
136   section_iterator SecI = O.getRelocationRelocatedSection(RI);
137   Value.Offset += RI->getOffset() + OffsetToNextPC + SecI->getAddress();
138 }
139
140 void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE,
141                                                uint64_t Value) const {
142   const SectionEntry &Section = Sections[RE.SectionID];
143   uint8_t *LocalAddress = Section.getAddress() + RE.Offset;
144   uint64_t FinalAddress = Section.getLoadAddress() + RE.Offset;
145
146   dbgs() << "resolveRelocation Section: " << RE.SectionID
147          << " LocalAddress: " << format("%p", LocalAddress)
148          << " FinalAddress: " << format("0x%016" PRIx64, FinalAddress)
149          << " Value: " << format("0x%016" PRIx64, Value) << " Addend: " << RE.Addend
150          << " isPCRel: " << RE.IsPCRel << " MachoType: " << RE.RelType
151          << " Size: " << (1 << RE.Size) << "\n";
152 }
153
154 section_iterator
155 RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj,
156                                       uint64_t Addr) {
157   section_iterator SI = Obj.section_begin();
158   section_iterator SE = Obj.section_end();
159
160   for (; SI != SE; ++SI) {
161     uint64_t SAddr = SI->getAddress();
162     uint64_t SSize = SI->getSize();
163     if ((Addr >= SAddr) && (Addr < SAddr + SSize))
164       return SI;
165   }
166
167   return SE;
168 }
169
170
171 // Populate __pointers section.
172 void RuntimeDyldMachO::populateIndirectSymbolPointersSection(
173                                                     const MachOObjectFile &Obj,
174                                                     const SectionRef &PTSection,
175                                                     unsigned PTSectionID) {
176   assert(!Obj.is64Bit() &&
177          "Pointer table section not supported in 64-bit MachO.");
178
179   MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
180   MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl());
181   uint32_t PTSectionSize = Sec32.size;
182   unsigned FirstIndirectSymbol = Sec32.reserved1;
183   const unsigned PTEntrySize = 4;
184   unsigned NumPTEntries = PTSectionSize / PTEntrySize;
185   unsigned PTEntryOffset = 0;
186
187   assert((PTSectionSize % PTEntrySize) == 0 &&
188          "Pointers section does not contain a whole number of stubs?");
189
190   DEBUG(dbgs() << "Populating pointer table section "
191                << Sections[PTSectionID].getName() << ", Section ID "
192                << PTSectionID << ", " << NumPTEntries << " entries, "
193                << PTEntrySize << " bytes each:\n");
194
195   for (unsigned i = 0; i < NumPTEntries; ++i) {
196     unsigned SymbolIndex =
197       Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
198     symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
199     Expected<StringRef> IndirectSymbolNameOrErr = SI->getName();
200     if (!IndirectSymbolNameOrErr) {
201       std::string Buf;
202       raw_string_ostream OS(Buf);
203       logAllUnhandledErrors(IndirectSymbolNameOrErr.takeError(), OS, "");
204       OS.flush();
205       report_fatal_error(Buf);
206     }
207     StringRef IndirectSymbolName = *IndirectSymbolNameOrErr;
208     DEBUG(dbgs() << "  " << IndirectSymbolName << ": index " << SymbolIndex
209           << ", PT offset: " << PTEntryOffset << "\n");
210     RelocationEntry RE(PTSectionID, PTEntryOffset,
211                        MachO::GENERIC_RELOC_VANILLA, 0, false, 2);
212     addRelocationForSymbol(RE, IndirectSymbolName);
213     PTEntryOffset += PTEntrySize;
214   }
215 }
216
217 bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const {
218   return Obj.isMachO();
219 }
220
221 template <typename Impl>
222 void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj,
223                                                   ObjSectionToIDMap &SectionMap) {
224   unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
225   unsigned TextSID = RTDYLD_INVALID_SECTION_ID;
226   unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID;
227
228   for (const auto &Section : Obj.sections()) {
229     StringRef Name;
230     Section.getName(Name);
231
232     // Force emission of the __text, __eh_frame, and __gcc_except_tab sections
233     // if they're present. Otherwise call down to the impl to handle other
234     // sections that have already been emitted.
235     if (Name == "__text")
236       TextSID = findOrEmitSection(Obj, Section, true, SectionMap);
237     else if (Name == "__eh_frame")
238       EHFrameSID = findOrEmitSection(Obj, Section, false, SectionMap);
239     else if (Name == "__gcc_except_tab")
240       ExceptTabSID = findOrEmitSection(Obj, Section, true, SectionMap);
241     else {
242       auto I = SectionMap.find(Section);
243       if (I != SectionMap.end())
244         impl().finalizeSection(Obj, I->second, Section);
245     }
246   }
247   UnregisteredEHFrameSections.push_back(
248     EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID));
249 }
250
251 template <typename Impl>
252 unsigned char *RuntimeDyldMachOCRTPBase<Impl>::processFDE(uint8_t *P,
253                                                           int64_t DeltaForText,
254                                                           int64_t DeltaForEH) {
255   typedef typename Impl::TargetPtrT TargetPtrT;
256
257   DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText
258                << ", Delta for EH: " << DeltaForEH << "\n");
259   uint32_t Length = readBytesUnaligned(P, 4);
260   P += 4;
261   uint8_t *Ret = P + Length;
262   uint32_t Offset = readBytesUnaligned(P, 4);
263   if (Offset == 0) // is a CIE
264     return Ret;
265
266   P += 4;
267   TargetPtrT FDELocation = readBytesUnaligned(P, sizeof(TargetPtrT));
268   TargetPtrT NewLocation = FDELocation - DeltaForText;
269   writeBytesUnaligned(NewLocation, P, sizeof(TargetPtrT));
270
271   P += sizeof(TargetPtrT);
272
273   // Skip the FDE address range
274   P += sizeof(TargetPtrT);
275
276   uint8_t Augmentationsize = *P;
277   P += 1;
278   if (Augmentationsize != 0) {
279     TargetPtrT LSDA = readBytesUnaligned(P, sizeof(TargetPtrT));
280     TargetPtrT NewLSDA = LSDA - DeltaForEH;
281     writeBytesUnaligned(NewLSDA, P, sizeof(TargetPtrT));
282   }
283
284   return Ret;
285 }
286
287 static int64_t computeDelta(SectionEntry *A, SectionEntry *B) {
288   int64_t ObjDistance = static_cast<int64_t>(A->getObjAddress()) -
289                         static_cast<int64_t>(B->getObjAddress());
290   int64_t MemDistance = A->getLoadAddress() - B->getLoadAddress();
291   return ObjDistance - MemDistance;
292 }
293
294 template <typename Impl>
295 void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() {
296
297   for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) {
298     EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i];
299     if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID ||
300         SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID)
301       continue;
302     SectionEntry *Text = &Sections[SectionInfo.TextSID];
303     SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID];
304     SectionEntry *ExceptTab = nullptr;
305     if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID)
306       ExceptTab = &Sections[SectionInfo.ExceptTabSID];
307
308     int64_t DeltaForText = computeDelta(Text, EHFrame);
309     int64_t DeltaForEH = 0;
310     if (ExceptTab)
311       DeltaForEH = computeDelta(ExceptTab, EHFrame);
312
313     uint8_t *P = EHFrame->getAddress();
314     uint8_t *End = P + EHFrame->getSize();
315     while (P != End) {
316       P = processFDE(P, DeltaForText, DeltaForEH);
317     }
318
319     MemMgr.registerEHFrames(EHFrame->getAddress(), EHFrame->getLoadAddress(),
320                             EHFrame->getSize());
321   }
322   UnregisteredEHFrameSections.clear();
323 }
324
325 std::unique_ptr<RuntimeDyldMachO>
326 RuntimeDyldMachO::create(Triple::ArchType Arch,
327                          RuntimeDyld::MemoryManager &MemMgr,
328                          RuntimeDyld::SymbolResolver &Resolver) {
329   switch (Arch) {
330   default:
331     llvm_unreachable("Unsupported target for RuntimeDyldMachO.");
332     break;
333   case Triple::arm:
334     return make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver);
335   case Triple::aarch64:
336     return make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver);
337   case Triple::x86:
338     return make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver);
339   case Triple::x86_64:
340     return make_unique<RuntimeDyldMachOX86_64>(MemMgr, Resolver);
341   }
342 }
343
344 std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
345 RuntimeDyldMachO::loadObject(const object::ObjectFile &O) {
346   return llvm::make_unique<LoadedMachOObjectInfo>(*this, loadObjectImpl(O));
347 }
348
349 } // end namespace llvm