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 processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & Obj,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)37 relocation_iterator processRelocationRef(unsigned SectionID, 38 relocation_iterator RelI, 39 const ObjectFile &Obj, 40 ObjSectionToIDMap &ObjSectionToID, 41 StubMap &Stubs) override { 42 auto Symbol = RelI->getSymbol(); 43 if (Symbol == Obj.symbol_end()) 44 report_fatal_error("Unknown symbol in relocation"); 45 46 ErrorOr<StringRef> TargetNameOrErr = Symbol->getName(); 47 if (auto EC = TargetNameOrErr.getError()) 48 report_fatal_error(EC.message()); 49 StringRef TargetName = *TargetNameOrErr; 50 51 auto Section = *Symbol->getSection(); 52 53 uint64_t RelType = RelI->getType(); 54 uint64_t Offset = RelI->getOffset(); 55 56 #if !defined(NDEBUG) 57 SmallString<32> RelTypeName; 58 RelI->getTypeName(RelTypeName); 59 #endif 60 DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset 61 << " RelType: " << RelTypeName << " TargetName: " << TargetName 62 << "\n"); 63 64 unsigned TargetSectionID = -1; 65 if (Section == Obj.section_end()) { 66 RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0); 67 addRelocationForSymbol(RE, TargetName); 68 } else { 69 TargetSectionID = 70 findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID); 71 72 switch (RelType) { 73 case COFF::IMAGE_REL_I386_ABSOLUTE: 74 // This relocation is ignored. 75 break; 76 case COFF::IMAGE_REL_I386_DIR32: 77 case COFF::IMAGE_REL_I386_DIR32NB: 78 case COFF::IMAGE_REL_I386_REL32: { 79 RelocationEntry RE = 80 RelocationEntry(SectionID, Offset, RelType, 0, TargetSectionID, 81 getSymbolOffset(*Symbol), 0, 0, false, 0); 82 addRelocationForSection(RE, TargetSectionID); 83 break; 84 } 85 case COFF::IMAGE_REL_I386_SECTION: { 86 RelocationEntry RE = 87 RelocationEntry(TargetSectionID, Offset, RelType, 0); 88 addRelocationForSection(RE, TargetSectionID); 89 break; 90 } 91 case COFF::IMAGE_REL_I386_SECREL: { 92 RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType, 93 getSymbolOffset(*Symbol)); 94 addRelocationForSection(RE, TargetSectionID); 95 break; 96 } 97 default: 98 llvm_unreachable("unsupported relocation type"); 99 } 100 101 } 102 103 return ++RelI; 104 } 105 resolveRelocation(const RelocationEntry & RE,uint64_t Value)106 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 107 const auto Section = Sections[RE.SectionID]; 108 uint8_t *Target = Section.getAddressWithOffset(RE.Offset); 109 110 switch (RE.RelType) { 111 case COFF::IMAGE_REL_I386_ABSOLUTE: 112 // This relocation is ignored. 113 break; 114 case COFF::IMAGE_REL_I386_DIR32: { 115 // The target's 32-bit VA. 116 uint64_t Result = 117 RE.Sections.SectionA == static_cast<uint32_t>(-1) 118 ? Value 119 : Sections[RE.Sections.SectionA].getLoadAddressWithOffset( 120 RE.Addend); 121 assert(static_cast<int32_t>(Result) <= INT32_MAX && 122 "relocation overflow"); 123 assert(static_cast<int32_t>(Result) >= INT32_MIN && 124 "relocation underflow"); 125 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 126 << " RelType: IMAGE_REL_I386_DIR32" 127 << " TargetSection: " << RE.Sections.SectionA 128 << " Value: " << format("0x%08" PRIx32, Result) << '\n'); 129 writeBytesUnaligned(Result, Target, 4); 130 break; 131 } 132 case COFF::IMAGE_REL_I386_DIR32NB: { 133 // The target's 32-bit RVA. 134 // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase 135 uint64_t Result = 136 Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend) - 137 Sections[0].getLoadAddress(); 138 assert(static_cast<int32_t>(Result) <= INT32_MAX && 139 "relocation overflow"); 140 assert(static_cast<int32_t>(Result) >= INT32_MIN && 141 "relocation underflow"); 142 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 143 << " RelType: IMAGE_REL_I386_DIR32NB" 144 << " TargetSection: " << RE.Sections.SectionA 145 << " Value: " << format("0x%08" PRIx32, Result) << '\n'); 146 writeBytesUnaligned(Result, Target, 4); 147 break; 148 } 149 case COFF::IMAGE_REL_I386_REL32: { 150 // 32-bit relative displacement to the target. 151 uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() - 152 Section.getLoadAddress() + RE.Addend - 4 - RE.Offset; 153 assert(static_cast<int32_t>(Result) <= INT32_MAX && 154 "relocation overflow"); 155 assert(static_cast<int32_t>(Result) >= INT32_MIN && 156 "relocation underflow"); 157 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 158 << " RelType: IMAGE_REL_I386_REL32" 159 << " TargetSection: " << RE.Sections.SectionA 160 << " Value: " << format("0x%08" PRIx32, Result) << '\n'); 161 writeBytesUnaligned(Result, Target, 4); 162 break; 163 } 164 case COFF::IMAGE_REL_I386_SECTION: 165 // 16-bit section index of the section that contains the target. 166 assert(static_cast<int32_t>(RE.SectionID) <= INT16_MAX && 167 "relocation overflow"); 168 assert(static_cast<int32_t>(RE.SectionID) >= INT16_MIN && 169 "relocation underflow"); 170 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 171 << " RelType: IMAGE_REL_I386_SECTION Value: " << RE.SectionID 172 << '\n'); 173 writeBytesUnaligned(RE.SectionID, Target, 2); 174 break; 175 case COFF::IMAGE_REL_I386_SECREL: 176 // 32-bit offset of the target from the beginning of its section. 177 assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX && 178 "relocation overflow"); 179 assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN && 180 "relocation underflow"); 181 DEBUG(dbgs() << "\t\tOffset: " << RE.Offset 182 << " RelType: IMAGE_REL_I386_SECREL Value: " << RE.Addend 183 << '\n'); 184 writeBytesUnaligned(RE.Addend, Target, 2); 185 break; 186 default: 187 llvm_unreachable("unsupported relocation type"); 188 } 189 } 190 registerEHFrames()191 void registerEHFrames() override {} deregisterEHFrames()192 void deregisterEHFrames() override {} 193 finalizeLoad(const ObjectFile & Obj,ObjSectionToIDMap & SectionMap)194 void finalizeLoad(const ObjectFile &Obj, 195 ObjSectionToIDMap &SectionMap) override {} 196 }; 197 198 } 199 200 #endif 201 202