RuntimeDyldMachOI386.h revision 274955
1//===---- RuntimeDyldMachOI386.h ---- MachO/I386 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_RUNTIMEDYLDMACHOI386_H 11#define LLVM_RUNTIMEDYLDMACHOI386_H 12 13#include "../RuntimeDyldMachO.h" 14 15#define DEBUG_TYPE "dyld" 16 17namespace llvm { 18 19class RuntimeDyldMachOI386 20 : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> { 21public: 22 RuntimeDyldMachOI386(RTDyldMemoryManager *MM) 23 : RuntimeDyldMachOCRTPBase(MM) {} 24 25 unsigned getMaxStubSize() override { return 0; } 26 27 unsigned getStubAlignment() override { return 1; } 28 29 relocation_iterator 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); 38 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, 43 ObjSectionToID); 44 else if (Arch == Triple::x86 && RelType == MachO::GENERIC_RELOC_VANILLA) 45 return processI386ScatteredVANILLA(SectionID, RelI, ObjImg, 46 ObjSectionToID); 47 llvm_unreachable("Unhandled scattered relocation."); 48 } 49 50 RelocationEntry RE(getBasicRelocationEntry(SectionID, ObjImg, RelI)); 51 RelocationValueRef Value( 52 getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); 53 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; 63 // } 64 if (RE.IsPCRel) 65 makeValueAddendPCRel(Value, ObjImg, RelI); 66 67 RE.Addend = Value.Addend; 68 69 if (Value.SymbolName) 70 addRelocationForSymbol(RE, Value.SymbolName); 71 else 72 addRelocationForSection(RE, Value.SectionID); 73 74 return ++RelI; 75 } 76 77 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) { 78 DEBUG(dumpRelocationToResolve(RE, Value)); 79 80 const SectionEntry &Section = Sections[RE.SectionID]; 81 uint8_t *LocalAddress = Section.Address + RE.Offset; 82 83 if (RE.IsPCRel) { 84 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 85 Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation. 86 } 87 88 switch (RE.RelType) { 89 default: 90 llvm_unreachable("Invalid relocation type!"); 91 case MachO::GENERIC_RELOC_VANILLA: 92 writeBytesUnaligned(LocalAddress, Value + RE.Addend, 1 << RE.Size); 93 break; 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); 102 break; 103 } 104 case MachO::GENERIC_RELOC_PB_LA_PTR: 105 Error("Relocation type not implemented yet!"); 106 } 107 } 108 109 void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, 110 const SectionRef &Section) { 111 StringRef Name; 112 Section.getName(Name); 113 114 if (Name == "__jump_table") 115 populateJumpTable(cast<MachOObjectFile>(*ObjImg.getObjectFile()), Section, 116 SectionID); 117 else if (Name == "__pointers") 118 populatePointersSection(cast<MachOObjectFile>(*ObjImg.getObjectFile()), 119 Section, SectionID); 120 } 121 122private: 123 relocation_iterator 124 processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, 125 ObjectImage &Obj, 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()); 131 132 SectionEntry &Section = Sections[SectionID]; 133 uint32_t RelocType = MachO->getAnyRelocationType(RE); 134 bool IsPCRel = MachO->getAnyRelocationPCRel(RE); 135 unsigned Size = MachO->getAnyRelocationLength(RE); 136 uint64_t Offset; 137 RelI->getOffset(Offset); 138 uint8_t *LocalAddress = Section.Address + Offset; 139 unsigned NumBytes = 1 << Size; 140 int64_t Addend = 0; 141 memcpy(&Addend, LocalAddress, NumBytes); 142 143 ++RelI; 144 MachO::any_relocation_info RE2 = 145 MachO->getRelocation(RelI->getRawDataRefImpl()); 146 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; 154 bool IsCode; 155 SectionA.isText(IsCode); 156 uint32_t SectionAID = 157 findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID); 158 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); 168 169 if (Addend != AddrA - AddrB) 170 Error("Unexpected SECTDIFF relocation addend."); 171 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, 179 Size); 180 181 addRelocationForSection(R, SectionAID); 182 addRelocationForSection(R, SectionBID); 183 184 return ++RelI; 185 } 186 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()); 194 195 SectionEntry &Section = Sections[SectionID]; 196 uint32_t RelocType = MachO->getAnyRelocationType(RE); 197 bool IsPCRel = MachO->getAnyRelocationPCRel(RE); 198 unsigned Size = MachO->getAnyRelocationLength(RE); 199 uint64_t Offset; 200 RelI->getOffset(Offset); 201 uint8_t *LocalAddress = Section.Address + Offset; 202 unsigned NumBytes = 1 << Size; 203 int64_t Addend = 0; 204 memcpy(&Addend, LocalAddress, NumBytes); 205 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; 212 bool IsCode; 213 TargetSection.isText(IsCode); 214 uint32_t TargetSectionID = 215 findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID); 216 217 Addend -= SectionBaseAddr; 218 RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size); 219 220 addRelocationForSection(R, TargetSectionID); 221 222 return ++RelI; 223 } 224 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."); 230 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; 239 240 assert((JTSectionSize % JTEntrySize) == 0 && 241 "Jump-table section does not contain a whole number of stubs?"); 242 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; 255 } 256 } 257 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."); 264 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; 272 273 assert((PTSectionSize % PTEntrySize) == 0 && 274 "Pointers section does not contain a whole number of stubs?"); 275 276 DEBUG(dbgs() << "Populating __pointers, Section ID " << PTSectionID << ", " 277 << NumPTEntries << " entries, " << PTEntrySize 278 << " bytes each:\n"); 279 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; 292 } 293 } 294 295 static section_iterator getSectionByAddress(const MachOObjectFile &Obj, 296 uint64_t Addr) { 297 section_iterator SI = Obj.section_begin(); 298 section_iterator SE = Obj.section_end(); 299 300 for (; SI != SE; ++SI) { 301 uint64_t SAddr, SSize; 302 SI->getAddress(SAddr); 303 SI->getSize(SSize); 304 if ((Addr >= SAddr) && (Addr < SAddr + SSize)) 305 return SI; 306 } 307 308 return SE; 309 } 310}; 311} 312 313#undef DEBUG_TYPE 314 315#endif // LLVM_RUNTIMEDYLDMACHOI386_H 316