Home | History | Annotate | Download | only in RuntimeDyld
      1 //===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- 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 // Implementation of the MC-JIT runtime dynamic linker.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "RuntimeDyldMachO.h"
     15 #include "Targets/RuntimeDyldMachOAArch64.h"
     16 #include "Targets/RuntimeDyldMachOARM.h"
     17 #include "Targets/RuntimeDyldMachOI386.h"
     18 #include "Targets/RuntimeDyldMachOX86_64.h"
     19 #include "llvm/ADT/STLExtras.h"
     20 #include "llvm/ADT/StringRef.h"
     21 
     22 using namespace llvm;
     23 using namespace llvm::object;
     24 
     25 #define DEBUG_TYPE "dyld"
     26 
     27 namespace {
     28 
     29 class LoadedMachOObjectInfo final
     30     : public RuntimeDyld::LoadedObjectInfoHelper<LoadedMachOObjectInfo> {
     31 public:
     32   LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld,
     33                         ObjSectionToIDMap ObjSecToIDMap)
     34       : LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {}
     35 
     36   OwningBinary<ObjectFile>
     37   getObjectForDebug(const ObjectFile &Obj) const override {
     38     return OwningBinary<ObjectFile>();
     39   }
     40 };
     41 
     42 }
     43 
     44 namespace llvm {
     45 
     46 int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const {
     47   unsigned NumBytes = 1 << RE.Size;
     48   uint8_t *Src = Sections[RE.SectionID].getAddress() + RE.Offset;
     49 
     50   return static_cast<int64_t>(readBytesUnaligned(Src, NumBytes));
     51 }
     52 
     53 relocation_iterator RuntimeDyldMachO::processScatteredVANILLA(
     54                           unsigned SectionID, relocation_iterator RelI,
     55                           const ObjectFile &BaseObjT,
     56                           RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) {
     57   const MachOObjectFile &Obj =
     58     static_cast<const MachOObjectFile&>(BaseObjT);
     59   MachO::any_relocation_info RE =
     60     Obj.getRelocation(RelI->getRawDataRefImpl());
     61 
     62   SectionEntry &Section = Sections[SectionID];
     63   uint32_t RelocType = Obj.getAnyRelocationType(RE);
     64   bool IsPCRel = Obj.getAnyRelocationPCRel(RE);
     65   unsigned Size = Obj.getAnyRelocationLength(RE);
     66   uint64_t Offset = RelI->getOffset();
     67   uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);
     68   unsigned NumBytes = 1 << Size;
     69   int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes);
     70 
     71   unsigned SymbolBaseAddr = Obj.getScatteredRelocationValue(RE);
     72   section_iterator TargetSI = getSectionByAddress(Obj, SymbolBaseAddr);
     73   assert(TargetSI != Obj.section_end() && "Can't find section for symbol");
     74   uint64_t SectionBaseAddr = TargetSI->getAddress();
     75   SectionRef TargetSection = *TargetSI;
     76   bool IsCode = TargetSection.isText();
     77   uint32_t TargetSectionID =
     78     findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID);
     79 
     80   Addend -= SectionBaseAddr;
     81   RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size);
     82 
     83   addRelocationForSection(R, TargetSectionID);
     84 
     85   return ++RelI;
     86 }
     87 
     88 
     89 RelocationValueRef RuntimeDyldMachO::getRelocationValueRef(
     90     const ObjectFile &BaseTObj, const relocation_iterator &RI,
     91     const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) {
     92 
     93   const MachOObjectFile &Obj =
     94       static_cast<const MachOObjectFile &>(BaseTObj);
     95   MachO::any_relocation_info RelInfo =
     96       Obj.getRelocation(RI->getRawDataRefImpl());
     97   RelocationValueRef Value;
     98 
     99   bool IsExternal = Obj.getPlainRelocationExternal(RelInfo);
    100   if (IsExternal) {
    101     symbol_iterator Symbol = RI->getSymbol();
    102     ErrorOr<StringRef> TargetNameOrErr = Symbol->getName();
    103     if (std::error_code EC = TargetNameOrErr.getError())
    104       report_fatal_error(EC.message());
    105     StringRef TargetName = *TargetNameOrErr;
    106     RTDyldSymbolTable::const_iterator SI =
    107       GlobalSymbolTable.find(TargetName.data());
    108     if (SI != GlobalSymbolTable.end()) {
    109       const auto &SymInfo = SI->second;
    110       Value.SectionID = SymInfo.getSectionID();
    111       Value.Offset = SymInfo.getOffset() + RE.Addend;
    112     } else {
    113       Value.SymbolName = TargetName.data();
    114       Value.Offset = RE.Addend;
    115     }
    116   } else {
    117     SectionRef Sec = Obj.getAnyRelocationSection(RelInfo);
    118     bool IsCode = Sec.isText();
    119     Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID);
    120     uint64_t Addr = Sec.getAddress();
    121     Value.Offset = RE.Addend - Addr;
    122   }
    123 
    124   return Value;
    125 }
    126 
    127 void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value,
    128                                             const relocation_iterator &RI,
    129                                             unsigned OffsetToNextPC) {
    130   auto &O = *cast<MachOObjectFile>(RI->getObject());
    131   section_iterator SecI = O.getRelocationRelocatedSection(RI);
    132   Value.Offset += RI->getOffset() + OffsetToNextPC + SecI->getAddress();
    133 }
    134 
    135 void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE,
    136                                                uint64_t Value) const {
    137   const SectionEntry &Section = Sections[RE.SectionID];
    138   uint8_t *LocalAddress = Section.getAddress() + RE.Offset;
    139   uint64_t FinalAddress = Section.getLoadAddress() + RE.Offset;
    140 
    141   dbgs() << "resolveRelocation Section: " << RE.SectionID
    142          << " LocalAddress: " << format("%p", LocalAddress)
    143          << " FinalAddress: " << format("0x%016" PRIx64, FinalAddress)
    144          << " Value: " << format("0x%016" PRIx64, Value) << " Addend: " << RE.Addend
    145          << " isPCRel: " << RE.IsPCRel << " MachoType: " << RE.RelType
    146          << " Size: " << (1 << RE.Size) << "\n";
    147 }
    148 
    149 section_iterator
    150 RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj,
    151                                       uint64_t Addr) {
    152   section_iterator SI = Obj.section_begin();
    153   section_iterator SE = Obj.section_end();
    154 
    155   for (; SI != SE; ++SI) {
    156     uint64_t SAddr = SI->getAddress();
    157     uint64_t SSize = SI->getSize();
    158     if ((Addr >= SAddr) && (Addr < SAddr + SSize))
    159       return SI;
    160   }
    161 
    162   return SE;
    163 }
    164 
    165 
    166 // Populate __pointers section.
    167 void RuntimeDyldMachO::populateIndirectSymbolPointersSection(
    168                                                     const MachOObjectFile &Obj,
    169                                                     const SectionRef &PTSection,
    170                                                     unsigned PTSectionID) {
    171   assert(!Obj.is64Bit() &&
    172          "Pointer table section not supported in 64-bit MachO.");
    173 
    174   MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
    175   MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl());
    176   uint32_t PTSectionSize = Sec32.size;
    177   unsigned FirstIndirectSymbol = Sec32.reserved1;
    178   const unsigned PTEntrySize = 4;
    179   unsigned NumPTEntries = PTSectionSize / PTEntrySize;
    180   unsigned PTEntryOffset = 0;
    181 
    182   assert((PTSectionSize % PTEntrySize) == 0 &&
    183          "Pointers section does not contain a whole number of stubs?");
    184 
    185   DEBUG(dbgs() << "Populating pointer table section "
    186                << Sections[PTSectionID].getName() << ", Section ID "
    187                << PTSectionID << ", " << NumPTEntries << " entries, "
    188                << PTEntrySize << " bytes each:\n");
    189 
    190   for (unsigned i = 0; i < NumPTEntries; ++i) {
    191     unsigned SymbolIndex =
    192       Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
    193     symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
    194     ErrorOr<StringRef> IndirectSymbolNameOrErr = SI->getName();
    195     if (std::error_code EC = IndirectSymbolNameOrErr.getError())
    196       report_fatal_error(EC.message());
    197     StringRef IndirectSymbolName = *IndirectSymbolNameOrErr;
    198     DEBUG(dbgs() << "  " << IndirectSymbolName << ": index " << SymbolIndex
    199           << ", PT offset: " << PTEntryOffset << "\n");
    200     RelocationEntry RE(PTSectionID, PTEntryOffset,
    201                        MachO::GENERIC_RELOC_VANILLA, 0, false, 2);
    202     addRelocationForSymbol(RE, IndirectSymbolName);
    203     PTEntryOffset += PTEntrySize;
    204   }
    205 }
    206 
    207 bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const {
    208   return Obj.isMachO();
    209 }
    210 
    211 template <typename Impl>
    212 void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj,
    213                                                   ObjSectionToIDMap &SectionMap) {
    214   unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
    215   unsigned TextSID = RTDYLD_INVALID_SECTION_ID;
    216   unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID;
    217 
    218   for (const auto &Section : Obj.sections()) {
    219     StringRef Name;
    220     Section.getName(Name);
    221 
    222     // Force emission of the __text, __eh_frame, and __gcc_except_tab sections
    223     // if they're present. Otherwise call down to the impl to handle other
    224     // sections that have already been emitted.
    225     if (Name == "__text")
    226       TextSID = findOrEmitSection(Obj, Section, true, SectionMap);
    227     else if (Name == "__eh_frame")
    228       EHFrameSID = findOrEmitSection(Obj, Section, false, SectionMap);
    229     else if (Name == "__gcc_except_tab")
    230       ExceptTabSID = findOrEmitSection(Obj, Section, true, SectionMap);
    231     else {
    232       auto I = SectionMap.find(Section);
    233       if (I != SectionMap.end())
    234         impl().finalizeSection(Obj, I->second, Section);
    235     }
    236   }
    237   UnregisteredEHFrameSections.push_back(
    238     EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID));
    239 }
    240 
    241 template <typename Impl>
    242 unsigned char *RuntimeDyldMachOCRTPBase<Impl>::processFDE(uint8_t *P,
    243                                                           int64_t DeltaForText,
    244                                                           int64_t DeltaForEH) {
    245   typedef typename Impl::TargetPtrT TargetPtrT;
    246 
    247   DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText
    248                << ", Delta for EH: " << DeltaForEH << "\n");
    249   uint32_t Length = readBytesUnaligned(P, 4);
    250   P += 4;
    251   uint8_t *Ret = P + Length;
    252   uint32_t Offset = readBytesUnaligned(P, 4);
    253   if (Offset == 0) // is a CIE
    254     return Ret;
    255 
    256   P += 4;
    257   TargetPtrT FDELocation = readBytesUnaligned(P, sizeof(TargetPtrT));
    258   TargetPtrT NewLocation = FDELocation - DeltaForText;
    259   writeBytesUnaligned(NewLocation, P, sizeof(TargetPtrT));
    260 
    261   P += sizeof(TargetPtrT);
    262 
    263   // Skip the FDE address range
    264   P += sizeof(TargetPtrT);
    265 
    266   uint8_t Augmentationsize = *P;
    267   P += 1;
    268   if (Augmentationsize != 0) {
    269     TargetPtrT LSDA = readBytesUnaligned(P, sizeof(TargetPtrT));
    270     TargetPtrT NewLSDA = LSDA - DeltaForEH;
    271     writeBytesUnaligned(NewLSDA, P, sizeof(TargetPtrT));
    272   }
    273 
    274   return Ret;
    275 }
    276 
    277 static int64_t computeDelta(SectionEntry *A, SectionEntry *B) {
    278   int64_t ObjDistance = static_cast<int64_t>(A->getObjAddress()) -
    279                         static_cast<int64_t>(B->getObjAddress());
    280   int64_t MemDistance = A->getLoadAddress() - B->getLoadAddress();
    281   return ObjDistance - MemDistance;
    282 }
    283 
    284 template <typename Impl>
    285 void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() {
    286 
    287   for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) {
    288     EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i];
    289     if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID ||
    290         SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID)
    291       continue;
    292     SectionEntry *Text = &Sections[SectionInfo.TextSID];
    293     SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID];
    294     SectionEntry *ExceptTab = nullptr;
    295     if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID)
    296       ExceptTab = &Sections[SectionInfo.ExceptTabSID];
    297 
    298     int64_t DeltaForText = computeDelta(Text, EHFrame);
    299     int64_t DeltaForEH = 0;
    300     if (ExceptTab)
    301       DeltaForEH = computeDelta(ExceptTab, EHFrame);
    302 
    303     uint8_t *P = EHFrame->getAddress();
    304     uint8_t *End = P + EHFrame->getSize();
    305     do {
    306       P = processFDE(P, DeltaForText, DeltaForEH);
    307     } while (P != End);
    308 
    309     MemMgr.registerEHFrames(EHFrame->getAddress(), EHFrame->getLoadAddress(),
    310                             EHFrame->getSize());
    311   }
    312   UnregisteredEHFrameSections.clear();
    313 }
    314 
    315 std::unique_ptr<RuntimeDyldMachO>
    316 RuntimeDyldMachO::create(Triple::ArchType Arch,
    317                          RuntimeDyld::MemoryManager &MemMgr,
    318                          RuntimeDyld::SymbolResolver &Resolver) {
    319   switch (Arch) {
    320   default:
    321     llvm_unreachable("Unsupported target for RuntimeDyldMachO.");
    322     break;
    323   case Triple::arm:
    324     return make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver);
    325   case Triple::aarch64:
    326     return make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver);
    327   case Triple::x86:
    328     return make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver);
    329   case Triple::x86_64:
    330     return make_unique<RuntimeDyldMachOX86_64>(MemMgr, Resolver);
    331   }
    332 }
    333 
    334 std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
    335 RuntimeDyldMachO::loadObject(const object::ObjectFile &O) {
    336   return llvm::make_unique<LoadedMachOObjectInfo>(*this, loadObjectImpl(O));
    337 }
    338 
    339 } // end namespace llvm
    340