Home | History | Annotate | Download | only in Targets
      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:
     27   RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM,
     28                       RuntimeDyld::SymbolResolver &Resolver)
     29       : RuntimeDyldCOFF(MM, Resolver) {}
     30 
     31   unsigned getMaxStubSize() override {
     32     return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
     33   }
     34 
     35   unsigned getStubAlignment() override { return 1; }
     36 
     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 
    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 
    191   void registerEHFrames() override {}
    192   void deregisterEHFrames() override {}
    193 
    194   void finalizeLoad(const ObjectFile &Obj,
    195                     ObjSectionToIDMap &SectionMap) override {}
    196 };
    197 
    198 }
    199 
    200 #endif
    201 
    202