LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/RuntimeDyld - RuntimeDyldMachO.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 160 195 82.1 %
Date: 2017-09-14 15:23:50 Functions: 20 25 80.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13