Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
35269 views
//===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Implementation of the MC-JIT runtime dynamic linker.9//10//===----------------------------------------------------------------------===//1112#include "RuntimeDyldMachO.h"13#include "Targets/RuntimeDyldMachOAArch64.h"14#include "Targets/RuntimeDyldMachOARM.h"15#include "Targets/RuntimeDyldMachOI386.h"16#include "Targets/RuntimeDyldMachOX86_64.h"17#include "llvm/ADT/STLExtras.h"18#include "llvm/ADT/StringRef.h"1920using namespace llvm;21using namespace llvm::object;2223#define DEBUG_TYPE "dyld"2425namespace {2627class LoadedMachOObjectInfo final28: public LoadedObjectInfoHelper<LoadedMachOObjectInfo,29RuntimeDyld::LoadedObjectInfo> {30public:31LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld,32ObjSectionToIDMap ObjSecToIDMap)33: LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {}3435OwningBinary<ObjectFile>36getObjectForDebug(const ObjectFile &Obj) const override {37return OwningBinary<ObjectFile>();38}39};4041}4243namespace llvm {4445int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const {46unsigned NumBytes = 1 << RE.Size;47uint8_t *Src = Sections[RE.SectionID].getAddress() + RE.Offset;4849return static_cast<int64_t>(readBytesUnaligned(Src, NumBytes));50}5152Expected<relocation_iterator>53RuntimeDyldMachO::processScatteredVANILLA(54unsigned SectionID, relocation_iterator RelI,55const ObjectFile &BaseObjT,56RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID,57bool TargetIsLocalThumbFunc) {58const MachOObjectFile &Obj =59static_cast<const MachOObjectFile&>(BaseObjT);60MachO::any_relocation_info RE =61Obj.getRelocation(RelI->getRawDataRefImpl());6263SectionEntry &Section = Sections[SectionID];64uint32_t RelocType = Obj.getAnyRelocationType(RE);65bool IsPCRel = Obj.getAnyRelocationPCRel(RE);66unsigned Size = Obj.getAnyRelocationLength(RE);67uint64_t Offset = RelI->getOffset();68uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);69unsigned NumBytes = 1 << Size;70int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes);7172unsigned SymbolBaseAddr = Obj.getScatteredRelocationValue(RE);73section_iterator TargetSI = getSectionByAddress(Obj, SymbolBaseAddr);74assert(TargetSI != Obj.section_end() && "Can't find section for symbol");75uint64_t SectionBaseAddr = TargetSI->getAddress();76SectionRef TargetSection = *TargetSI;77bool IsCode = TargetSection.isText();78uint32_t TargetSectionID = ~0U;79if (auto TargetSectionIDOrErr =80findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID))81TargetSectionID = *TargetSectionIDOrErr;82else83return TargetSectionIDOrErr.takeError();8485Addend -= SectionBaseAddr;86RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size);87R.IsTargetThumbFunc = TargetIsLocalThumbFunc;8889addRelocationForSection(R, TargetSectionID);9091return ++RelI;92}939495Expected<RelocationValueRef>96RuntimeDyldMachO::getRelocationValueRef(97const ObjectFile &BaseTObj, const relocation_iterator &RI,98const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) {99100const MachOObjectFile &Obj =101static_cast<const MachOObjectFile &>(BaseTObj);102MachO::any_relocation_info RelInfo =103Obj.getRelocation(RI->getRawDataRefImpl());104RelocationValueRef Value;105106bool IsExternal = Obj.getPlainRelocationExternal(RelInfo);107if (IsExternal) {108symbol_iterator Symbol = RI->getSymbol();109StringRef TargetName;110if (auto TargetNameOrErr = Symbol->getName())111TargetName = *TargetNameOrErr;112else113return TargetNameOrErr.takeError();114RTDyldSymbolTable::const_iterator SI =115GlobalSymbolTable.find(TargetName.data());116if (SI != GlobalSymbolTable.end()) {117const auto &SymInfo = SI->second;118Value.SectionID = SymInfo.getSectionID();119Value.Offset = SymInfo.getOffset() + RE.Addend;120} else {121Value.SymbolName = TargetName.data();122Value.Offset = RE.Addend;123}124} else {125SectionRef Sec = Obj.getAnyRelocationSection(RelInfo);126bool IsCode = Sec.isText();127if (auto SectionIDOrErr = findOrEmitSection(Obj, Sec, IsCode,128ObjSectionToID))129Value.SectionID = *SectionIDOrErr;130else131return SectionIDOrErr.takeError();132uint64_t Addr = Sec.getAddress();133Value.Offset = RE.Addend - Addr;134}135136return Value;137}138139void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value,140const relocation_iterator &RI,141unsigned OffsetToNextPC) {142auto &O = *cast<MachOObjectFile>(RI->getObject());143section_iterator SecI = O.getRelocationRelocatedSection(RI);144Value.Offset += RI->getOffset() + OffsetToNextPC + SecI->getAddress();145}146147void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE,148uint64_t Value) const {149const SectionEntry &Section = Sections[RE.SectionID];150uint8_t *LocalAddress = Section.getAddress() + RE.Offset;151uint64_t FinalAddress = Section.getLoadAddress() + RE.Offset;152153dbgs() << "resolveRelocation Section: " << RE.SectionID154<< " LocalAddress: " << format("%p", LocalAddress)155<< " FinalAddress: " << format("0x%016" PRIx64, FinalAddress)156<< " Value: " << format("0x%016" PRIx64, Value) << " Addend: " << RE.Addend157<< " isPCRel: " << RE.IsPCRel << " MachoType: " << RE.RelType158<< " Size: " << (1 << RE.Size) << "\n";159}160161section_iterator162RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj,163uint64_t Addr) {164section_iterator SI = Obj.section_begin();165section_iterator SE = Obj.section_end();166167for (; SI != SE; ++SI) {168uint64_t SAddr = SI->getAddress();169uint64_t SSize = SI->getSize();170if ((Addr >= SAddr) && (Addr < SAddr + SSize))171return SI;172}173174return SE;175}176177178// Populate __pointers section.179Error RuntimeDyldMachO::populateIndirectSymbolPointersSection(180const MachOObjectFile &Obj,181const SectionRef &PTSection,182unsigned PTSectionID) {183assert(!Obj.is64Bit() &&184"Pointer table section not supported in 64-bit MachO.");185186MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();187MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl());188uint32_t PTSectionSize = Sec32.size;189unsigned FirstIndirectSymbol = Sec32.reserved1;190const unsigned PTEntrySize = 4;191unsigned NumPTEntries = PTSectionSize / PTEntrySize;192unsigned PTEntryOffset = 0;193194assert((PTSectionSize % PTEntrySize) == 0 &&195"Pointers section does not contain a whole number of stubs?");196197LLVM_DEBUG(dbgs() << "Populating pointer table section "198<< Sections[PTSectionID].getName() << ", Section ID "199<< PTSectionID << ", " << NumPTEntries << " entries, "200<< PTEntrySize << " bytes each:\n");201202for (unsigned i = 0; i < NumPTEntries; ++i) {203unsigned SymbolIndex =204Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);205symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);206StringRef IndirectSymbolName;207if (auto IndirectSymbolNameOrErr = SI->getName())208IndirectSymbolName = *IndirectSymbolNameOrErr;209else210return IndirectSymbolNameOrErr.takeError();211LLVM_DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex212<< ", PT offset: " << PTEntryOffset << "\n");213RelocationEntry RE(PTSectionID, PTEntryOffset,214MachO::GENERIC_RELOC_VANILLA, 0, false, 2);215addRelocationForSymbol(RE, IndirectSymbolName);216PTEntryOffset += PTEntrySize;217}218return Error::success();219}220221bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const {222return Obj.isMachO();223}224225template <typename Impl>226Error227RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj,228ObjSectionToIDMap &SectionMap) {229unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;230unsigned TextSID = RTDYLD_INVALID_SECTION_ID;231unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID;232233for (const auto &Section : Obj.sections()) {234StringRef Name;235if (Expected<StringRef> NameOrErr = Section.getName())236Name = *NameOrErr;237else238consumeError(NameOrErr.takeError());239240// Force emission of the __text, __eh_frame, and __gcc_except_tab sections241// if they're present. Otherwise call down to the impl to handle other242// sections that have already been emitted.243if (Name == "__text") {244if (auto TextSIDOrErr = findOrEmitSection(Obj, Section, true, SectionMap))245TextSID = *TextSIDOrErr;246else247return TextSIDOrErr.takeError();248} else if (Name == "__eh_frame") {249if (auto EHFrameSIDOrErr = findOrEmitSection(Obj, Section, false,250SectionMap))251EHFrameSID = *EHFrameSIDOrErr;252else253return EHFrameSIDOrErr.takeError();254} else if (Name == "__gcc_except_tab") {255if (auto ExceptTabSIDOrErr = findOrEmitSection(Obj, Section, true,256SectionMap))257ExceptTabSID = *ExceptTabSIDOrErr;258else259return ExceptTabSIDOrErr.takeError();260} else {261auto I = SectionMap.find(Section);262if (I != SectionMap.end())263if (auto Err = impl().finalizeSection(Obj, I->second, Section))264return Err;265}266}267UnregisteredEHFrameSections.push_back(268EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID));269270return Error::success();271}272273template <typename Impl>274unsigned char *RuntimeDyldMachOCRTPBase<Impl>::processFDE(uint8_t *P,275int64_t DeltaForText,276int64_t DeltaForEH) {277typedef typename Impl::TargetPtrT TargetPtrT;278279LLVM_DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText280<< ", Delta for EH: " << DeltaForEH << "\n");281uint32_t Length = readBytesUnaligned(P, 4);282P += 4;283uint8_t *Ret = P + Length;284uint32_t Offset = readBytesUnaligned(P, 4);285if (Offset == 0) // is a CIE286return Ret;287288P += 4;289TargetPtrT FDELocation = readBytesUnaligned(P, sizeof(TargetPtrT));290TargetPtrT NewLocation = FDELocation - DeltaForText;291writeBytesUnaligned(NewLocation, P, sizeof(TargetPtrT));292293P += sizeof(TargetPtrT);294295// Skip the FDE address range296P += sizeof(TargetPtrT);297298uint8_t Augmentationsize = *P;299P += 1;300if (Augmentationsize != 0) {301TargetPtrT LSDA = readBytesUnaligned(P, sizeof(TargetPtrT));302TargetPtrT NewLSDA = LSDA - DeltaForEH;303writeBytesUnaligned(NewLSDA, P, sizeof(TargetPtrT));304}305306return Ret;307}308309static int64_t computeDelta(SectionEntry *A, SectionEntry *B) {310int64_t ObjDistance = static_cast<int64_t>(A->getObjAddress()) -311static_cast<int64_t>(B->getObjAddress());312int64_t MemDistance = A->getLoadAddress() - B->getLoadAddress();313return ObjDistance - MemDistance;314}315316template <typename Impl>317void RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() {318319for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) {320EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i];321if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID ||322SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID)323continue;324SectionEntry *Text = &Sections[SectionInfo.TextSID];325SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID];326SectionEntry *ExceptTab = nullptr;327if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID)328ExceptTab = &Sections[SectionInfo.ExceptTabSID];329330int64_t DeltaForText = computeDelta(Text, EHFrame);331int64_t DeltaForEH = 0;332if (ExceptTab)333DeltaForEH = computeDelta(ExceptTab, EHFrame);334335uint8_t *P = EHFrame->getAddress();336uint8_t *End = P + EHFrame->getSize();337while (P != End) {338P = processFDE(P, DeltaForText, DeltaForEH);339}340341MemMgr.registerEHFrames(EHFrame->getAddress(), EHFrame->getLoadAddress(),342EHFrame->getSize());343}344UnregisteredEHFrameSections.clear();345}346347std::unique_ptr<RuntimeDyldMachO>348RuntimeDyldMachO::create(Triple::ArchType Arch,349RuntimeDyld::MemoryManager &MemMgr,350JITSymbolResolver &Resolver) {351switch (Arch) {352default:353llvm_unreachable("Unsupported target for RuntimeDyldMachO.");354break;355case Triple::arm:356return std::make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver);357case Triple::aarch64:358return std::make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver);359case Triple::aarch64_32:360return std::make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver);361case Triple::x86:362return std::make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver);363case Triple::x86_64:364return std::make_unique<RuntimeDyldMachOX86_64>(MemMgr, Resolver);365}366}367368std::unique_ptr<RuntimeDyld::LoadedObjectInfo>369RuntimeDyldMachO::loadObject(const object::ObjectFile &O) {370if (auto ObjSectionToIDOrErr = loadObjectImpl(O))371return std::make_unique<LoadedMachOObjectInfo>(*this,372*ObjSectionToIDOrErr);373else {374HasError = true;375raw_string_ostream ErrStream(ErrorStr);376logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream);377return nullptr;378}379}380381} // end namespace llvm382383384