1 //===--- RuntimeDyldCOFFI386.h --- COFF/X86_64 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 // COFF x86 support for MC-JIT runtime dynamic linker. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H 15 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H 16 17 #include "../RuntimeDyldCOFF.h" 18 #include "llvm/BinaryFormat/COFF.h" 19 #include "llvm/Object/COFF.h" 20 21 #define DEBUG_TYPE "dyld" 22 23 namespace llvm { 24 25 class RuntimeDyldCOFFI386 : public RuntimeDyldCOFF { 26 public: RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager & MM,JITSymbolResolver & Resolver)27 RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM, 28 JITSymbolResolver &Resolver) 29 : RuntimeDyldCOFF(MM, Resolver) {} 30 getMaxStubSize()31 unsigned getMaxStubSize() override { 32 return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad 33 } 34 getStubAlignment()35 unsigned getStubAlignment() override { return 1; } 36 37 Expected<relocation_iterator> processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & Obj,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)38 processRelocationRef(unsigned SectionID, 39 relocation_iterator RelI, 40 const ObjectFile &Obj, 41 ObjSectionToIDMap &ObjSectionToID, 42 StubMap &Stubs) override { 43 44 auto Symbol = RelI->getSymbol(); 45 if (Symbol == Obj.symbol_end()) 46 report_fatal_error("Unknown symbol in relocation"); 47 48 Expected<StringRef> TargetNameOrErr = Symbol->getName(); 49 if (!TargetNameOrErr) 50 return TargetNameOrErr.takeError(); 51 StringRef TargetName = *TargetNameOrErr; 52 53 auto SectionOrErr = Symbol->getSection(); 54 if (!SectionOrErr) 55 return SectionOrErr.takeError(); 56 auto Section = *SectionOrErr; 57 58 uint64_t RelType = RelI->getType(); 59 uint64_t Offset = RelI->getOffset(); 60 61 // Determine the Addend used to adjust the relocation value. 62 uint64_t Addend = 0; 63 SectionEntry &AddendSection = Sections[SectionID]; 64 uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset; 65 uint8_t *Displacement = (uint8_t *)ObjTarget; 66 67 switch (RelType) { 68 case COFF::IMAGE_REL_I386_DIR32: 69 case COFF::IMAGE_REL_I386_DIR32NB: 70 case COFF::IMAGE_REL_I386_SECREL: 71 case COFF::IMAGE_REL_I386_REL32: { 72 Addend = readBytesUnaligned(Displacement, 4); 73 break; 74 } 75 default: 76 break; 77 } 78 79 #if !defined(NDEBUG) 80 SmallString<32> RelTypeName; 81 RelI->getTypeName(RelTypeName); 82 #endif 83 LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset 84 << " RelType: " << RelTypeName << " TargetName: " 85 << TargetName << " Addend " << Addend << "\n"); 86 87 unsigned TargetSectionID = -1; 88 if (Section == Obj.section_end()) { 89 RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0); 90 addRelocationForSymbol(RE, TargetName); 91 } else { 92 if (auto TargetSectionIDOrErr = 93 findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID)) 94 TargetSectionID = *TargetSectionIDOrErr; 95 else 96 return TargetSectionIDOrErr.takeError(); 97 98 switch (RelType) { 99 case COFF::IMAGE_REL_I386_ABSOLUTE: 100 // This relocation is ignored. 101 break; 102 case COFF::IMAGE_REL_I386_DIR32: 103 case COFF::IMAGE_REL_I386_DIR32NB: 104 case COFF::IMAGE_REL_I386_REL32: { 105 RelocationEntry RE = 106 RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID, 107 getSymbolOffset(*Symbol), 0, 0, false, 0); 108 addRelocationForSection(RE, TargetSectionID); 109 break; 110 } 111 case COFF::IMAGE_REL_I386_SECTION: { 112 RelocationEntry RE = 113 RelocationEntry(TargetSectionID, Offset, RelType, 0); 114 addRelocationForSection(RE, TargetSectionID); 115 break; 116 } 117 case COFF::IMAGE_REL_I386_SECREL: { 118 RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, 119 getSymbolOffset(*Symbol) + Addend); 120 addRelocationForSection(RE, TargetSectionID); 121 break; 122 } 123 default: 124 llvm_unreachable("unsupported relocation type"); 125 } 126 127 } 128 129 return ++RelI; 130 } 131 resolveRelocation(const RelocationEntry & RE,uint64_t Value)132 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 133 const auto Section = Sections[RE.SectionID]; 134 uint8_t *Target = Section.getAddressWithOffset(RE.Offset); 135 136 switch (RE.RelType) { 137 case COFF::IMAGE_REL_I386_ABSOLUTE: 138 // This relocation is ignored. 139 break; 140 case COFF::IMAGE_REL_I386_DIR32: { 141 // The target's 32-bit VA. 142 uint64_t Result = 143 RE.Sections.SectionA == static_cast<uint32_t>(-1) 144 ? Value 145 : Sections[RE.Sections.SectionA].getLoadAddressWithOffset( 146 RE.Addend); 147 assert(Result <= UINT32_MAX && "relocation overflow"); 148 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 149 << " RelType: IMAGE_REL_I386_DIR32" 150 << " TargetSection: " << RE.Sections.SectionA 151 << " Value: " << format("0x%08" PRIx32, Result) 152 << '\n'); 153 writeBytesUnaligned(Result, Target, 4); 154 break; 155 } 156 case COFF::IMAGE_REL_I386_DIR32NB: { 157 // The target's 32-bit RVA. 158 // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase 159 uint64_t Result = 160 Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend) - 161 Sections[0].getLoadAddress(); 162 assert(Result <= UINT32_MAX && "relocation overflow"); 163 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 164 << " RelType: IMAGE_REL_I386_DIR32NB" 165 << " TargetSection: " << RE.Sections.SectionA 166 << " Value: " << format("0x%08" PRIx32, Result) 167 << '\n'); 168 writeBytesUnaligned(Result, Target, 4); 169 break; 170 } 171 case COFF::IMAGE_REL_I386_REL32: { 172 // 32-bit relative displacement to the target. 173 uint64_t Result = RE.Sections.SectionA == static_cast<uint32_t>(-1) 174 ? Value 175 : Sections[RE.Sections.SectionA].getLoadAddress(); 176 Result = Result - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset; 177 assert(static_cast<int64_t>(Result) <= INT32_MAX && 178 "relocation overflow"); 179 assert(static_cast<int64_t>(Result) >= INT32_MIN && 180 "relocation underflow"); 181 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 182 << " RelType: IMAGE_REL_I386_REL32" 183 << " TargetSection: " << RE.Sections.SectionA 184 << " Value: " << format("0x%08" PRIx32, Result) 185 << '\n'); 186 writeBytesUnaligned(Result, Target, 4); 187 break; 188 } 189 case COFF::IMAGE_REL_I386_SECTION: 190 // 16-bit section index of the section that contains the target. 191 assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX && 192 "relocation overflow"); 193 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 194 << " RelType: IMAGE_REL_I386_SECTION Value: " 195 << RE.SectionID << '\n'); 196 writeBytesUnaligned(RE.SectionID, Target, 2); 197 break; 198 case COFF::IMAGE_REL_I386_SECREL: 199 // 32-bit offset of the target from the beginning of its section. 200 assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX && 201 "relocation overflow"); 202 LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 203 << " RelType: IMAGE_REL_I386_SECREL Value: " 204 << RE.Addend << '\n'); 205 writeBytesUnaligned(RE.Addend, Target, 4); 206 break; 207 default: 208 llvm_unreachable("unsupported relocation type"); 209 } 210 } 211 registerEHFrames()212 void registerEHFrames() override {} 213 }; 214 215 } 216 217 #endif 218 219