Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
35271 views
//===----- MachOLinkGraphBuilder.h - MachO LinkGraph builder ----*- 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// Generic MachO LinkGraph building code.9//10//===----------------------------------------------------------------------===//1112#ifndef LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H13#define LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H1415#include "llvm/ADT/DenseMap.h"16#include "llvm/ADT/StringMap.h"17#include "llvm/ExecutionEngine/JITLink/JITLink.h"18#include "llvm/Object/MachO.h"1920#include "EHFrameSupportImpl.h"21#include "JITLinkGeneric.h"2223#include <list>2425namespace llvm {26namespace jitlink {2728class MachOLinkGraphBuilder {29public:30virtual ~MachOLinkGraphBuilder();31Expected<std::unique_ptr<LinkGraph>> buildGraph();3233protected:3435struct NormalizedSymbol {36friend class MachOLinkGraphBuilder;3738private:39NormalizedSymbol(std::optional<StringRef> Name, uint64_t Value,40uint8_t Type, uint8_t Sect, uint16_t Desc, Linkage L,41Scope S)42: Name(Name), Value(Value), Type(Type), Sect(Sect), Desc(Desc), L(L),43S(S) {44assert((!Name || !Name->empty()) && "Name must be none or non-empty");45}4647public:48NormalizedSymbol(const NormalizedSymbol &) = delete;49NormalizedSymbol &operator=(const NormalizedSymbol &) = delete;50NormalizedSymbol(NormalizedSymbol &&) = delete;51NormalizedSymbol &operator=(NormalizedSymbol &&) = delete;5253std::optional<StringRef> Name;54uint64_t Value = 0;55uint8_t Type = 0;56uint8_t Sect = 0;57uint16_t Desc = 0;58Linkage L = Linkage::Strong;59Scope S = Scope::Default;60Symbol *GraphSymbol = nullptr;61};6263// Normalized section representation. Section and segment names are guaranteed64// to be null-terminated, hence the extra bytes on SegName and SectName.65class NormalizedSection {66friend class MachOLinkGraphBuilder;6768private:69NormalizedSection() = default;7071public:72char SectName[17];73char SegName[17];74orc::ExecutorAddr Address;75uint64_t Size = 0;76uint64_t Alignment = 0;77uint32_t Flags = 0;78const char *Data = nullptr;79Section *GraphSection = nullptr;80std::map<orc::ExecutorAddr, Symbol *> CanonicalSymbols;81};8283using SectionParserFunction = std::function<Error(NormalizedSection &S)>;8485MachOLinkGraphBuilder(const object::MachOObjectFile &Obj, Triple TT,86SubtargetFeatures Features,87LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);8889LinkGraph &getGraph() const { return *G; }9091const object::MachOObjectFile &getObject() const { return Obj; }9293void addCustomSectionParser(StringRef SectionName,94SectionParserFunction Parse);9596virtual Error addRelocations() = 0;9798/// Create a symbol.99template <typename... ArgTs>100NormalizedSymbol &createNormalizedSymbol(ArgTs &&... Args) {101NormalizedSymbol *Sym = reinterpret_cast<NormalizedSymbol *>(102Allocator.Allocate<NormalizedSymbol>());103new (Sym) NormalizedSymbol(std::forward<ArgTs>(Args)...);104return *Sym;105}106107/// Index is zero-based (MachO section indexes are usually one-based) and108/// assumed to be in-range. Client is responsible for checking.109NormalizedSection &getSectionByIndex(unsigned Index) {110auto I = IndexToSection.find(Index);111assert(I != IndexToSection.end() && "No section recorded at index");112return I->second;113}114115/// Try to get the section at the given index. Will return an error if the116/// given index is out of range, or if no section has been added for the given117/// index.118Expected<NormalizedSection &> findSectionByIndex(unsigned Index) {119auto I = IndexToSection.find(Index);120if (I == IndexToSection.end())121return make_error<JITLinkError>("No section recorded for index " +122formatv("{0:d}", Index));123return I->second;124}125126/// Try to get the symbol at the given index. Will return an error if the127/// given index is out of range, or if no symbol has been added for the given128/// index.129Expected<NormalizedSymbol &> findSymbolByIndex(uint64_t Index) {130auto I = IndexToSymbol.find(Index);131if (I == IndexToSymbol.end())132return make_error<JITLinkError>("No symbol at index " +133formatv("{0:d}", Index));134assert(I->second && "Null symbol at index");135return *I->second;136}137138/// Returns the symbol with the highest address not greater than the search139/// address, or null if no such symbol exists.140Symbol *getSymbolByAddress(NormalizedSection &NSec,141orc::ExecutorAddr Address) {142auto I = NSec.CanonicalSymbols.upper_bound(Address);143if (I == NSec.CanonicalSymbols.begin())144return nullptr;145return std::prev(I)->second;146}147148/// Returns the symbol with the highest address not greater than the search149/// address, or an error if no such symbol exists.150Expected<Symbol &> findSymbolByAddress(NormalizedSection &NSec,151orc::ExecutorAddr Address) {152auto *Sym = getSymbolByAddress(NSec, Address);153if (Sym)154if (Address <= Sym->getAddress() + Sym->getSize())155return *Sym;156return make_error<JITLinkError>("No symbol covering address " +157formatv("{0:x16}", Address));158}159160static Linkage getLinkage(uint16_t Desc);161static Scope getScope(StringRef Name, uint8_t Type);162static bool isAltEntry(const NormalizedSymbol &NSym);163164static bool isDebugSection(const NormalizedSection &NSec);165static bool isZeroFillSection(const NormalizedSection &NSec);166167MachO::relocation_info168getRelocationInfo(const object::relocation_iterator RelItr) {169MachO::any_relocation_info ARI =170getObject().getRelocation(RelItr->getRawDataRefImpl());171MachO::relocation_info RI;172RI.r_address = ARI.r_word0;173RI.r_symbolnum = ARI.r_word1 & 0xffffff;174RI.r_pcrel = (ARI.r_word1 >> 24) & 1;175RI.r_length = (ARI.r_word1 >> 25) & 3;176RI.r_extern = (ARI.r_word1 >> 27) & 1;177RI.r_type = (ARI.r_word1 >> 28);178return RI;179}180181private:182static unsigned getPointerSize(const object::MachOObjectFile &Obj);183static llvm::endianness getEndianness(const object::MachOObjectFile &Obj);184185void setCanonicalSymbol(NormalizedSection &NSec, Symbol &Sym) {186auto *&CanonicalSymEntry = NSec.CanonicalSymbols[Sym.getAddress()];187// There should be no symbol at this address, or, if there is,188// it should be a zero-sized symbol from an empty section (which189// we can safely override).190assert((!CanonicalSymEntry || CanonicalSymEntry->getSize() == 0) &&191"Duplicate canonical symbol at address");192CanonicalSymEntry = &Sym;193}194195Section &getCommonSection();196void addSectionStartSymAndBlock(unsigned SecIndex, Section &GraphSec,197orc::ExecutorAddr Address, const char *Data,198orc::ExecutorAddrDiff Size,199uint32_t Alignment, bool IsLive);200201Error createNormalizedSections();202Error createNormalizedSymbols();203204/// Create graph blocks and symbols for externals, absolutes, commons and205/// all defined symbols in sections without custom parsers.206Error graphifyRegularSymbols();207208/// Create and return a graph symbol for the given normalized symbol.209///210/// NSym's GraphSymbol member will be updated to point at the newly created211/// symbol.212Symbol &createStandardGraphSymbol(NormalizedSymbol &Sym, Block &B,213size_t Size, bool IsText,214bool IsNoDeadStrip, bool IsCanonical);215216/// Create graph blocks and symbols for all sections.217Error graphifySectionsWithCustomParsers();218219/// Graphify cstring section.220Error graphifyCStringSection(NormalizedSection &NSec,221std::vector<NormalizedSymbol *> NSyms);222223// Put the BumpPtrAllocator first so that we don't free any of the underlying224// memory until the Symbol/Addressable destructors have been run.225BumpPtrAllocator Allocator;226227const object::MachOObjectFile &Obj;228std::unique_ptr<LinkGraph> G;229230bool SubsectionsViaSymbols = false;231DenseMap<unsigned, NormalizedSection> IndexToSection;232Section *CommonSection = nullptr;233234DenseMap<uint32_t, NormalizedSymbol *> IndexToSymbol;235StringMap<SectionParserFunction> CustomSectionParserFunctions;236};237238/// A pass to split up __LD,__compact_unwind sections.239class CompactUnwindSplitter {240public:241CompactUnwindSplitter(StringRef CompactUnwindSectionName)242: CompactUnwindSectionName(CompactUnwindSectionName) {}243Error operator()(LinkGraph &G);244245private:246StringRef CompactUnwindSectionName;247};248249} // end namespace jitlink250} // end namespace llvm251252#endif // LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H253254255