Home | History | Annotate | Download | only in Targets
      1 //===-- RuntimeDyldMachOX86_64.h ---- MachO/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 #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOX86_64_H
     11 #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOX86_64_H
     12 
     13 #include "../RuntimeDyldMachO.h"
     14 #include <string>
     15 
     16 #define DEBUG_TYPE "dyld"
     17 
     18 namespace llvm {
     19 
     20 class RuntimeDyldMachOX86_64
     21     : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOX86_64> {
     22 public:
     23 
     24   typedef uint64_t TargetPtrT;
     25 
     26   RuntimeDyldMachOX86_64(RuntimeDyld::MemoryManager &MM,
     27                          RuntimeDyld::SymbolResolver &Resolver)
     28       : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
     29 
     30   unsigned getMaxStubSize() override { return 8; }
     31 
     32   unsigned getStubAlignment() override { return 1; }
     33 
     34   Expected<relocation_iterator>
     35   processRelocationRef(unsigned SectionID, relocation_iterator RelI,
     36                        const ObjectFile &BaseObjT,
     37                        ObjSectionToIDMap &ObjSectionToID,
     38                        StubMap &Stubs) override {
     39     const MachOObjectFile &Obj =
     40       static_cast<const MachOObjectFile &>(BaseObjT);
     41     MachO::any_relocation_info RelInfo =
     42         Obj.getRelocation(RelI->getRawDataRefImpl());
     43     uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
     44 
     45     if (RelType == MachO::X86_64_RELOC_SUBTRACTOR)
     46       return processSubtractRelocation(SectionID, RelI, Obj, ObjSectionToID);
     47 
     48     assert(!Obj.isRelocationScattered(RelInfo) &&
     49            "Scattered relocations not supported on X86_64");
     50 
     51     RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
     52     RE.Addend = memcpyAddend(RE);
     53     RelocationValueRef Value;
     54     if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
     55       Value = *ValueOrErr;
     56     else
     57       return ValueOrErr.takeError();
     58 
     59     bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
     60     if (!IsExtern && RE.IsPCRel)
     61       makeValueAddendPCRel(Value, RelI, 1 << RE.Size);
     62 
     63     switch (RelType) {
     64     UNIMPLEMENTED_RELOC(MachO::X86_64_RELOC_TLV);
     65     default:
     66       if (RelType > MachO::X86_64_RELOC_TLV)
     67         return make_error<RuntimeDyldError>(("MachO X86_64 relocation type " +
     68                                              Twine(RelType) +
     69                                              " is out of range").str());
     70       break;
     71     }
     72 
     73     if (RE.RelType == MachO::X86_64_RELOC_GOT ||
     74         RE.RelType == MachO::X86_64_RELOC_GOT_LOAD)
     75       processGOTRelocation(RE, Value, Stubs);
     76     else {
     77       RE.Addend = Value.Offset;
     78       if (Value.SymbolName)
     79         addRelocationForSymbol(RE, Value.SymbolName);
     80       else
     81         addRelocationForSection(RE, Value.SectionID);
     82     }
     83 
     84     return ++RelI;
     85   }
     86 
     87   void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
     88     DEBUG(dumpRelocationToResolve(RE, Value));
     89     const SectionEntry &Section = Sections[RE.SectionID];
     90     uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
     91 
     92     // If the relocation is PC-relative, the value to be encoded is the
     93     // pointer difference.
     94     if (RE.IsPCRel) {
     95       // FIXME: It seems this value needs to be adjusted by 4 for an effective
     96       // PC address. Is that expected? Only for branches, perhaps?
     97       uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
     98       Value -= FinalAddress + 4;
     99     }
    100 
    101     switch (RE.RelType) {
    102     default:
    103       llvm_unreachable("Invalid relocation type!");
    104     case MachO::X86_64_RELOC_SIGNED_1:
    105     case MachO::X86_64_RELOC_SIGNED_2:
    106     case MachO::X86_64_RELOC_SIGNED_4:
    107     case MachO::X86_64_RELOC_SIGNED:
    108     case MachO::X86_64_RELOC_UNSIGNED:
    109     case MachO::X86_64_RELOC_BRANCH:
    110       writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size);
    111       break;
    112     case MachO::X86_64_RELOC_SUBTRACTOR: {
    113       uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress();
    114       uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress();
    115       assert((Value == SectionABase || Value == SectionBBase) &&
    116              "Unexpected SUBTRACTOR relocation value.");
    117       Value = SectionABase - SectionBBase + RE.Addend;
    118       writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size);
    119       break;
    120     }
    121     }
    122   }
    123 
    124   Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,
    125                         const SectionRef &Section) {
    126     return Error::success();
    127   }
    128 
    129 private:
    130   void processGOTRelocation(const RelocationEntry &RE,
    131                             RelocationValueRef &Value, StubMap &Stubs) {
    132     SectionEntry &Section = Sections[RE.SectionID];
    133     assert(RE.IsPCRel);
    134     assert(RE.Size == 2);
    135     Value.Offset -= RE.Addend;
    136     RuntimeDyldMachO::StubMap::const_iterator i = Stubs.find(Value);
    137     uint8_t *Addr;
    138     if (i != Stubs.end()) {
    139       Addr = Section.getAddressWithOffset(i->second);
    140     } else {
    141       Stubs[Value] = Section.getStubOffset();
    142       uint8_t *GOTEntry = Section.getAddressWithOffset(Section.getStubOffset());
    143       RelocationEntry GOTRE(RE.SectionID, Section.getStubOffset(),
    144                             MachO::X86_64_RELOC_UNSIGNED, Value.Offset, false,
    145                             3);
    146       if (Value.SymbolName)
    147         addRelocationForSymbol(GOTRE, Value.SymbolName);
    148       else
    149         addRelocationForSection(GOTRE, Value.SectionID);
    150       Section.advanceStubOffset(8);
    151       Addr = GOTEntry;
    152     }
    153     RelocationEntry TargetRE(RE.SectionID, RE.Offset,
    154                              MachO::X86_64_RELOC_UNSIGNED, RE.Addend, true, 2);
    155     resolveRelocation(TargetRE, (uint64_t)Addr);
    156   }
    157 
    158   Expected<relocation_iterator>
    159   processSubtractRelocation(unsigned SectionID, relocation_iterator RelI,
    160                             const MachOObjectFile &BaseObj,
    161                             ObjSectionToIDMap &ObjSectionToID) {
    162     const MachOObjectFile &Obj =
    163         static_cast<const MachOObjectFile&>(BaseObj);
    164     MachO::any_relocation_info RE =
    165         Obj.getRelocation(RelI->getRawDataRefImpl());
    166 
    167     unsigned Size = Obj.getAnyRelocationLength(RE);
    168     uint64_t Offset = RelI->getOffset();
    169     uint8_t *LocalAddress = Sections[SectionID].getAddressWithOffset(Offset);
    170     unsigned NumBytes = 1 << Size;
    171     int64_t Addend =
    172       SignExtend64(readBytesUnaligned(LocalAddress, NumBytes), NumBytes * 8);
    173 
    174     unsigned SectionBID = ~0U;
    175     uint64_t SectionBOffset = 0;
    176 
    177     MachO::any_relocation_info RelInfo =
    178       Obj.getRelocation(RelI->getRawDataRefImpl());
    179 
    180     bool AIsExternal = BaseObj.getPlainRelocationExternal(RelInfo);
    181 
    182     if (AIsExternal) {
    183       Expected<StringRef> SubtrahendNameOrErr = RelI->getSymbol()->getName();
    184       if (!SubtrahendNameOrErr)
    185         return SubtrahendNameOrErr.takeError();
    186       auto SubtrahendI = GlobalSymbolTable.find(*SubtrahendNameOrErr);
    187       SectionBID = SubtrahendI->second.getSectionID();
    188       SectionBOffset = SubtrahendI->second.getOffset();
    189     } else {
    190       SectionRef SecB = Obj.getAnyRelocationSection(RelInfo);
    191       bool IsCode = SecB.isText();
    192       Expected<unsigned> SectionBIDOrErr =
    193         findOrEmitSection(Obj, SecB, IsCode, ObjSectionToID);
    194       if (!SectionBIDOrErr)
    195         return SectionBIDOrErr.takeError();
    196       SectionBID = *SectionBIDOrErr;
    197       Addend += SecB.getAddress();
    198     }
    199 
    200     ++RelI;
    201 
    202     unsigned SectionAID = ~0U;
    203     uint64_t SectionAOffset = 0;
    204 
    205     RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl());
    206 
    207     bool BIsExternal = BaseObj.getPlainRelocationExternal(RelInfo);
    208     if (BIsExternal) {
    209       Expected<StringRef> MinuendNameOrErr = RelI->getSymbol()->getName();
    210       if (!MinuendNameOrErr)
    211         return MinuendNameOrErr.takeError();
    212       auto MinuendI = GlobalSymbolTable.find(*MinuendNameOrErr);
    213       SectionAID = MinuendI->second.getSectionID();
    214       SectionAOffset = MinuendI->second.getOffset();
    215     } else {
    216       SectionRef SecA = Obj.getAnyRelocationSection(RelInfo);
    217       bool IsCode = SecA.isText();
    218       Expected<unsigned> SectionAIDOrErr =
    219         findOrEmitSection(Obj, SecA, IsCode, ObjSectionToID);
    220       if (!SectionAIDOrErr)
    221         return SectionAIDOrErr.takeError();
    222       SectionAID = *SectionAIDOrErr;
    223       Addend -= SecA.getAddress();
    224     }
    225 
    226     RelocationEntry R(SectionID, Offset, MachO::X86_64_RELOC_SUBTRACTOR, (uint64_t)Addend,
    227                       SectionAID, SectionAOffset, SectionBID, SectionBOffset,
    228                       false, Size);
    229 
    230     addRelocationForSection(R, SectionAID);
    231 
    232     return ++RelI;
    233   }
    234 
    235 };
    236 }
    237 
    238 #undef DEBUG_TYPE
    239 
    240 #endif
    241