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" 19*e8d8bef9SDimitry 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: 408bcb0991SDimitry Andric NormalizedSymbol(Optional<StringRef> Name, uint64_t Value, uint8_t Type, 418bcb0991SDimitry Andric uint8_t Sect, uint16_t Desc, Linkage L, Scope S) 428bcb0991SDimitry Andric : Name(Name), Value(Value), Type(Type), Sect(Sect), Desc(Desc), L(L), 438bcb0991SDimitry Andric S(S) { 448bcb0991SDimitry Andric assert((!Name || !Name->empty()) && "Name must be none or non-empty"); 458bcb0991SDimitry Andric } 468bcb0991SDimitry Andric 478bcb0991SDimitry Andric public: 488bcb0991SDimitry Andric NormalizedSymbol(const NormalizedSymbol &) = delete; 498bcb0991SDimitry Andric NormalizedSymbol &operator=(const NormalizedSymbol &) = delete; 508bcb0991SDimitry Andric NormalizedSymbol(NormalizedSymbol &&) = delete; 518bcb0991SDimitry Andric NormalizedSymbol &operator=(NormalizedSymbol &&) = delete; 528bcb0991SDimitry Andric 538bcb0991SDimitry Andric Optional<StringRef> Name; 548bcb0991SDimitry Andric uint64_t Value = 0; 558bcb0991SDimitry Andric uint8_t Type = 0; 568bcb0991SDimitry Andric uint8_t Sect = 0; 578bcb0991SDimitry Andric uint16_t Desc = 0; 588bcb0991SDimitry Andric Linkage L = Linkage::Strong; 598bcb0991SDimitry Andric Scope S = Scope::Default; 608bcb0991SDimitry Andric Symbol *GraphSymbol = nullptr; 618bcb0991SDimitry Andric }; 628bcb0991SDimitry Andric 635ffd83dbSDimitry Andric // Normalized section representation. Section and segment names are guaranteed 645ffd83dbSDimitry Andric // to be null-terminated, hence the extra bytes on SegName and SectName. 658bcb0991SDimitry Andric class NormalizedSection { 668bcb0991SDimitry Andric friend class MachOLinkGraphBuilder; 678bcb0991SDimitry Andric 688bcb0991SDimitry Andric private: 698bcb0991SDimitry Andric NormalizedSection() = default; 708bcb0991SDimitry Andric 718bcb0991SDimitry Andric public: 725ffd83dbSDimitry Andric char SectName[17]; 735ffd83dbSDimitry Andric char SegName[17]; 748bcb0991SDimitry Andric uint64_t Address = 0; 758bcb0991SDimitry Andric uint64_t Size = 0; 768bcb0991SDimitry Andric uint64_t Alignment = 0; 778bcb0991SDimitry Andric uint32_t Flags = 0; 788bcb0991SDimitry Andric const char *Data = nullptr; 795ffd83dbSDimitry Andric Section *GraphSection = nullptr; 808bcb0991SDimitry Andric }; 818bcb0991SDimitry Andric 828bcb0991SDimitry Andric using SectionParserFunction = std::function<Error(NormalizedSection &S)>; 838bcb0991SDimitry Andric 84*e8d8bef9SDimitry Andric MachOLinkGraphBuilder(const object::MachOObjectFile &Obj, Triple TT); 858bcb0991SDimitry Andric 868bcb0991SDimitry Andric LinkGraph &getGraph() const { return *G; } 878bcb0991SDimitry Andric 888bcb0991SDimitry Andric const object::MachOObjectFile &getObject() const { return Obj; } 898bcb0991SDimitry Andric 908bcb0991SDimitry Andric void addCustomSectionParser(StringRef SectionName, 918bcb0991SDimitry Andric SectionParserFunction Parse); 928bcb0991SDimitry Andric 938bcb0991SDimitry Andric virtual Error addRelocations() = 0; 948bcb0991SDimitry Andric 958bcb0991SDimitry Andric /// Create a symbol. 968bcb0991SDimitry Andric template <typename... ArgTs> 978bcb0991SDimitry Andric NormalizedSymbol &createNormalizedSymbol(ArgTs &&... Args) { 988bcb0991SDimitry Andric NormalizedSymbol *Sym = reinterpret_cast<NormalizedSymbol *>( 998bcb0991SDimitry Andric Allocator.Allocate<NormalizedSymbol>()); 1008bcb0991SDimitry Andric new (Sym) NormalizedSymbol(std::forward<ArgTs>(Args)...); 1018bcb0991SDimitry Andric return *Sym; 1028bcb0991SDimitry Andric } 1038bcb0991SDimitry Andric 1048bcb0991SDimitry Andric /// Index is zero-based (MachO section indexes are usually one-based) and 1058bcb0991SDimitry Andric /// assumed to be in-range. Client is responsible for checking. 1068bcb0991SDimitry Andric NormalizedSection &getSectionByIndex(unsigned Index) { 1078bcb0991SDimitry Andric auto I = IndexToSection.find(Index); 1088bcb0991SDimitry Andric assert(I != IndexToSection.end() && "No section recorded at index"); 1098bcb0991SDimitry Andric return I->second; 1108bcb0991SDimitry Andric } 1118bcb0991SDimitry Andric 1128bcb0991SDimitry Andric /// Try to get the section at the given index. Will return an error if the 1138bcb0991SDimitry Andric /// given index is out of range, or if no section has been added for the given 1148bcb0991SDimitry Andric /// index. 1158bcb0991SDimitry Andric Expected<NormalizedSection &> findSectionByIndex(unsigned Index) { 1168bcb0991SDimitry Andric auto I = IndexToSection.find(Index); 1178bcb0991SDimitry Andric if (I == IndexToSection.end()) 1188bcb0991SDimitry Andric return make_error<JITLinkError>("No section recorded for index " + 1195ffd83dbSDimitry Andric formatv("{0:d}", Index)); 1208bcb0991SDimitry Andric return I->second; 1218bcb0991SDimitry Andric } 1228bcb0991SDimitry Andric 1238bcb0991SDimitry Andric /// Try to get the symbol at the given index. Will return an error if the 1248bcb0991SDimitry Andric /// given index is out of range, or if no symbol has been added for the given 1258bcb0991SDimitry Andric /// index. 1268bcb0991SDimitry Andric Expected<NormalizedSymbol &> findSymbolByIndex(uint64_t Index) { 1278bcb0991SDimitry Andric if (Index >= IndexToSymbol.size()) 1288bcb0991SDimitry Andric return make_error<JITLinkError>("Symbol index out of range"); 1298bcb0991SDimitry Andric auto *Sym = IndexToSymbol[Index]; 1308bcb0991SDimitry Andric if (!Sym) 1318bcb0991SDimitry Andric return make_error<JITLinkError>("No symbol at index " + 1325ffd83dbSDimitry Andric formatv("{0:d}", Index)); 1338bcb0991SDimitry Andric return *Sym; 1348bcb0991SDimitry Andric } 1358bcb0991SDimitry Andric 1368bcb0991SDimitry Andric /// Returns the symbol with the highest address not greater than the search 1378bcb0991SDimitry Andric /// address, or null if no such symbol exists. 1388bcb0991SDimitry Andric Symbol *getSymbolByAddress(JITTargetAddress Address) { 1398bcb0991SDimitry Andric auto I = AddrToCanonicalSymbol.upper_bound(Address); 1408bcb0991SDimitry Andric if (I == AddrToCanonicalSymbol.begin()) 1418bcb0991SDimitry Andric return nullptr; 1428bcb0991SDimitry Andric return std::prev(I)->second; 1438bcb0991SDimitry Andric } 1448bcb0991SDimitry Andric 1458bcb0991SDimitry Andric /// Returns the symbol with the highest address not greater than the search 1468bcb0991SDimitry Andric /// address, or an error if no such symbol exists. 1478bcb0991SDimitry Andric Expected<Symbol &> findSymbolByAddress(JITTargetAddress Address) { 1488bcb0991SDimitry Andric auto *Sym = getSymbolByAddress(Address); 1498bcb0991SDimitry Andric if (Sym) 1508bcb0991SDimitry Andric if (Address < Sym->getAddress() + Sym->getSize()) 1518bcb0991SDimitry Andric return *Sym; 1528bcb0991SDimitry Andric return make_error<JITLinkError>("No symbol covering address " + 1538bcb0991SDimitry Andric formatv("{0:x16}", Address)); 1548bcb0991SDimitry Andric } 1558bcb0991SDimitry Andric 1568bcb0991SDimitry Andric static Linkage getLinkage(uint16_t Desc); 1578bcb0991SDimitry Andric static Scope getScope(StringRef Name, uint8_t Type); 1588bcb0991SDimitry Andric static bool isAltEntry(const NormalizedSymbol &NSym); 1598bcb0991SDimitry Andric 1605ffd83dbSDimitry Andric static bool isDebugSection(const NormalizedSection &NSec); 1615ffd83dbSDimitry Andric 1625ffd83dbSDimitry Andric MachO::relocation_info 1635ffd83dbSDimitry Andric getRelocationInfo(const object::relocation_iterator RelItr) { 1645ffd83dbSDimitry Andric MachO::any_relocation_info ARI = 1655ffd83dbSDimitry Andric getObject().getRelocation(RelItr->getRawDataRefImpl()); 1665ffd83dbSDimitry Andric MachO::relocation_info RI; 1675ffd83dbSDimitry Andric RI.r_address = ARI.r_word0; 1685ffd83dbSDimitry Andric RI.r_symbolnum = ARI.r_word1 & 0xffffff; 1695ffd83dbSDimitry Andric RI.r_pcrel = (ARI.r_word1 >> 24) & 1; 1705ffd83dbSDimitry Andric RI.r_length = (ARI.r_word1 >> 25) & 3; 1715ffd83dbSDimitry Andric RI.r_extern = (ARI.r_word1 >> 27) & 1; 1725ffd83dbSDimitry Andric RI.r_type = (ARI.r_word1 >> 28); 1735ffd83dbSDimitry Andric return RI; 1745ffd83dbSDimitry Andric } 1755ffd83dbSDimitry Andric 1768bcb0991SDimitry Andric private: 1778bcb0991SDimitry Andric static unsigned getPointerSize(const object::MachOObjectFile &Obj); 1788bcb0991SDimitry Andric static support::endianness getEndianness(const object::MachOObjectFile &Obj); 1798bcb0991SDimitry Andric 1808bcb0991SDimitry Andric void setCanonicalSymbol(Symbol &Sym) { 1818bcb0991SDimitry Andric auto *&CanonicalSymEntry = AddrToCanonicalSymbol[Sym.getAddress()]; 1828bcb0991SDimitry Andric // There should be no symbol at this address, or, if there is, 1838bcb0991SDimitry Andric // it should be a zero-sized symbol from an empty section (which 1848bcb0991SDimitry Andric // we can safely override). 1858bcb0991SDimitry Andric assert((!CanonicalSymEntry || CanonicalSymEntry->getSize() == 0) && 1868bcb0991SDimitry Andric "Duplicate canonical symbol at address"); 1878bcb0991SDimitry Andric CanonicalSymEntry = &Sym; 1888bcb0991SDimitry Andric } 1898bcb0991SDimitry Andric 1908bcb0991SDimitry Andric Section &getCommonSection(); 1918bcb0991SDimitry Andric void addSectionStartSymAndBlock(Section &GraphSec, uint64_t Address, 1928bcb0991SDimitry Andric const char *Data, uint64_t Size, 1938bcb0991SDimitry Andric uint32_t Alignment, bool IsLive); 1948bcb0991SDimitry Andric 1958bcb0991SDimitry Andric Error createNormalizedSections(); 1968bcb0991SDimitry Andric Error createNormalizedSymbols(); 1978bcb0991SDimitry Andric 1988bcb0991SDimitry Andric /// Create graph blocks and symbols for externals, absolutes, commons and 1998bcb0991SDimitry Andric /// all defined symbols in sections without custom parsers. 2008bcb0991SDimitry Andric Error graphifyRegularSymbols(); 2018bcb0991SDimitry Andric 2028bcb0991SDimitry Andric /// Create graph blocks and symbols for all sections. 2038bcb0991SDimitry Andric Error graphifySectionsWithCustomParsers(); 2048bcb0991SDimitry Andric 2058bcb0991SDimitry Andric // Put the BumpPtrAllocator first so that we don't free any of the underlying 2068bcb0991SDimitry Andric // memory until the Symbol/Addressable destructors have been run. 2078bcb0991SDimitry Andric BumpPtrAllocator Allocator; 2088bcb0991SDimitry Andric 2098bcb0991SDimitry Andric const object::MachOObjectFile &Obj; 2108bcb0991SDimitry Andric std::unique_ptr<LinkGraph> G; 2118bcb0991SDimitry Andric 2128bcb0991SDimitry Andric DenseMap<unsigned, NormalizedSection> IndexToSection; 2138bcb0991SDimitry Andric Section *CommonSection = nullptr; 2148bcb0991SDimitry Andric 2158bcb0991SDimitry Andric DenseMap<uint32_t, NormalizedSymbol *> IndexToSymbol; 2168bcb0991SDimitry Andric std::map<JITTargetAddress, Symbol *> AddrToCanonicalSymbol; 2178bcb0991SDimitry Andric StringMap<SectionParserFunction> CustomSectionParserFunctions; 2188bcb0991SDimitry Andric }; 2198bcb0991SDimitry Andric 2208bcb0991SDimitry Andric } // end namespace jitlink 2218bcb0991SDimitry Andric } // end namespace llvm 2228bcb0991SDimitry Andric 2238bcb0991SDimitry Andric #endif // LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H 224