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