1 //===---- RuntimeDyldMachOI386.h ---- MachO/I386 specific code. ---*- C++ -*-=//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_RUNTIMEDYLDMACHOI386_H
11 #define LLVM_RUNTIMEDYLDMACHOI386_H
13 #include "../RuntimeDyldMachO.h"
15 #define DEBUG_TYPE "dyld"
19 class RuntimeDyldMachOI386
20 : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> {
22 RuntimeDyldMachOI386(RTDyldMemoryManager *MM)
23 : RuntimeDyldMachOCRTPBase(MM) {}
25 unsigned getMaxStubSize() override { return 0; }
27 unsigned getStubAlignment() override { return 1; }
30 processRelocationRef(unsigned SectionID, relocation_iterator RelI,
31 ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID,
32 const SymbolTableMap &Symbols, StubMap &Stubs) override {
33 const MachOObjectFile &Obj =
34 static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile());
35 MachO::any_relocation_info RelInfo =
36 Obj.getRelocation(RelI->getRawDataRefImpl());
37 uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
39 if (Obj.isRelocationScattered(RelInfo)) {
40 if (RelType == MachO::GENERIC_RELOC_SECTDIFF ||
41 RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)
42 return processSECTDIFFRelocation(SectionID, RelI, ObjImg,
44 else if (Arch == Triple::x86 && RelType == MachO::GENERIC_RELOC_VANILLA)
45 return processI386ScatteredVANILLA(SectionID, RelI, ObjImg,
47 llvm_unreachable("Unhandled scattered relocation.");
50 RelocationEntry RE(getBasicRelocationEntry(SectionID, ObjImg, RelI));
51 RelocationValueRef Value(
52 getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols));
54 // Addends for external, PC-rel relocations on i386 point back to the zero
55 // offset. Calculate the final offset from the relocation target instead.
56 // This allows us to use the same logic for both external and internal
57 // relocations in resolveI386RelocationRef.
58 // bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
59 // if (IsExtern && RE.IsPCRel) {
60 // uint64_t RelocAddr = 0;
61 // RelI->getAddress(RelocAddr);
62 // Value.Addend += RelocAddr + 4;
65 makeValueAddendPCRel(Value, ObjImg, RelI);
67 RE.Addend = Value.Addend;
70 addRelocationForSymbol(RE, Value.SymbolName);
72 addRelocationForSection(RE, Value.SectionID);
77 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) {
78 DEBUG(dumpRelocationToResolve(RE, Value));
80 const SectionEntry &Section = Sections[RE.SectionID];
81 uint8_t *LocalAddress = Section.Address + RE.Offset;
84 uint64_t FinalAddress = Section.LoadAddress + RE.Offset;
85 Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation.
90 llvm_unreachable("Invalid relocation type!");
91 case MachO::GENERIC_RELOC_VANILLA:
92 writeBytesUnaligned(LocalAddress, Value + RE.Addend, 1 << RE.Size);
94 case MachO::GENERIC_RELOC_SECTDIFF:
95 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
96 uint64_t SectionABase = Sections[RE.Sections.SectionA].LoadAddress;
97 uint64_t SectionBBase = Sections[RE.Sections.SectionB].LoadAddress;
98 assert((Value == SectionABase || Value == SectionBBase) &&
99 "Unexpected SECTDIFF relocation value.");
100 Value = SectionABase - SectionBBase + RE.Addend;
101 writeBytesUnaligned(LocalAddress, Value, 1 << RE.Size);
104 case MachO::GENERIC_RELOC_PB_LA_PTR:
105 Error("Relocation type not implemented yet!");
109 void finalizeSection(ObjectImage &ObjImg, unsigned SectionID,
110 const SectionRef &Section) {
112 Section.getName(Name);
114 if (Name == "__jump_table")
115 populateJumpTable(cast<MachOObjectFile>(*ObjImg.getObjectFile()), Section,
117 else if (Name == "__pointers")
118 populatePointersSection(cast<MachOObjectFile>(*ObjImg.getObjectFile()),
124 processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
126 ObjSectionToIDMap &ObjSectionToID) {
127 const MachOObjectFile *MachO =
128 static_cast<const MachOObjectFile *>(Obj.getObjectFile());
129 MachO::any_relocation_info RE =
130 MachO->getRelocation(RelI->getRawDataRefImpl());
132 SectionEntry &Section = Sections[SectionID];
133 uint32_t RelocType = MachO->getAnyRelocationType(RE);
134 bool IsPCRel = MachO->getAnyRelocationPCRel(RE);
135 unsigned Size = MachO->getAnyRelocationLength(RE);
137 RelI->getOffset(Offset);
138 uint8_t *LocalAddress = Section.Address + Offset;
139 unsigned NumBytes = 1 << Size;
141 memcpy(&Addend, LocalAddress, NumBytes);
144 MachO::any_relocation_info RE2 =
145 MachO->getRelocation(RelI->getRawDataRefImpl());
147 uint32_t AddrA = MachO->getScatteredRelocationValue(RE);
148 section_iterator SAI = getSectionByAddress(*MachO, AddrA);
149 assert(SAI != MachO->section_end() && "Can't find section for address A");
150 uint64_t SectionABase;
151 SAI->getAddress(SectionABase);
152 uint64_t SectionAOffset = AddrA - SectionABase;
153 SectionRef SectionA = *SAI;
155 SectionA.isText(IsCode);
156 uint32_t SectionAID =
157 findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID);
159 uint32_t AddrB = MachO->getScatteredRelocationValue(RE2);
160 section_iterator SBI = getSectionByAddress(*MachO, AddrB);
161 assert(SBI != MachO->section_end() && "Can't find section for address B");
162 uint64_t SectionBBase;
163 SBI->getAddress(SectionBBase);
164 uint64_t SectionBOffset = AddrB - SectionBBase;
165 SectionRef SectionB = *SBI;
166 uint32_t SectionBID =
167 findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID);
169 if (Addend != AddrA - AddrB)
170 Error("Unexpected SECTDIFF relocation addend.");
172 DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB
173 << ", Addend: " << Addend << ", SectionA ID: " << SectionAID
174 << ", SectionAOffset: " << SectionAOffset
175 << ", SectionB ID: " << SectionBID
176 << ", SectionBOffset: " << SectionBOffset << "\n");
177 RelocationEntry R(SectionID, Offset, RelocType, 0, SectionAID,
178 SectionAOffset, SectionBID, SectionBOffset, IsPCRel,
181 addRelocationForSection(R, SectionAID);
182 addRelocationForSection(R, SectionBID);
187 relocation_iterator processI386ScatteredVANILLA(
188 unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj,
189 RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) {
190 const MachOObjectFile *MachO =
191 static_cast<const MachOObjectFile *>(Obj.getObjectFile());
192 MachO::any_relocation_info RE =
193 MachO->getRelocation(RelI->getRawDataRefImpl());
195 SectionEntry &Section = Sections[SectionID];
196 uint32_t RelocType = MachO->getAnyRelocationType(RE);
197 bool IsPCRel = MachO->getAnyRelocationPCRel(RE);
198 unsigned Size = MachO->getAnyRelocationLength(RE);
200 RelI->getOffset(Offset);
201 uint8_t *LocalAddress = Section.Address + Offset;
202 unsigned NumBytes = 1 << Size;
204 memcpy(&Addend, LocalAddress, NumBytes);
206 unsigned SymbolBaseAddr = MachO->getScatteredRelocationValue(RE);
207 section_iterator TargetSI = getSectionByAddress(*MachO, SymbolBaseAddr);
208 assert(TargetSI != MachO->section_end() && "Can't find section for symbol");
209 uint64_t SectionBaseAddr;
210 TargetSI->getAddress(SectionBaseAddr);
211 SectionRef TargetSection = *TargetSI;
213 TargetSection.isText(IsCode);
214 uint32_t TargetSectionID =
215 findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID);
217 Addend -= SectionBaseAddr;
218 RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size);
220 addRelocationForSection(R, TargetSectionID);
225 // Populate stubs in __jump_table section.
226 void populateJumpTable(MachOObjectFile &Obj, const SectionRef &JTSection,
227 unsigned JTSectionID) {
228 assert(!Obj.is64Bit() &&
229 "__jump_table section not supported in 64-bit MachO.");
231 MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
232 MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl());
233 uint32_t JTSectionSize = Sec32.size;
234 unsigned FirstIndirectSymbol = Sec32.reserved1;
235 unsigned JTEntrySize = Sec32.reserved2;
236 unsigned NumJTEntries = JTSectionSize / JTEntrySize;
237 uint8_t *JTSectionAddr = getSectionAddress(JTSectionID);
238 unsigned JTEntryOffset = 0;
240 assert((JTSectionSize % JTEntrySize) == 0 &&
241 "Jump-table section does not contain a whole number of stubs?");
243 for (unsigned i = 0; i < NumJTEntries; ++i) {
244 unsigned SymbolIndex =
245 Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
246 symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
247 StringRef IndirectSymbolName;
248 SI->getName(IndirectSymbolName);
249 uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset;
250 createStubFunction(JTEntryAddr);
251 RelocationEntry RE(JTSectionID, JTEntryOffset + 1,
252 MachO::GENERIC_RELOC_VANILLA, 0, true, 2);
253 addRelocationForSymbol(RE, IndirectSymbolName);
254 JTEntryOffset += JTEntrySize;
258 // Populate __pointers section.
259 void populatePointersSection(MachOObjectFile &Obj,
260 const SectionRef &PTSection,
261 unsigned PTSectionID) {
262 assert(!Obj.is64Bit() &&
263 "__pointers section not supported in 64-bit MachO.");
265 MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
266 MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl());
267 uint32_t PTSectionSize = Sec32.size;
268 unsigned FirstIndirectSymbol = Sec32.reserved1;
269 const unsigned PTEntrySize = 4;
270 unsigned NumPTEntries = PTSectionSize / PTEntrySize;
271 unsigned PTEntryOffset = 0;
273 assert((PTSectionSize % PTEntrySize) == 0 &&
274 "Pointers section does not contain a whole number of stubs?");
276 DEBUG(dbgs() << "Populating __pointers, Section ID " << PTSectionID << ", "
277 << NumPTEntries << " entries, " << PTEntrySize
278 << " bytes each:\n");
280 for (unsigned i = 0; i < NumPTEntries; ++i) {
281 unsigned SymbolIndex =
282 Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
283 symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
284 StringRef IndirectSymbolName;
285 SI->getName(IndirectSymbolName);
286 DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex
287 << ", PT offset: " << PTEntryOffset << "\n");
288 RelocationEntry RE(PTSectionID, PTEntryOffset,
289 MachO::GENERIC_RELOC_VANILLA, 0, false, 2);
290 addRelocationForSymbol(RE, IndirectSymbolName);
291 PTEntryOffset += PTEntrySize;
295 static section_iterator getSectionByAddress(const MachOObjectFile &Obj,
297 section_iterator SI = Obj.section_begin();
298 section_iterator SE = Obj.section_end();
300 for (; SI != SE; ++SI) {
301 uint64_t SAddr, SSize;
302 SI->getAddress(SAddr);
304 if ((Addr >= SAddr) && (Addr < SAddr + SSize))
315 #endif // LLVM_RUNTIMEDYLDMACHOI386_H