18bcb0991SDimitry Andric //===----- MachOLinkGraphBuilder.h - MachO LinkGraph builder ----*- C++ -*-===// 28bcb0991SDimitry Andric // 38bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 48bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 58bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68bcb0991SDimitry Andric // 78bcb0991SDimitry Andric //===----------------------------------------------------------------------===// 88bcb0991SDimitry Andric // 98bcb0991SDimitry Andric // Generic MachO LinkGraph building code. 108bcb0991SDimitry Andric // 118bcb0991SDimitry Andric //===----------------------------------------------------------------------===// 128bcb0991SDimitry Andric 138bcb0991SDimitry Andric #ifndef LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H 148bcb0991SDimitry Andric #define LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H 158bcb0991SDimitry Andric 165ffd83dbSDimitry Andric #include "llvm/ADT/DenseMap.h" 175ffd83dbSDimitry Andric #include "llvm/ADT/StringMap.h" 188bcb0991SDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h" 19e8d8bef9SDimitry Andric #include "llvm/Object/MachO.h" 208bcb0991SDimitry Andric 218bcb0991SDimitry Andric #include "EHFrameSupportImpl.h" 228bcb0991SDimitry Andric #include "JITLinkGeneric.h" 238bcb0991SDimitry Andric 248bcb0991SDimitry Andric #include <list> 258bcb0991SDimitry Andric 268bcb0991SDimitry Andric namespace llvm { 278bcb0991SDimitry Andric namespace jitlink { 288bcb0991SDimitry Andric 298bcb0991SDimitry Andric class MachOLinkGraphBuilder { 308bcb0991SDimitry Andric public: 318bcb0991SDimitry Andric virtual ~MachOLinkGraphBuilder(); 328bcb0991SDimitry Andric Expected<std::unique_ptr<LinkGraph>> buildGraph(); 338bcb0991SDimitry Andric 348bcb0991SDimitry Andric protected: 358bcb0991SDimitry Andric 368bcb0991SDimitry Andric struct NormalizedSymbol { 378bcb0991SDimitry Andric friend class MachOLinkGraphBuilder; 388bcb0991SDimitry Andric 398bcb0991SDimitry Andric private: NormalizedSymbolNormalizedSymbol40bdd1243dSDimitry Andric NormalizedSymbol(std::optional<StringRef> Name, uint64_t Value, 41bdd1243dSDimitry Andric uint8_t Type, uint8_t Sect, uint16_t Desc, Linkage L, 42bdd1243dSDimitry Andric Scope S) 438bcb0991SDimitry Andric : Name(Name), Value(Value), Type(Type), Sect(Sect), Desc(Desc), L(L), 448bcb0991SDimitry Andric S(S) { 458bcb0991SDimitry Andric assert((!Name || !Name->empty()) && "Name must be none or non-empty"); 468bcb0991SDimitry Andric } 478bcb0991SDimitry Andric 488bcb0991SDimitry Andric public: 498bcb0991SDimitry Andric NormalizedSymbol(const NormalizedSymbol &) = delete; 508bcb0991SDimitry Andric NormalizedSymbol &operator=(const NormalizedSymbol &) = delete; 518bcb0991SDimitry Andric NormalizedSymbol(NormalizedSymbol &&) = delete; 528bcb0991SDimitry Andric NormalizedSymbol &operator=(NormalizedSymbol &&) = delete; 538bcb0991SDimitry Andric 54bdd1243dSDimitry Andric std::optional<StringRef> Name; 558bcb0991SDimitry Andric uint64_t Value = 0; 568bcb0991SDimitry Andric uint8_t Type = 0; 578bcb0991SDimitry Andric uint8_t Sect = 0; 588bcb0991SDimitry Andric uint16_t Desc = 0; 598bcb0991SDimitry Andric Linkage L = Linkage::Strong; 608bcb0991SDimitry Andric Scope S = Scope::Default; 618bcb0991SDimitry Andric Symbol *GraphSymbol = nullptr; 628bcb0991SDimitry Andric }; 638bcb0991SDimitry Andric 645ffd83dbSDimitry Andric // Normalized section representation. Section and segment names are guaranteed 655ffd83dbSDimitry Andric // to be null-terminated, hence the extra bytes on SegName and SectName. 668bcb0991SDimitry Andric class NormalizedSection { 678bcb0991SDimitry Andric friend class MachOLinkGraphBuilder; 688bcb0991SDimitry Andric 698bcb0991SDimitry Andric private: 708bcb0991SDimitry Andric NormalizedSection() = default; 718bcb0991SDimitry Andric 728bcb0991SDimitry Andric public: 735ffd83dbSDimitry Andric char SectName[17]; 745ffd83dbSDimitry Andric char SegName[17]; 7504eeddc0SDimitry Andric orc::ExecutorAddr Address; 768bcb0991SDimitry Andric uint64_t Size = 0; 778bcb0991SDimitry Andric uint64_t Alignment = 0; 788bcb0991SDimitry Andric uint32_t Flags = 0; 798bcb0991SDimitry Andric const char *Data = nullptr; 805ffd83dbSDimitry Andric Section *GraphSection = nullptr; 8104eeddc0SDimitry Andric std::map<orc::ExecutorAddr, Symbol *> CanonicalSymbols; 828bcb0991SDimitry Andric }; 838bcb0991SDimitry Andric 848bcb0991SDimitry Andric using SectionParserFunction = std::function<Error(NormalizedSection &S)>; 858bcb0991SDimitry Andric 86fe6060f1SDimitry Andric MachOLinkGraphBuilder(const object::MachOObjectFile &Obj, Triple TT, 8706c3fb27SDimitry Andric SubtargetFeatures Features, 88fe6060f1SDimitry Andric LinkGraph::GetEdgeKindNameFunction GetEdgeKindName); 898bcb0991SDimitry Andric getGraph()908bcb0991SDimitry Andric LinkGraph &getGraph() const { return *G; } 918bcb0991SDimitry Andric getObject()928bcb0991SDimitry Andric const object::MachOObjectFile &getObject() const { return Obj; } 938bcb0991SDimitry Andric 948bcb0991SDimitry Andric void addCustomSectionParser(StringRef SectionName, 958bcb0991SDimitry Andric SectionParserFunction Parse); 968bcb0991SDimitry Andric 978bcb0991SDimitry Andric virtual Error addRelocations() = 0; 988bcb0991SDimitry Andric 998bcb0991SDimitry Andric /// Create a symbol. 1008bcb0991SDimitry Andric template <typename... ArgTs> createNormalizedSymbol(ArgTs &&...Args)1018bcb0991SDimitry Andric NormalizedSymbol &createNormalizedSymbol(ArgTs &&... Args) { 1028bcb0991SDimitry Andric NormalizedSymbol *Sym = reinterpret_cast<NormalizedSymbol *>( 1038bcb0991SDimitry Andric Allocator.Allocate<NormalizedSymbol>()); 1048bcb0991SDimitry Andric new (Sym) NormalizedSymbol(std::forward<ArgTs>(Args)...); 1058bcb0991SDimitry Andric return *Sym; 1068bcb0991SDimitry Andric } 1078bcb0991SDimitry Andric 1088bcb0991SDimitry Andric /// Index is zero-based (MachO section indexes are usually one-based) and 1098bcb0991SDimitry Andric /// assumed to be in-range. Client is responsible for checking. getSectionByIndex(unsigned Index)1108bcb0991SDimitry Andric NormalizedSection &getSectionByIndex(unsigned Index) { 1118bcb0991SDimitry Andric auto I = IndexToSection.find(Index); 1128bcb0991SDimitry Andric assert(I != IndexToSection.end() && "No section recorded at index"); 1138bcb0991SDimitry Andric return I->second; 1148bcb0991SDimitry Andric } 1158bcb0991SDimitry Andric 1168bcb0991SDimitry Andric /// Try to get the section at the given index. Will return an error if the 1178bcb0991SDimitry Andric /// given index is out of range, or if no section has been added for the given 1188bcb0991SDimitry Andric /// index. findSectionByIndex(unsigned Index)1198bcb0991SDimitry Andric Expected<NormalizedSection &> findSectionByIndex(unsigned Index) { 1208bcb0991SDimitry Andric auto I = IndexToSection.find(Index); 1218bcb0991SDimitry Andric if (I == IndexToSection.end()) 1228bcb0991SDimitry Andric return make_error<JITLinkError>("No section recorded for index " + 1235ffd83dbSDimitry Andric formatv("{0:d}", Index)); 1248bcb0991SDimitry Andric return I->second; 1258bcb0991SDimitry Andric } 1268bcb0991SDimitry Andric 1278bcb0991SDimitry Andric /// Try to get the symbol at the given index. Will return an error if the 1288bcb0991SDimitry Andric /// given index is out of range, or if no symbol has been added for the given 1298bcb0991SDimitry Andric /// index. findSymbolByIndex(uint64_t Index)1308bcb0991SDimitry Andric Expected<NormalizedSymbol &> findSymbolByIndex(uint64_t Index) { 131349cc55cSDimitry Andric auto I = IndexToSymbol.find(Index); 132349cc55cSDimitry Andric if (I == IndexToSymbol.end()) 1338bcb0991SDimitry Andric return make_error<JITLinkError>("No symbol at index " + 1345ffd83dbSDimitry Andric formatv("{0:d}", Index)); 135349cc55cSDimitry Andric assert(I->second && "Null symbol at index"); 136349cc55cSDimitry Andric return *I->second; 1378bcb0991SDimitry Andric } 1388bcb0991SDimitry Andric 1398bcb0991SDimitry Andric /// Returns the symbol with the highest address not greater than the search 1408bcb0991SDimitry Andric /// address, or null if no such symbol exists. getSymbolByAddress(NormalizedSection & NSec,orc::ExecutorAddr Address)141349cc55cSDimitry Andric Symbol *getSymbolByAddress(NormalizedSection &NSec, 14204eeddc0SDimitry Andric orc::ExecutorAddr Address) { 143349cc55cSDimitry Andric auto I = NSec.CanonicalSymbols.upper_bound(Address); 144349cc55cSDimitry Andric if (I == NSec.CanonicalSymbols.begin()) 1458bcb0991SDimitry Andric return nullptr; 1468bcb0991SDimitry Andric return std::prev(I)->second; 1478bcb0991SDimitry Andric } 1488bcb0991SDimitry Andric 1498bcb0991SDimitry Andric /// Returns the symbol with the highest address not greater than the search 1508bcb0991SDimitry Andric /// address, or an error if no such symbol exists. findSymbolByAddress(NormalizedSection & NSec,orc::ExecutorAddr Address)151349cc55cSDimitry Andric Expected<Symbol &> findSymbolByAddress(NormalizedSection &NSec, 15204eeddc0SDimitry Andric orc::ExecutorAddr Address) { 153349cc55cSDimitry Andric auto *Sym = getSymbolByAddress(NSec, Address); 1548bcb0991SDimitry Andric if (Sym) 155349cc55cSDimitry Andric if (Address <= Sym->getAddress() + Sym->getSize()) 1568bcb0991SDimitry Andric return *Sym; 1578bcb0991SDimitry Andric return make_error<JITLinkError>("No symbol covering address " + 1588bcb0991SDimitry Andric formatv("{0:x16}", Address)); 1598bcb0991SDimitry Andric } 1608bcb0991SDimitry Andric 1618bcb0991SDimitry Andric static Linkage getLinkage(uint16_t Desc); 1628bcb0991SDimitry Andric static Scope getScope(StringRef Name, uint8_t Type); 1638bcb0991SDimitry Andric static bool isAltEntry(const NormalizedSymbol &NSym); 1648bcb0991SDimitry Andric 1655ffd83dbSDimitry Andric static bool isDebugSection(const NormalizedSection &NSec); 166fe6060f1SDimitry Andric static bool isZeroFillSection(const NormalizedSection &NSec); 1675ffd83dbSDimitry Andric 1685ffd83dbSDimitry Andric MachO::relocation_info getRelocationInfo(const object::relocation_iterator RelItr)1695ffd83dbSDimitry Andric getRelocationInfo(const object::relocation_iterator RelItr) { 1705ffd83dbSDimitry Andric MachO::any_relocation_info ARI = 1715ffd83dbSDimitry Andric getObject().getRelocation(RelItr->getRawDataRefImpl()); 1725ffd83dbSDimitry Andric MachO::relocation_info RI; 1735ffd83dbSDimitry Andric RI.r_address = ARI.r_word0; 1745ffd83dbSDimitry Andric RI.r_symbolnum = ARI.r_word1 & 0xffffff; 1755ffd83dbSDimitry Andric RI.r_pcrel = (ARI.r_word1 >> 24) & 1; 1765ffd83dbSDimitry Andric RI.r_length = (ARI.r_word1 >> 25) & 3; 1775ffd83dbSDimitry Andric RI.r_extern = (ARI.r_word1 >> 27) & 1; 1785ffd83dbSDimitry Andric RI.r_type = (ARI.r_word1 >> 28); 1795ffd83dbSDimitry Andric return RI; 1805ffd83dbSDimitry Andric } 1815ffd83dbSDimitry Andric 1828bcb0991SDimitry Andric private: 1838bcb0991SDimitry Andric static unsigned getPointerSize(const object::MachOObjectFile &Obj); 184*5f757f3fSDimitry Andric static llvm::endianness getEndianness(const object::MachOObjectFile &Obj); 1858bcb0991SDimitry Andric setCanonicalSymbol(NormalizedSection & NSec,Symbol & Sym)186349cc55cSDimitry Andric void setCanonicalSymbol(NormalizedSection &NSec, Symbol &Sym) { 187349cc55cSDimitry Andric auto *&CanonicalSymEntry = NSec.CanonicalSymbols[Sym.getAddress()]; 1888bcb0991SDimitry Andric // There should be no symbol at this address, or, if there is, 1898bcb0991SDimitry Andric // it should be a zero-sized symbol from an empty section (which 1908bcb0991SDimitry Andric // we can safely override). 1918bcb0991SDimitry Andric assert((!CanonicalSymEntry || CanonicalSymEntry->getSize() == 0) && 1928bcb0991SDimitry Andric "Duplicate canonical symbol at address"); 1938bcb0991SDimitry Andric CanonicalSymEntry = &Sym; 1948bcb0991SDimitry Andric } 1958bcb0991SDimitry Andric 1968bcb0991SDimitry Andric Section &getCommonSection(); 197349cc55cSDimitry Andric void addSectionStartSymAndBlock(unsigned SecIndex, Section &GraphSec, 19804eeddc0SDimitry Andric orc::ExecutorAddr Address, const char *Data, 19904eeddc0SDimitry Andric orc::ExecutorAddrDiff Size, 20004eeddc0SDimitry Andric uint32_t Alignment, bool IsLive); 2018bcb0991SDimitry Andric 2028bcb0991SDimitry Andric Error createNormalizedSections(); 2038bcb0991SDimitry Andric Error createNormalizedSymbols(); 2048bcb0991SDimitry Andric 2058bcb0991SDimitry Andric /// Create graph blocks and symbols for externals, absolutes, commons and 2068bcb0991SDimitry Andric /// all defined symbols in sections without custom parsers. 2078bcb0991SDimitry Andric Error graphifyRegularSymbols(); 2088bcb0991SDimitry Andric 209fe6060f1SDimitry Andric /// Create and return a graph symbol for the given normalized symbol. 210fe6060f1SDimitry Andric /// 211fe6060f1SDimitry Andric /// NSym's GraphSymbol member will be updated to point at the newly created 212fe6060f1SDimitry Andric /// symbol. 213fe6060f1SDimitry Andric Symbol &createStandardGraphSymbol(NormalizedSymbol &Sym, Block &B, 214fe6060f1SDimitry Andric size_t Size, bool IsText, 215fe6060f1SDimitry Andric bool IsNoDeadStrip, bool IsCanonical); 216fe6060f1SDimitry Andric 2178bcb0991SDimitry Andric /// Create graph blocks and symbols for all sections. 2188bcb0991SDimitry Andric Error graphifySectionsWithCustomParsers(); 2198bcb0991SDimitry Andric 220fe6060f1SDimitry Andric /// Graphify cstring section. 221fe6060f1SDimitry Andric Error graphifyCStringSection(NormalizedSection &NSec, 222fe6060f1SDimitry Andric std::vector<NormalizedSymbol *> NSyms); 223fe6060f1SDimitry Andric 2248bcb0991SDimitry Andric // Put the BumpPtrAllocator first so that we don't free any of the underlying 2258bcb0991SDimitry Andric // memory until the Symbol/Addressable destructors have been run. 2268bcb0991SDimitry Andric BumpPtrAllocator Allocator; 2278bcb0991SDimitry Andric 2288bcb0991SDimitry Andric const object::MachOObjectFile &Obj; 2298bcb0991SDimitry Andric std::unique_ptr<LinkGraph> G; 2308bcb0991SDimitry Andric 231bdd1243dSDimitry Andric bool SubsectionsViaSymbols = false; 2328bcb0991SDimitry Andric DenseMap<unsigned, NormalizedSection> IndexToSection; 2338bcb0991SDimitry Andric Section *CommonSection = nullptr; 2348bcb0991SDimitry Andric 2358bcb0991SDimitry Andric DenseMap<uint32_t, NormalizedSymbol *> IndexToSymbol; 2368bcb0991SDimitry Andric StringMap<SectionParserFunction> CustomSectionParserFunctions; 2378bcb0991SDimitry Andric }; 2388bcb0991SDimitry Andric 239349cc55cSDimitry Andric /// A pass to split up __LD,__compact_unwind sections. 240349cc55cSDimitry Andric class CompactUnwindSplitter { 241349cc55cSDimitry Andric public: CompactUnwindSplitter(StringRef CompactUnwindSectionName)242349cc55cSDimitry Andric CompactUnwindSplitter(StringRef CompactUnwindSectionName) 243349cc55cSDimitry Andric : CompactUnwindSectionName(CompactUnwindSectionName) {} 244349cc55cSDimitry Andric Error operator()(LinkGraph &G); 245349cc55cSDimitry Andric 246349cc55cSDimitry Andric private: 247349cc55cSDimitry Andric StringRef CompactUnwindSectionName; 248349cc55cSDimitry Andric }; 249349cc55cSDimitry Andric 2508bcb0991SDimitry Andric } // end namespace jitlink 2518bcb0991SDimitry Andric } // end namespace llvm 2528bcb0991SDimitry Andric 2538bcb0991SDimitry Andric #endif // LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H 254