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 "llvm/Object/COFF.h" 18 #include "llvm/Support/COFF.h" 19 #include "../RuntimeDyldCOFF.h" 20 21 #define DEBUG_TYPE "dyld" 22 23 namespace llvm { 24 25 class RuntimeDyldCOFFI386 : public RuntimeDyldCOFF { 26 public: RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager & MM,RuntimeDyld::SymbolResolver & Resolver)27 RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM, 28 RuntimeDyld::SymbolResolver &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 DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset 84 << " RelType: " << RelTypeName << " TargetName: " << TargetName 85 << " 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(static_cast<int32_t>(Result) <= INT32_MAX && 148 "relocation overflow"); 149 assert(static_cast<int32_t>(Result) >= INT32_MIN && 150 "relocation underflow"); 151 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 152 << " RelType: IMAGE_REL_I386_DIR32" 153 << " TargetSection: " << RE.Sections.SectionA 154 << " Value: " << format("0x%08" PRIx32, Result) << '\n'); 155 writeBytesUnaligned(Result, Target, 4); 156 break; 157 } 158 case COFF::IMAGE_REL_I386_DIR32NB: { 159 // The target's 32-bit RVA. 160 // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase 161 uint64_t Result = 162 Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend) - 163 Sections[0].getLoadAddress(); 164 assert(static_cast<int32_t>(Result) <= INT32_MAX && 165 "relocation overflow"); 166 assert(static_cast<int32_t>(Result) >= INT32_MIN && 167 "relocation underflow"); 168 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 169 << " RelType: IMAGE_REL_I386_DIR32NB" 170 << " TargetSection: " << RE.Sections.SectionA 171 << " Value: " << format("0x%08" PRIx32, Result) << '\n'); 172 writeBytesUnaligned(Result, Target, 4); 173 break; 174 } 175 case COFF::IMAGE_REL_I386_REL32: { 176 // 32-bit relative displacement to the target. 177 uint64_t Result = RE.Sections.SectionA == static_cast<uint32_t>(-1) 178 ? Value 179 : Sections[RE.Sections.SectionA].getLoadAddress(); 180 Result = Result - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset; 181 assert(static_cast<int32_t>(Result) <= INT32_MAX && 182 "relocation overflow"); 183 assert(static_cast<int32_t>(Result) >= INT32_MIN && 184 "relocation underflow"); 185 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 186 << " RelType: IMAGE_REL_I386_REL32" 187 << " TargetSection: " << RE.Sections.SectionA 188 << " Value: " << format("0x%08" PRIx32, Result) << '\n'); 189 writeBytesUnaligned(Result, Target, 4); 190 break; 191 } 192 case COFF::IMAGE_REL_I386_SECTION: 193 // 16-bit section index of the section that contains the target. 194 assert(static_cast<int32_t>(RE.SectionID) <= INT16_MAX && 195 "relocation overflow"); 196 assert(static_cast<int32_t>(RE.SectionID) >= INT16_MIN && 197 "relocation underflow"); 198 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 199 << " RelType: IMAGE_REL_I386_SECTION Value: " << RE.SectionID 200 << '\n'); 201 writeBytesUnaligned(RE.SectionID, Target, 2); 202 break; 203 case COFF::IMAGE_REL_I386_SECREL: 204 // 32-bit offset of the target from the beginning of its section. 205 assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX && 206 "relocation overflow"); 207 assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN && 208 "relocation underflow"); 209 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 210 << " RelType: IMAGE_REL_I386_SECREL Value: " << RE.Addend 211 << '\n'); 212 writeBytesUnaligned(RE.Addend, Target, 2); 213 break; 214 default: 215 llvm_unreachable("unsupported relocation type"); 216 } 217 } 218 registerEHFrames()219 void registerEHFrames() override {} deregisterEHFrames()220 void deregisterEHFrames() override {} 221 }; 222 223 } 224 225 #endif 226 227