LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/RuntimeDyld - RuntimeDyldMachO.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 231 332 69.6 %
Date: 2018-10-20 13:21:21 Functions: 19 23 82.6 %
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           0 : 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          32 :   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             :   const MachOObjectFile &Obj =
      61             :     static_cast<const MachOObjectFile&>(BaseObjT);
      62             :   MachO::any_relocation_info RE =
      63           2 :     Obj.getRelocation(RelI->getRawDataRefImpl());
      64             : 
      65           2 :   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           2 :   uint64_t Offset = RelI->getOffset();
      70           2 :   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           2 :   uint64_t SectionBaseAddr = TargetSI->getAddress();
      78           2 :   SectionRef TargetSection = *TargetSI;
      79           2 :   bool IsCode = TargetSection.isText();
      80             :   uint32_t TargetSectionID = ~0U;
      81           2 :   if (auto TargetSectionIDOrErr =
      82           2 :         findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID))
      83           2 :     TargetSectionID = *TargetSectionIDOrErr;
      84             :   else
      85             :     return TargetSectionIDOrErr.takeError();
      86             : 
      87           2 :   Addend -= SectionBaseAddr;
      88             :   RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size);
      89           2 :   R.IsTargetThumbFunc = TargetIsLocalThumbFunc;
      90             : 
      91           2 :   addRelocationForSection(R, TargetSectionID);
      92             : 
      93             :   return ++RelI;
      94             : }
      95             : 
      96             : 
      97             : Expected<RelocationValueRef>
      98          47 : RuntimeDyldMachO::getRelocationValueRef(
      99             :     const ObjectFile &BaseTObj, const relocation_iterator &RI,
     100             :     const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) {
     101             : 
     102             :   const MachOObjectFile &Obj =
     103             :       static_cast<const MachOObjectFile &>(BaseTObj);
     104             :   MachO::any_relocation_info RelInfo =
     105          47 :       Obj.getRelocation(RI->getRawDataRefImpl());
     106             :   RelocationValueRef Value;
     107             : 
     108          47 :   bool IsExternal = Obj.getPlainRelocationExternal(RelInfo);
     109          47 :   if (IsExternal) {
     110          21 :     symbol_iterator Symbol = RI->getSymbol();
     111             :     StringRef TargetName;
     112          21 :     if (auto TargetNameOrErr = Symbol->getName())
     113          21 :       TargetName = *TargetNameOrErr;
     114             :     else
     115             :       return TargetNameOrErr.takeError();
     116             :     RTDyldSymbolTable::const_iterator SI =
     117          42 :       GlobalSymbolTable.find(TargetName.data());
     118          42 :     if (SI != GlobalSymbolTable.end()) {
     119             :       const auto &SymInfo = SI->second;
     120          14 :       Value.SectionID = SymInfo.getSectionID();
     121          14 :       Value.Offset = SymInfo.getOffset() + RE.Addend;
     122             :     } else {
     123             :       Value.SymbolName = TargetName.data();
     124           7 :       Value.Offset = RE.Addend;
     125             :     }
     126             :   } else {
     127          26 :     SectionRef Sec = Obj.getAnyRelocationSection(RelInfo);
     128          26 :     bool IsCode = Sec.isText();
     129          26 :     if (auto SectionIDOrErr = findOrEmitSection(Obj, Sec, IsCode,
     130          26 :                                                 ObjSectionToID))
     131          26 :       Value.SectionID = *SectionIDOrErr;
     132             :     else
     133             :       return SectionIDOrErr.takeError();
     134          26 :     uint64_t Addr = Sec.getAddress();
     135          26 :     Value.Offset = RE.Addend - Addr;
     136             :   }
     137             : 
     138             :   return Value;
     139             : }
     140             : 
     141           8 : void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value,
     142             :                                             const relocation_iterator &RI,
     143             :                                             unsigned OffsetToNextPC) {
     144           8 :   auto &O = *cast<MachOObjectFile>(RI->getObject());
     145           8 :   section_iterator SecI = O.getRelocationRelocatedSection(RI);
     146           8 :   Value.Offset += RI->getOffset() + OffsetToNextPC + SecI->getAddress();
     147           8 : }
     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           8 : RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj,
     165             :                                       uint64_t Addr) {
     166           8 :   section_iterator SI = Obj.section_begin();
     167           8 :   section_iterator SE = Obj.section_end();
     168             : 
     169          20 :   for (; SI != SE; ++SI) {
     170          20 :     uint64_t SAddr = SI->getAddress();
     171          20 :     uint64_t SSize = SI->getSize();
     172          20 :     if ((Addr >= SAddr) && (Addr < SAddr + SSize))
     173           8 :       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           2 :   MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl());
     190           2 :   uint32_t PTSectionSize = Sec32.size;
     191           2 :   unsigned FirstIndirectSymbol = Sec32.reserved1;
     192             :   const unsigned PTEntrySize = 4;
     193           2 :   unsigned NumPTEntries = PTSectionSize / PTEntrySize;
     194             :   unsigned PTEntryOffset = 0;
     195             : 
     196             :   assert((PTSectionSize % PTEntrySize) == 0 &&
     197             :          "Pointers section does not contain a whole number of stubs?");
     198             : 
     199             :   LLVM_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             :     StringRef IndirectSymbolName;
     209           2 :     if (auto IndirectSymbolNameOrErr = SI->getName())
     210           2 :       IndirectSymbolName = *IndirectSymbolNameOrErr;
     211             :     else
     212             :       return IndirectSymbolNameOrErr.takeError();
     213             :     LLVM_DEBUG(dbgs() << "  " << IndirectSymbolName << ": index " << SymbolIndex
     214             :                       << ", PT offset: " << PTEntryOffset << "\n");
     215             :     RelocationEntry RE(PTSectionID, PTEntryOffset,
     216           2 :                        MachO::GENERIC_RELOC_VANILLA, 0, false, 2);
     217           2 :     addRelocationForSymbol(RE, IndirectSymbolName);
     218           2 :     PTEntryOffset += PTEntrySize;
     219             :   }
     220             :   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             :   unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
     232             :   unsigned TextSID = RTDYLD_INVALID_SECTION_ID;
     233             :   unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID;
     234             : 
     235          75 :   for (const auto &Section : Obj.sections()) {
     236          64 :     StringRef Name;
     237          64 :     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             :     if (Name == "__text") {
     243          11 :       if (auto TextSIDOrErr = findOrEmitSection(Obj, Section, true, SectionMap))
     244          11 :         TextSID = *TextSIDOrErr;
     245             :       else
     246             :         return TextSIDOrErr.takeError();
     247             :     } else if (Name == "__eh_frame") {
     248           7 :       if (auto EHFrameSIDOrErr = findOrEmitSection(Obj, Section, false,
     249             :                                                    SectionMap))
     250           7 :         EHFrameSID = *EHFrameSIDOrErr;
     251             :       else
     252             :         return EHFrameSIDOrErr.takeError();
     253             :     } else if (Name == "__gcc_except_tab") {
     254           0 :       if (auto ExceptTabSIDOrErr = findOrEmitSection(Obj, Section, true,
     255             :                                                      SectionMap))
     256           0 :         ExceptTabSID = *ExceptTabSIDOrErr;
     257             :       else
     258             :         return ExceptTabSIDOrErr.takeError();
     259             :     } else {
     260             :       auto I = SectionMap.find(Section);
     261           6 :       if (I != SectionMap.end())
     262          12 :         if (auto Err = impl().finalizeSection(Obj, I->second, Section))
     263             :           return Err;
     264             :     }
     265             :   }
     266          22 :   UnregisteredEHFrameSections.push_back(
     267             :     EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID));
     268             : 
     269             :   return Error::success();
     270             : }
     271           1 : 
     272             : template <typename Impl>
     273             : unsigned char *RuntimeDyldMachOCRTPBase<Impl>::processFDE(uint8_t *P,
     274             :                                                           int64_t DeltaForText,
     275             :                                                           int64_t DeltaForEH) {
     276             :   typedef typename Impl::TargetPtrT TargetPtrT;
     277           3 : 
     278           2 :   LLVM_DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText
     279           2 :                     << ", Delta for EH: " << DeltaForEH << "\n");
     280             :   uint32_t Length = readBytesUnaligned(P, 4);
     281             :   P += 4;
     282             :   uint8_t *Ret = P + Length;
     283             :   uint32_t Offset = readBytesUnaligned(P, 4);
     284             :   if (Offset == 0) // is a CIE
     285           1 :     return Ret;
     286           1 : 
     287             :   P += 4;
     288             :   TargetPtrT FDELocation = readBytesUnaligned(P, sizeof(TargetPtrT));
     289             :   TargetPtrT NewLocation = FDELocation - DeltaForText;
     290           0 :   writeBytesUnaligned(NewLocation, P, sizeof(TargetPtrT));
     291             : 
     292           0 :   P += sizeof(TargetPtrT);
     293             : 
     294             :   // Skip the FDE address range
     295             :   P += sizeof(TargetPtrT);
     296           0 : 
     297             :   uint8_t Augmentationsize = *P;
     298           0 :   P += 1;
     299             :   if (Augmentationsize != 0) {
     300             :     TargetPtrT LSDA = readBytesUnaligned(P, sizeof(TargetPtrT));
     301             :     TargetPtrT NewLSDA = LSDA - DeltaForEH;
     302             :     writeBytesUnaligned(NewLSDA, P, sizeof(TargetPtrT));
     303             :   }
     304             : 
     305             :   return Ret;
     306             : }
     307             : 
     308           2 : static int64_t computeDelta(SectionEntry *A, SectionEntry *B) {
     309             :   int64_t ObjDistance = static_cast<int64_t>(A->getObjAddress()) -
     310             :                         static_cast<int64_t>(B->getObjAddress());
     311             :   int64_t MemDistance = A->getLoadAddress() - B->getLoadAddress();
     312             :   return ObjDistance - MemDistance;
     313           2 : }
     314             : 
     315             : template <typename Impl>
     316             : void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() {
     317             : 
     318             :   for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) {
     319           6 :     EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i];
     320           4 :     if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID ||
     321           4 :         SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID)
     322             :       continue;
     323             :     SectionEntry *Text = &Sections[SectionInfo.TextSID];
     324             :     SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID];
     325             :     SectionEntry *ExceptTab = nullptr;
     326             :     if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID)
     327           2 :       ExceptTab = &Sections[SectionInfo.ExceptTabSID];
     328           2 : 
     329             :     int64_t DeltaForText = computeDelta(Text, EHFrame);
     330             :     int64_t DeltaForEH = 0;
     331             :     if (ExceptTab)
     332           0 :       DeltaForEH = computeDelta(ExceptTab, EHFrame);
     333             : 
     334           0 :     uint8_t *P = EHFrame->getAddress();
     335             :     uint8_t *End = P + EHFrame->getSize();
     336             :     while (P != End) {
     337             :       P = processFDE(P, DeltaForText, DeltaForEH);
     338           0 :     }
     339             : 
     340           0 :     MemMgr.registerEHFrames(EHFrame->getAddress(), EHFrame->getLoadAddress(),
     341             :                             EHFrame->getSize());
     342             :   }
     343             :   UnregisteredEHFrameSections.clear();
     344             : }
     345           2 : 
     346           4 : std::unique_ptr<RuntimeDyldMachO>
     347             : RuntimeDyldMachO::create(Triple::ArchType Arch,
     348             :                          RuntimeDyld::MemoryManager &MemMgr,
     349             :                          JITSymbolResolver &Resolver) {
     350           4 :   switch (Arch) {
     351             :   default:
     352             :     llvm_unreachable("Unsupported target for RuntimeDyldMachO.");
     353             :     break;
     354             :   case Triple::arm:
     355           2 :     return make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver);
     356             :   case Triple::aarch64:
     357             :     return make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver);
     358             :   case Triple::x86:
     359             :     return make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver);
     360             :   case Triple::x86_64:
     361           9 :     return make_unique<RuntimeDyldMachOX86_64>(MemMgr, Resolver);
     362           7 :   }
     363           7 : }
     364             : 
     365             : std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
     366             : RuntimeDyldMachO::loadObject(const object::ObjectFile &O) {
     367             :   if (auto ObjSectionToIDOrErr = loadObjectImpl(O))
     368             :     return llvm::make_unique<LoadedMachOObjectInfo>(*this,
     369           2 :                                                     *ObjSectionToIDOrErr);
     370           2 :   else {
     371             :     HasError = true;
     372             :     raw_string_ostream ErrStream(ErrorStr);
     373             :     logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream, "");
     374           1 :     return nullptr;
     375             :   }
     376           1 : }
     377             : 
     378             : } // end namespace llvm

Generated by: LCOV version 1.13