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