1*0a6a1f1dSLionel Sambuc //===---- RuntimeDyldMachOI386.h ---- MachO/I386 specific code. ---*- C++ -*-=//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*0a6a1f1dSLionel Sambuc // License. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc 
10*0a6a1f1dSLionel Sambuc #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H
11*0a6a1f1dSLionel Sambuc #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H
12*0a6a1f1dSLionel Sambuc 
13*0a6a1f1dSLionel Sambuc #include "../RuntimeDyldMachO.h"
14*0a6a1f1dSLionel Sambuc 
15*0a6a1f1dSLionel Sambuc #define DEBUG_TYPE "dyld"
16*0a6a1f1dSLionel Sambuc 
17*0a6a1f1dSLionel Sambuc namespace llvm {
18*0a6a1f1dSLionel Sambuc 
19*0a6a1f1dSLionel Sambuc class RuntimeDyldMachOI386
20*0a6a1f1dSLionel Sambuc     : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> {
21*0a6a1f1dSLionel Sambuc public:
22*0a6a1f1dSLionel Sambuc 
23*0a6a1f1dSLionel Sambuc   typedef uint32_t TargetPtrT;
24*0a6a1f1dSLionel Sambuc 
RuntimeDyldMachOI386(RTDyldMemoryManager * MM)25*0a6a1f1dSLionel Sambuc   RuntimeDyldMachOI386(RTDyldMemoryManager *MM)
26*0a6a1f1dSLionel Sambuc       : RuntimeDyldMachOCRTPBase(MM) {}
27*0a6a1f1dSLionel Sambuc 
getMaxStubSize()28*0a6a1f1dSLionel Sambuc   unsigned getMaxStubSize() override { return 0; }
29*0a6a1f1dSLionel Sambuc 
getStubAlignment()30*0a6a1f1dSLionel Sambuc   unsigned getStubAlignment() override { return 1; }
31*0a6a1f1dSLionel Sambuc 
32*0a6a1f1dSLionel Sambuc   relocation_iterator
processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)33*0a6a1f1dSLionel Sambuc   processRelocationRef(unsigned SectionID, relocation_iterator RelI,
34*0a6a1f1dSLionel Sambuc                        const ObjectFile &BaseObjT,
35*0a6a1f1dSLionel Sambuc                        ObjSectionToIDMap &ObjSectionToID,
36*0a6a1f1dSLionel Sambuc                        StubMap &Stubs) override {
37*0a6a1f1dSLionel Sambuc     const MachOObjectFile &Obj =
38*0a6a1f1dSLionel Sambuc         static_cast<const MachOObjectFile &>(BaseObjT);
39*0a6a1f1dSLionel Sambuc     MachO::any_relocation_info RelInfo =
40*0a6a1f1dSLionel Sambuc         Obj.getRelocation(RelI->getRawDataRefImpl());
41*0a6a1f1dSLionel Sambuc     uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
42*0a6a1f1dSLionel Sambuc 
43*0a6a1f1dSLionel Sambuc     if (Obj.isRelocationScattered(RelInfo)) {
44*0a6a1f1dSLionel Sambuc       if (RelType == MachO::GENERIC_RELOC_SECTDIFF ||
45*0a6a1f1dSLionel Sambuc           RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)
46*0a6a1f1dSLionel Sambuc         return processSECTDIFFRelocation(SectionID, RelI, Obj,
47*0a6a1f1dSLionel Sambuc                                          ObjSectionToID);
48*0a6a1f1dSLionel Sambuc       else if (RelType == MachO::GENERIC_RELOC_VANILLA)
49*0a6a1f1dSLionel Sambuc         return processI386ScatteredVANILLA(SectionID, RelI, Obj,
50*0a6a1f1dSLionel Sambuc                                            ObjSectionToID);
51*0a6a1f1dSLionel Sambuc       llvm_unreachable("Unhandled scattered relocation.");
52*0a6a1f1dSLionel Sambuc     }
53*0a6a1f1dSLionel Sambuc 
54*0a6a1f1dSLionel Sambuc     RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
55*0a6a1f1dSLionel Sambuc     RE.Addend = memcpyAddend(RE);
56*0a6a1f1dSLionel Sambuc     RelocationValueRef Value(
57*0a6a1f1dSLionel Sambuc         getRelocationValueRef(Obj, RelI, RE, ObjSectionToID));
58*0a6a1f1dSLionel Sambuc 
59*0a6a1f1dSLionel Sambuc     // Addends for external, PC-rel relocations on i386 point back to the zero
60*0a6a1f1dSLionel Sambuc     // offset. Calculate the final offset from the relocation target instead.
61*0a6a1f1dSLionel Sambuc     // This allows us to use the same logic for both external and internal
62*0a6a1f1dSLionel Sambuc     // relocations in resolveI386RelocationRef.
63*0a6a1f1dSLionel Sambuc     // bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
64*0a6a1f1dSLionel Sambuc     // if (IsExtern && RE.IsPCRel) {
65*0a6a1f1dSLionel Sambuc     //   uint64_t RelocAddr = 0;
66*0a6a1f1dSLionel Sambuc     //   RelI->getAddress(RelocAddr);
67*0a6a1f1dSLionel Sambuc     //   Value.Addend += RelocAddr + 4;
68*0a6a1f1dSLionel Sambuc     // }
69*0a6a1f1dSLionel Sambuc     if (RE.IsPCRel)
70*0a6a1f1dSLionel Sambuc       makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size);
71*0a6a1f1dSLionel Sambuc 
72*0a6a1f1dSLionel Sambuc     RE.Addend = Value.Offset;
73*0a6a1f1dSLionel Sambuc 
74*0a6a1f1dSLionel Sambuc     if (Value.SymbolName)
75*0a6a1f1dSLionel Sambuc       addRelocationForSymbol(RE, Value.SymbolName);
76*0a6a1f1dSLionel Sambuc     else
77*0a6a1f1dSLionel Sambuc       addRelocationForSection(RE, Value.SectionID);
78*0a6a1f1dSLionel Sambuc 
79*0a6a1f1dSLionel Sambuc     return ++RelI;
80*0a6a1f1dSLionel Sambuc   }
81*0a6a1f1dSLionel Sambuc 
resolveRelocation(const RelocationEntry & RE,uint64_t Value)82*0a6a1f1dSLionel Sambuc   void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
83*0a6a1f1dSLionel Sambuc     DEBUG(dumpRelocationToResolve(RE, Value));
84*0a6a1f1dSLionel Sambuc 
85*0a6a1f1dSLionel Sambuc     const SectionEntry &Section = Sections[RE.SectionID];
86*0a6a1f1dSLionel Sambuc     uint8_t *LocalAddress = Section.Address + RE.Offset;
87*0a6a1f1dSLionel Sambuc 
88*0a6a1f1dSLionel Sambuc     if (RE.IsPCRel) {
89*0a6a1f1dSLionel Sambuc       uint64_t FinalAddress = Section.LoadAddress + RE.Offset;
90*0a6a1f1dSLionel Sambuc       Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation.
91*0a6a1f1dSLionel Sambuc     }
92*0a6a1f1dSLionel Sambuc 
93*0a6a1f1dSLionel Sambuc     switch (RE.RelType) {
94*0a6a1f1dSLionel Sambuc     default:
95*0a6a1f1dSLionel Sambuc       llvm_unreachable("Invalid relocation type!");
96*0a6a1f1dSLionel Sambuc     case MachO::GENERIC_RELOC_VANILLA:
97*0a6a1f1dSLionel Sambuc       writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size);
98*0a6a1f1dSLionel Sambuc       break;
99*0a6a1f1dSLionel Sambuc     case MachO::GENERIC_RELOC_SECTDIFF:
100*0a6a1f1dSLionel Sambuc     case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
101*0a6a1f1dSLionel Sambuc       uint64_t SectionABase = Sections[RE.Sections.SectionA].LoadAddress;
102*0a6a1f1dSLionel Sambuc       uint64_t SectionBBase = Sections[RE.Sections.SectionB].LoadAddress;
103*0a6a1f1dSLionel Sambuc       assert((Value == SectionABase || Value == SectionBBase) &&
104*0a6a1f1dSLionel Sambuc              "Unexpected SECTDIFF relocation value.");
105*0a6a1f1dSLionel Sambuc       Value = SectionABase - SectionBBase + RE.Addend;
106*0a6a1f1dSLionel Sambuc       writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size);
107*0a6a1f1dSLionel Sambuc       break;
108*0a6a1f1dSLionel Sambuc     }
109*0a6a1f1dSLionel Sambuc     case MachO::GENERIC_RELOC_PB_LA_PTR:
110*0a6a1f1dSLionel Sambuc       Error("Relocation type not implemented yet!");
111*0a6a1f1dSLionel Sambuc     }
112*0a6a1f1dSLionel Sambuc   }
113*0a6a1f1dSLionel Sambuc 
finalizeSection(const ObjectFile & Obj,unsigned SectionID,const SectionRef & Section)114*0a6a1f1dSLionel Sambuc   void finalizeSection(const ObjectFile &Obj, unsigned SectionID,
115*0a6a1f1dSLionel Sambuc                        const SectionRef &Section) {
116*0a6a1f1dSLionel Sambuc     StringRef Name;
117*0a6a1f1dSLionel Sambuc     Section.getName(Name);
118*0a6a1f1dSLionel Sambuc 
119*0a6a1f1dSLionel Sambuc     if (Name == "__jump_table")
120*0a6a1f1dSLionel Sambuc       populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID);
121*0a6a1f1dSLionel Sambuc     else if (Name == "__pointers")
122*0a6a1f1dSLionel Sambuc       populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj),
123*0a6a1f1dSLionel Sambuc                                             Section, SectionID);
124*0a6a1f1dSLionel Sambuc   }
125*0a6a1f1dSLionel Sambuc 
126*0a6a1f1dSLionel Sambuc private:
127*0a6a1f1dSLionel Sambuc   relocation_iterator
processSECTDIFFRelocation(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,ObjSectionToIDMap & ObjSectionToID)128*0a6a1f1dSLionel Sambuc   processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
129*0a6a1f1dSLionel Sambuc                             const ObjectFile &BaseObjT,
130*0a6a1f1dSLionel Sambuc                             ObjSectionToIDMap &ObjSectionToID) {
131*0a6a1f1dSLionel Sambuc     const MachOObjectFile &Obj =
132*0a6a1f1dSLionel Sambuc         static_cast<const MachOObjectFile&>(BaseObjT);
133*0a6a1f1dSLionel Sambuc     MachO::any_relocation_info RE =
134*0a6a1f1dSLionel Sambuc         Obj.getRelocation(RelI->getRawDataRefImpl());
135*0a6a1f1dSLionel Sambuc 
136*0a6a1f1dSLionel Sambuc     SectionEntry &Section = Sections[SectionID];
137*0a6a1f1dSLionel Sambuc     uint32_t RelocType = Obj.getAnyRelocationType(RE);
138*0a6a1f1dSLionel Sambuc     bool IsPCRel = Obj.getAnyRelocationPCRel(RE);
139*0a6a1f1dSLionel Sambuc     unsigned Size = Obj.getAnyRelocationLength(RE);
140*0a6a1f1dSLionel Sambuc     uint64_t Offset;
141*0a6a1f1dSLionel Sambuc     RelI->getOffset(Offset);
142*0a6a1f1dSLionel Sambuc     uint8_t *LocalAddress = Section.Address + Offset;
143*0a6a1f1dSLionel Sambuc     unsigned NumBytes = 1 << Size;
144*0a6a1f1dSLionel Sambuc     uint64_t Addend = readBytesUnaligned(LocalAddress, NumBytes);
145*0a6a1f1dSLionel Sambuc 
146*0a6a1f1dSLionel Sambuc     ++RelI;
147*0a6a1f1dSLionel Sambuc     MachO::any_relocation_info RE2 =
148*0a6a1f1dSLionel Sambuc         Obj.getRelocation(RelI->getRawDataRefImpl());
149*0a6a1f1dSLionel Sambuc 
150*0a6a1f1dSLionel Sambuc     uint32_t AddrA = Obj.getScatteredRelocationValue(RE);
151*0a6a1f1dSLionel Sambuc     section_iterator SAI = getSectionByAddress(Obj, AddrA);
152*0a6a1f1dSLionel Sambuc     assert(SAI != Obj.section_end() && "Can't find section for address A");
153*0a6a1f1dSLionel Sambuc     uint64_t SectionABase = SAI->getAddress();
154*0a6a1f1dSLionel Sambuc     uint64_t SectionAOffset = AddrA - SectionABase;
155*0a6a1f1dSLionel Sambuc     SectionRef SectionA = *SAI;
156*0a6a1f1dSLionel Sambuc     bool IsCode = SectionA.isText();
157*0a6a1f1dSLionel Sambuc     uint32_t SectionAID =
158*0a6a1f1dSLionel Sambuc         findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID);
159*0a6a1f1dSLionel Sambuc 
160*0a6a1f1dSLionel Sambuc     uint32_t AddrB = Obj.getScatteredRelocationValue(RE2);
161*0a6a1f1dSLionel Sambuc     section_iterator SBI = getSectionByAddress(Obj, AddrB);
162*0a6a1f1dSLionel Sambuc     assert(SBI != Obj.section_end() && "Can't find section for address B");
163*0a6a1f1dSLionel Sambuc     uint64_t SectionBBase = SBI->getAddress();
164*0a6a1f1dSLionel Sambuc     uint64_t SectionBOffset = AddrB - SectionBBase;
165*0a6a1f1dSLionel Sambuc     SectionRef SectionB = *SBI;
166*0a6a1f1dSLionel Sambuc     uint32_t SectionBID =
167*0a6a1f1dSLionel Sambuc         findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID);
168*0a6a1f1dSLionel Sambuc 
169*0a6a1f1dSLionel Sambuc     if (Addend != AddrA - AddrB)
170*0a6a1f1dSLionel Sambuc       Error("Unexpected SECTDIFF relocation addend.");
171*0a6a1f1dSLionel Sambuc 
172*0a6a1f1dSLionel Sambuc     DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB
173*0a6a1f1dSLionel Sambuc                  << ", Addend: " << Addend << ", SectionA ID: " << SectionAID
174*0a6a1f1dSLionel Sambuc                  << ", SectionAOffset: " << SectionAOffset
175*0a6a1f1dSLionel Sambuc                  << ", SectionB ID: " << SectionBID
176*0a6a1f1dSLionel Sambuc                  << ", SectionBOffset: " << SectionBOffset << "\n");
177*0a6a1f1dSLionel Sambuc     RelocationEntry R(SectionID, Offset, RelocType, 0, SectionAID,
178*0a6a1f1dSLionel Sambuc                       SectionAOffset, SectionBID, SectionBOffset, IsPCRel,
179*0a6a1f1dSLionel Sambuc                       Size);
180*0a6a1f1dSLionel Sambuc 
181*0a6a1f1dSLionel Sambuc     addRelocationForSection(R, SectionAID);
182*0a6a1f1dSLionel Sambuc     addRelocationForSection(R, SectionBID);
183*0a6a1f1dSLionel Sambuc 
184*0a6a1f1dSLionel Sambuc     return ++RelI;
185*0a6a1f1dSLionel Sambuc   }
186*0a6a1f1dSLionel Sambuc 
processI386ScatteredVANILLA(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,RuntimeDyldMachO::ObjSectionToIDMap & ObjSectionToID)187*0a6a1f1dSLionel Sambuc   relocation_iterator processI386ScatteredVANILLA(
188*0a6a1f1dSLionel Sambuc       unsigned SectionID, relocation_iterator RelI,
189*0a6a1f1dSLionel Sambuc       const ObjectFile &BaseObjT,
190*0a6a1f1dSLionel Sambuc       RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) {
191*0a6a1f1dSLionel Sambuc     const MachOObjectFile &Obj =
192*0a6a1f1dSLionel Sambuc         static_cast<const MachOObjectFile&>(BaseObjT);
193*0a6a1f1dSLionel Sambuc     MachO::any_relocation_info RE =
194*0a6a1f1dSLionel Sambuc         Obj.getRelocation(RelI->getRawDataRefImpl());
195*0a6a1f1dSLionel Sambuc 
196*0a6a1f1dSLionel Sambuc     SectionEntry &Section = Sections[SectionID];
197*0a6a1f1dSLionel Sambuc     uint32_t RelocType = Obj.getAnyRelocationType(RE);
198*0a6a1f1dSLionel Sambuc     bool IsPCRel = Obj.getAnyRelocationPCRel(RE);
199*0a6a1f1dSLionel Sambuc     unsigned Size = Obj.getAnyRelocationLength(RE);
200*0a6a1f1dSLionel Sambuc     uint64_t Offset;
201*0a6a1f1dSLionel Sambuc     RelI->getOffset(Offset);
202*0a6a1f1dSLionel Sambuc     uint8_t *LocalAddress = Section.Address + Offset;
203*0a6a1f1dSLionel Sambuc     unsigned NumBytes = 1 << Size;
204*0a6a1f1dSLionel Sambuc     int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes);
205*0a6a1f1dSLionel Sambuc 
206*0a6a1f1dSLionel Sambuc     unsigned SymbolBaseAddr = Obj.getScatteredRelocationValue(RE);
207*0a6a1f1dSLionel Sambuc     section_iterator TargetSI = getSectionByAddress(Obj, SymbolBaseAddr);
208*0a6a1f1dSLionel Sambuc     assert(TargetSI != Obj.section_end() && "Can't find section for symbol");
209*0a6a1f1dSLionel Sambuc     uint64_t SectionBaseAddr = TargetSI->getAddress();
210*0a6a1f1dSLionel Sambuc     SectionRef TargetSection = *TargetSI;
211*0a6a1f1dSLionel Sambuc     bool IsCode = TargetSection.isText();
212*0a6a1f1dSLionel Sambuc     uint32_t TargetSectionID =
213*0a6a1f1dSLionel Sambuc         findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID);
214*0a6a1f1dSLionel Sambuc 
215*0a6a1f1dSLionel Sambuc     Addend -= SectionBaseAddr;
216*0a6a1f1dSLionel Sambuc     RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size);
217*0a6a1f1dSLionel Sambuc 
218*0a6a1f1dSLionel Sambuc     addRelocationForSection(R, TargetSectionID);
219*0a6a1f1dSLionel Sambuc 
220*0a6a1f1dSLionel Sambuc     return ++RelI;
221*0a6a1f1dSLionel Sambuc   }
222*0a6a1f1dSLionel Sambuc 
223*0a6a1f1dSLionel Sambuc   // Populate stubs in __jump_table section.
populateJumpTable(const MachOObjectFile & Obj,const SectionRef & JTSection,unsigned JTSectionID)224*0a6a1f1dSLionel Sambuc   void populateJumpTable(const MachOObjectFile &Obj, const SectionRef &JTSection,
225*0a6a1f1dSLionel Sambuc                          unsigned JTSectionID) {
226*0a6a1f1dSLionel Sambuc     assert(!Obj.is64Bit() &&
227*0a6a1f1dSLionel Sambuc            "__jump_table section not supported in 64-bit MachO.");
228*0a6a1f1dSLionel Sambuc 
229*0a6a1f1dSLionel Sambuc     MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
230*0a6a1f1dSLionel Sambuc     MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl());
231*0a6a1f1dSLionel Sambuc     uint32_t JTSectionSize = Sec32.size;
232*0a6a1f1dSLionel Sambuc     unsigned FirstIndirectSymbol = Sec32.reserved1;
233*0a6a1f1dSLionel Sambuc     unsigned JTEntrySize = Sec32.reserved2;
234*0a6a1f1dSLionel Sambuc     unsigned NumJTEntries = JTSectionSize / JTEntrySize;
235*0a6a1f1dSLionel Sambuc     uint8_t *JTSectionAddr = getSectionAddress(JTSectionID);
236*0a6a1f1dSLionel Sambuc     unsigned JTEntryOffset = 0;
237*0a6a1f1dSLionel Sambuc 
238*0a6a1f1dSLionel Sambuc     assert((JTSectionSize % JTEntrySize) == 0 &&
239*0a6a1f1dSLionel Sambuc            "Jump-table section does not contain a whole number of stubs?");
240*0a6a1f1dSLionel Sambuc 
241*0a6a1f1dSLionel Sambuc     for (unsigned i = 0; i < NumJTEntries; ++i) {
242*0a6a1f1dSLionel Sambuc       unsigned SymbolIndex =
243*0a6a1f1dSLionel Sambuc           Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
244*0a6a1f1dSLionel Sambuc       symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
245*0a6a1f1dSLionel Sambuc       StringRef IndirectSymbolName;
246*0a6a1f1dSLionel Sambuc       SI->getName(IndirectSymbolName);
247*0a6a1f1dSLionel Sambuc       uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset;
248*0a6a1f1dSLionel Sambuc       createStubFunction(JTEntryAddr);
249*0a6a1f1dSLionel Sambuc       RelocationEntry RE(JTSectionID, JTEntryOffset + 1,
250*0a6a1f1dSLionel Sambuc                          MachO::GENERIC_RELOC_VANILLA, 0, true, 2);
251*0a6a1f1dSLionel Sambuc       addRelocationForSymbol(RE, IndirectSymbolName);
252*0a6a1f1dSLionel Sambuc       JTEntryOffset += JTEntrySize;
253*0a6a1f1dSLionel Sambuc     }
254*0a6a1f1dSLionel Sambuc   }
255*0a6a1f1dSLionel Sambuc 
256*0a6a1f1dSLionel Sambuc };
257*0a6a1f1dSLionel Sambuc }
258*0a6a1f1dSLionel Sambuc 
259*0a6a1f1dSLionel Sambuc #undef DEBUG_TYPE
260*0a6a1f1dSLionel Sambuc 
261*0a6a1f1dSLionel Sambuc #endif
262