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: 40*bdd1243dSDimitry Andric NormalizedSymbol(std::optional<StringRef> Name, uint64_t Value, 41*bdd1243dSDimitry Andric uint8_t Type, uint8_t Sect, uint16_t Desc, Linkage L, 42*bdd1243dSDimitry 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 54*bdd1243dSDimitry 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, 87fe6060f1SDimitry Andric LinkGraph::GetEdgeKindNameFunction GetEdgeKindName); 888bcb0991SDimitry Andric 898bcb0991SDimitry Andric LinkGraph &getGraph() const { return *G; } 908bcb0991SDimitry Andric 918bcb0991SDimitry Andric const object::MachOObjectFile &getObject() const { return Obj; } 928bcb0991SDimitry Andric 938bcb0991SDimitry Andric void addCustomSectionParser(StringRef SectionName, 948bcb0991SDimitry Andric SectionParserFunction Parse); 958bcb0991SDimitry Andric 968bcb0991SDimitry Andric virtual Error addRelocations() = 0; 978bcb0991SDimitry Andric 988bcb0991SDimitry Andric /// Create a symbol. 998bcb0991SDimitry Andric template <typename... ArgTs> 1008bcb0991SDimitry Andric NormalizedSymbol &createNormalizedSymbol(ArgTs &&... Args) { 1018bcb0991SDimitry Andric NormalizedSymbol *Sym = reinterpret_cast<NormalizedSymbol *>( 1028bcb0991SDimitry Andric Allocator.Allocate<NormalizedSymbol>()); 1038bcb0991SDimitry Andric new (Sym) NormalizedSymbol(std::forward<ArgTs>(Args)...); 1048bcb0991SDimitry Andric return *Sym; 1058bcb0991SDimitry Andric } 1068bcb0991SDimitry Andric 1078bcb0991SDimitry Andric /// Index is zero-based (MachO section indexes are usually one-based) and 1088bcb0991SDimitry Andric /// assumed to be in-range. Client is responsible for checking. 1098bcb0991SDimitry Andric NormalizedSection &getSectionByIndex(unsigned Index) { 1108bcb0991SDimitry Andric auto I = IndexToSection.find(Index); 1118bcb0991SDimitry Andric assert(I != IndexToSection.end() && "No section recorded at index"); 1128bcb0991SDimitry Andric return I->second; 1138bcb0991SDimitry Andric } 1148bcb0991SDimitry Andric 1158bcb0991SDimitry Andric /// Try to get the section at the given index. Will return an error if the 1168bcb0991SDimitry Andric /// given index is out of range, or if no section has been added for the given 1178bcb0991SDimitry Andric /// index. 1188bcb0991SDimitry Andric Expected<NormalizedSection &> findSectionByIndex(unsigned Index) { 1198bcb0991SDimitry Andric auto I = IndexToSection.find(Index); 1208bcb0991SDimitry Andric if (I == IndexToSection.end()) 1218bcb0991SDimitry Andric return make_error<JITLinkError>("No section recorded for index " + 1225ffd83dbSDimitry Andric formatv("{0:d}", Index)); 1238bcb0991SDimitry Andric return I->second; 1248bcb0991SDimitry Andric } 1258bcb0991SDimitry Andric 1268bcb0991SDimitry Andric /// Try to get the symbol at the given index. Will return an error if the 1278bcb0991SDimitry Andric /// given index is out of range, or if no symbol has been added for the given 1288bcb0991SDimitry Andric /// index. 1298bcb0991SDimitry Andric Expected<NormalizedSymbol &> findSymbolByIndex(uint64_t Index) { 130349cc55cSDimitry Andric auto I = IndexToSymbol.find(Index); 131349cc55cSDimitry Andric if (I == IndexToSymbol.end()) 1328bcb0991SDimitry Andric return make_error<JITLinkError>("No symbol at index " + 1335ffd83dbSDimitry Andric formatv("{0:d}", Index)); 134349cc55cSDimitry Andric assert(I->second && "Null symbol at index"); 135349cc55cSDimitry Andric return *I->second; 1368bcb0991SDimitry Andric } 1378bcb0991SDimitry Andric 1388bcb0991SDimitry Andric /// Returns the symbol with the highest address not greater than the search 1398bcb0991SDimitry Andric /// address, or null if no such symbol exists. 140349cc55cSDimitry Andric Symbol *getSymbolByAddress(NormalizedSection &NSec, 14104eeddc0SDimitry Andric orc::ExecutorAddr Address) { 142349cc55cSDimitry Andric auto I = NSec.CanonicalSymbols.upper_bound(Address); 143349cc55cSDimitry Andric if (I == NSec.CanonicalSymbols.begin()) 1448bcb0991SDimitry Andric return nullptr; 1458bcb0991SDimitry Andric return std::prev(I)->second; 1468bcb0991SDimitry Andric } 1478bcb0991SDimitry Andric 1488bcb0991SDimitry Andric /// Returns the symbol with the highest address not greater than the search 1498bcb0991SDimitry Andric /// address, or an error if no such symbol exists. 150349cc55cSDimitry Andric Expected<Symbol &> findSymbolByAddress(NormalizedSection &NSec, 15104eeddc0SDimitry Andric orc::ExecutorAddr Address) { 152349cc55cSDimitry Andric auto *Sym = getSymbolByAddress(NSec, Address); 1538bcb0991SDimitry Andric if (Sym) 154349cc55cSDimitry Andric if (Address <= Sym->getAddress() + Sym->getSize()) 1558bcb0991SDimitry Andric return *Sym; 1568bcb0991SDimitry Andric return make_error<JITLinkError>("No symbol covering address " + 1578bcb0991SDimitry Andric formatv("{0:x16}", Address)); 1588bcb0991SDimitry Andric } 1598bcb0991SDimitry Andric 1608bcb0991SDimitry Andric static Linkage getLinkage(uint16_t Desc); 1618bcb0991SDimitry Andric static Scope getScope(StringRef Name, uint8_t Type); 1628bcb0991SDimitry Andric static bool isAltEntry(const NormalizedSymbol &NSym); 1638bcb0991SDimitry Andric 1645ffd83dbSDimitry Andric static bool isDebugSection(const NormalizedSection &NSec); 165fe6060f1SDimitry Andric static bool isZeroFillSection(const NormalizedSection &NSec); 1665ffd83dbSDimitry Andric 1675ffd83dbSDimitry Andric MachO::relocation_info 1685ffd83dbSDimitry Andric getRelocationInfo(const object::relocation_iterator RelItr) { 1695ffd83dbSDimitry Andric MachO::any_relocation_info ARI = 1705ffd83dbSDimitry Andric getObject().getRelocation(RelItr->getRawDataRefImpl()); 1715ffd83dbSDimitry Andric MachO::relocation_info RI; 1725ffd83dbSDimitry Andric RI.r_address = ARI.r_word0; 1735ffd83dbSDimitry Andric RI.r_symbolnum = ARI.r_word1 & 0xffffff; 1745ffd83dbSDimitry Andric RI.r_pcrel = (ARI.r_word1 >> 24) & 1; 1755ffd83dbSDimitry Andric RI.r_length = (ARI.r_word1 >> 25) & 3; 1765ffd83dbSDimitry Andric RI.r_extern = (ARI.r_word1 >> 27) & 1; 1775ffd83dbSDimitry Andric RI.r_type = (ARI.r_word1 >> 28); 1785ffd83dbSDimitry Andric return RI; 1795ffd83dbSDimitry Andric } 1805ffd83dbSDimitry Andric 1818bcb0991SDimitry Andric private: 1828bcb0991SDimitry Andric static unsigned getPointerSize(const object::MachOObjectFile &Obj); 1838bcb0991SDimitry Andric static support::endianness getEndianness(const object::MachOObjectFile &Obj); 1848bcb0991SDimitry Andric 185349cc55cSDimitry Andric void setCanonicalSymbol(NormalizedSection &NSec, Symbol &Sym) { 186349cc55cSDimitry Andric auto *&CanonicalSymEntry = NSec.CanonicalSymbols[Sym.getAddress()]; 1878bcb0991SDimitry Andric // There should be no symbol at this address, or, if there is, 1888bcb0991SDimitry Andric // it should be a zero-sized symbol from an empty section (which 1898bcb0991SDimitry Andric // we can safely override). 1908bcb0991SDimitry Andric assert((!CanonicalSymEntry || CanonicalSymEntry->getSize() == 0) && 1918bcb0991SDimitry Andric "Duplicate canonical symbol at address"); 1928bcb0991SDimitry Andric CanonicalSymEntry = &Sym; 1938bcb0991SDimitry Andric } 1948bcb0991SDimitry Andric 1958bcb0991SDimitry Andric Section &getCommonSection(); 196349cc55cSDimitry Andric void addSectionStartSymAndBlock(unsigned SecIndex, Section &GraphSec, 19704eeddc0SDimitry Andric orc::ExecutorAddr Address, const char *Data, 19804eeddc0SDimitry Andric orc::ExecutorAddrDiff Size, 19904eeddc0SDimitry Andric uint32_t Alignment, bool IsLive); 2008bcb0991SDimitry Andric 2018bcb0991SDimitry Andric Error createNormalizedSections(); 2028bcb0991SDimitry Andric Error createNormalizedSymbols(); 2038bcb0991SDimitry Andric 2048bcb0991SDimitry Andric /// Create graph blocks and symbols for externals, absolutes, commons and 2058bcb0991SDimitry Andric /// all defined symbols in sections without custom parsers. 2068bcb0991SDimitry Andric Error graphifyRegularSymbols(); 2078bcb0991SDimitry Andric 208fe6060f1SDimitry Andric /// Create and return a graph symbol for the given normalized symbol. 209fe6060f1SDimitry Andric /// 210fe6060f1SDimitry Andric /// NSym's GraphSymbol member will be updated to point at the newly created 211fe6060f1SDimitry Andric /// symbol. 212fe6060f1SDimitry Andric Symbol &createStandardGraphSymbol(NormalizedSymbol &Sym, Block &B, 213fe6060f1SDimitry Andric size_t Size, bool IsText, 214fe6060f1SDimitry Andric bool IsNoDeadStrip, bool IsCanonical); 215fe6060f1SDimitry Andric 2168bcb0991SDimitry Andric /// Create graph blocks and symbols for all sections. 2178bcb0991SDimitry Andric Error graphifySectionsWithCustomParsers(); 2188bcb0991SDimitry Andric 219fe6060f1SDimitry Andric /// Graphify cstring section. 220fe6060f1SDimitry Andric Error graphifyCStringSection(NormalizedSection &NSec, 221fe6060f1SDimitry Andric std::vector<NormalizedSymbol *> NSyms); 222fe6060f1SDimitry Andric 2238bcb0991SDimitry Andric // Put the BumpPtrAllocator first so that we don't free any of the underlying 2248bcb0991SDimitry Andric // memory until the Symbol/Addressable destructors have been run. 2258bcb0991SDimitry Andric BumpPtrAllocator Allocator; 2268bcb0991SDimitry Andric 2278bcb0991SDimitry Andric const object::MachOObjectFile &Obj; 2288bcb0991SDimitry Andric std::unique_ptr<LinkGraph> G; 2298bcb0991SDimitry Andric 230*bdd1243dSDimitry Andric bool SubsectionsViaSymbols = false; 2318bcb0991SDimitry Andric DenseMap<unsigned, NormalizedSection> IndexToSection; 2328bcb0991SDimitry Andric Section *CommonSection = nullptr; 2338bcb0991SDimitry Andric 2348bcb0991SDimitry Andric DenseMap<uint32_t, NormalizedSymbol *> IndexToSymbol; 2358bcb0991SDimitry Andric StringMap<SectionParserFunction> CustomSectionParserFunctions; 2368bcb0991SDimitry Andric }; 2378bcb0991SDimitry Andric 238349cc55cSDimitry Andric /// A pass to split up __LD,__compact_unwind sections. 239349cc55cSDimitry Andric class CompactUnwindSplitter { 240349cc55cSDimitry Andric public: 241349cc55cSDimitry Andric CompactUnwindSplitter(StringRef CompactUnwindSectionName) 242349cc55cSDimitry Andric : CompactUnwindSectionName(CompactUnwindSectionName) {} 243349cc55cSDimitry Andric Error operator()(LinkGraph &G); 244349cc55cSDimitry Andric 245349cc55cSDimitry Andric private: 246349cc55cSDimitry Andric StringRef CompactUnwindSectionName; 247349cc55cSDimitry Andric }; 248349cc55cSDimitry Andric 2498bcb0991SDimitry Andric } // end namespace jitlink 2508bcb0991SDimitry Andric } // end namespace llvm 2518bcb0991SDimitry Andric 2528bcb0991SDimitry Andric #endif // LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H 253