xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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:
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*fe6060f1SDimitry Andric   MachOLinkGraphBuilder(const object::MachOObjectFile &Obj, Triple TT,
85*fe6060f1SDimitry Andric                         LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
868bcb0991SDimitry Andric 
878bcb0991SDimitry Andric   LinkGraph &getGraph() const { return *G; }
888bcb0991SDimitry Andric 
898bcb0991SDimitry Andric   const object::MachOObjectFile &getObject() const { return Obj; }
908bcb0991SDimitry Andric 
918bcb0991SDimitry Andric   void addCustomSectionParser(StringRef SectionName,
928bcb0991SDimitry Andric                               SectionParserFunction Parse);
938bcb0991SDimitry Andric 
948bcb0991SDimitry Andric   virtual Error addRelocations() = 0;
958bcb0991SDimitry Andric 
968bcb0991SDimitry Andric   /// Create a symbol.
978bcb0991SDimitry Andric   template <typename... ArgTs>
988bcb0991SDimitry Andric   NormalizedSymbol &createNormalizedSymbol(ArgTs &&... Args) {
998bcb0991SDimitry Andric     NormalizedSymbol *Sym = reinterpret_cast<NormalizedSymbol *>(
1008bcb0991SDimitry Andric         Allocator.Allocate<NormalizedSymbol>());
1018bcb0991SDimitry Andric     new (Sym) NormalizedSymbol(std::forward<ArgTs>(Args)...);
1028bcb0991SDimitry Andric     return *Sym;
1038bcb0991SDimitry Andric   }
1048bcb0991SDimitry Andric 
1058bcb0991SDimitry Andric   /// Index is zero-based (MachO section indexes are usually one-based) and
1068bcb0991SDimitry Andric   /// assumed to be in-range. Client is responsible for checking.
1078bcb0991SDimitry Andric   NormalizedSection &getSectionByIndex(unsigned Index) {
1088bcb0991SDimitry Andric     auto I = IndexToSection.find(Index);
1098bcb0991SDimitry Andric     assert(I != IndexToSection.end() && "No section recorded at index");
1108bcb0991SDimitry Andric     return I->second;
1118bcb0991SDimitry Andric   }
1128bcb0991SDimitry Andric 
1138bcb0991SDimitry Andric   /// Try to get the section at the given index. Will return an error if the
1148bcb0991SDimitry Andric   /// given index is out of range, or if no section has been added for the given
1158bcb0991SDimitry Andric   /// index.
1168bcb0991SDimitry Andric   Expected<NormalizedSection &> findSectionByIndex(unsigned Index) {
1178bcb0991SDimitry Andric     auto I = IndexToSection.find(Index);
1188bcb0991SDimitry Andric     if (I == IndexToSection.end())
1198bcb0991SDimitry Andric       return make_error<JITLinkError>("No section recorded for index " +
1205ffd83dbSDimitry Andric                                       formatv("{0:d}", Index));
1218bcb0991SDimitry Andric     return I->second;
1228bcb0991SDimitry Andric   }
1238bcb0991SDimitry Andric 
1248bcb0991SDimitry Andric   /// Try to get the symbol at the given index. Will return an error if the
1258bcb0991SDimitry Andric   /// given index is out of range, or if no symbol has been added for the given
1268bcb0991SDimitry Andric   /// index.
1278bcb0991SDimitry Andric   Expected<NormalizedSymbol &> findSymbolByIndex(uint64_t Index) {
1288bcb0991SDimitry Andric     if (Index >= IndexToSymbol.size())
1298bcb0991SDimitry Andric       return make_error<JITLinkError>("Symbol index out of range");
1308bcb0991SDimitry Andric     auto *Sym = IndexToSymbol[Index];
1318bcb0991SDimitry Andric     if (!Sym)
1328bcb0991SDimitry Andric       return make_error<JITLinkError>("No symbol at index " +
1335ffd83dbSDimitry Andric                                       formatv("{0:d}", Index));
1348bcb0991SDimitry Andric     return *Sym;
1358bcb0991SDimitry Andric   }
1368bcb0991SDimitry Andric 
1378bcb0991SDimitry Andric   /// Returns the symbol with the highest address not greater than the search
1388bcb0991SDimitry Andric   /// address, or null if no such symbol exists.
1398bcb0991SDimitry Andric   Symbol *getSymbolByAddress(JITTargetAddress Address) {
1408bcb0991SDimitry Andric     auto I = AddrToCanonicalSymbol.upper_bound(Address);
1418bcb0991SDimitry Andric     if (I == AddrToCanonicalSymbol.begin())
1428bcb0991SDimitry Andric       return nullptr;
1438bcb0991SDimitry Andric     return std::prev(I)->second;
1448bcb0991SDimitry Andric   }
1458bcb0991SDimitry Andric 
1468bcb0991SDimitry Andric   /// Returns the symbol with the highest address not greater than the search
1478bcb0991SDimitry Andric   /// address, or an error if no such symbol exists.
1488bcb0991SDimitry Andric   Expected<Symbol &> findSymbolByAddress(JITTargetAddress Address) {
1498bcb0991SDimitry Andric     auto *Sym = getSymbolByAddress(Address);
1508bcb0991SDimitry Andric     if (Sym)
1518bcb0991SDimitry Andric       if (Address < Sym->getAddress() + Sym->getSize())
1528bcb0991SDimitry Andric         return *Sym;
1538bcb0991SDimitry Andric     return make_error<JITLinkError>("No symbol covering address " +
1548bcb0991SDimitry Andric                                     formatv("{0:x16}", Address));
1558bcb0991SDimitry Andric   }
1568bcb0991SDimitry Andric 
1578bcb0991SDimitry Andric   static Linkage getLinkage(uint16_t Desc);
1588bcb0991SDimitry Andric   static Scope getScope(StringRef Name, uint8_t Type);
1598bcb0991SDimitry Andric   static bool isAltEntry(const NormalizedSymbol &NSym);
1608bcb0991SDimitry Andric 
1615ffd83dbSDimitry Andric   static bool isDebugSection(const NormalizedSection &NSec);
162*fe6060f1SDimitry Andric   static bool isZeroFillSection(const NormalizedSection &NSec);
1635ffd83dbSDimitry Andric 
1645ffd83dbSDimitry Andric   MachO::relocation_info
1655ffd83dbSDimitry Andric   getRelocationInfo(const object::relocation_iterator RelItr) {
1665ffd83dbSDimitry Andric     MachO::any_relocation_info ARI =
1675ffd83dbSDimitry Andric         getObject().getRelocation(RelItr->getRawDataRefImpl());
1685ffd83dbSDimitry Andric     MachO::relocation_info RI;
1695ffd83dbSDimitry Andric     RI.r_address = ARI.r_word0;
1705ffd83dbSDimitry Andric     RI.r_symbolnum = ARI.r_word1 & 0xffffff;
1715ffd83dbSDimitry Andric     RI.r_pcrel = (ARI.r_word1 >> 24) & 1;
1725ffd83dbSDimitry Andric     RI.r_length = (ARI.r_word1 >> 25) & 3;
1735ffd83dbSDimitry Andric     RI.r_extern = (ARI.r_word1 >> 27) & 1;
1745ffd83dbSDimitry Andric     RI.r_type = (ARI.r_word1 >> 28);
1755ffd83dbSDimitry Andric     return RI;
1765ffd83dbSDimitry Andric   }
1775ffd83dbSDimitry Andric 
1788bcb0991SDimitry Andric private:
1798bcb0991SDimitry Andric   static unsigned getPointerSize(const object::MachOObjectFile &Obj);
1808bcb0991SDimitry Andric   static support::endianness getEndianness(const object::MachOObjectFile &Obj);
1818bcb0991SDimitry Andric 
1828bcb0991SDimitry Andric   void setCanonicalSymbol(Symbol &Sym) {
1838bcb0991SDimitry Andric     auto *&CanonicalSymEntry = AddrToCanonicalSymbol[Sym.getAddress()];
1848bcb0991SDimitry Andric     // There should be no symbol at this address, or, if there is,
1858bcb0991SDimitry Andric     // it should be a zero-sized symbol from an empty section (which
1868bcb0991SDimitry Andric     // we can safely override).
1878bcb0991SDimitry Andric     assert((!CanonicalSymEntry || CanonicalSymEntry->getSize() == 0) &&
1888bcb0991SDimitry Andric            "Duplicate canonical symbol at address");
1898bcb0991SDimitry Andric     CanonicalSymEntry = &Sym;
1908bcb0991SDimitry Andric   }
1918bcb0991SDimitry Andric 
1928bcb0991SDimitry Andric   Section &getCommonSection();
1938bcb0991SDimitry Andric   void addSectionStartSymAndBlock(Section &GraphSec, uint64_t Address,
1948bcb0991SDimitry Andric                                   const char *Data, uint64_t Size,
1958bcb0991SDimitry Andric                                   uint32_t Alignment, bool IsLive);
1968bcb0991SDimitry Andric 
1978bcb0991SDimitry Andric   Error createNormalizedSections();
1988bcb0991SDimitry Andric   Error createNormalizedSymbols();
1998bcb0991SDimitry Andric 
2008bcb0991SDimitry Andric   /// Create graph blocks and symbols for externals, absolutes, commons and
2018bcb0991SDimitry Andric   /// all defined symbols in sections without custom parsers.
2028bcb0991SDimitry Andric   Error graphifyRegularSymbols();
2038bcb0991SDimitry Andric 
204*fe6060f1SDimitry Andric   /// Create and return a graph symbol for the given normalized symbol.
205*fe6060f1SDimitry Andric   ///
206*fe6060f1SDimitry Andric   /// NSym's GraphSymbol member will be updated to point at the newly created
207*fe6060f1SDimitry Andric   /// symbol.
208*fe6060f1SDimitry Andric   Symbol &createStandardGraphSymbol(NormalizedSymbol &Sym, Block &B,
209*fe6060f1SDimitry Andric                                     size_t Size, bool IsText,
210*fe6060f1SDimitry Andric                                     bool IsNoDeadStrip, bool IsCanonical);
211*fe6060f1SDimitry Andric 
2128bcb0991SDimitry Andric   /// Create graph blocks and symbols for all sections.
2138bcb0991SDimitry Andric   Error graphifySectionsWithCustomParsers();
2148bcb0991SDimitry Andric 
215*fe6060f1SDimitry Andric   /// Graphify cstring section.
216*fe6060f1SDimitry Andric   Error graphifyCStringSection(NormalizedSection &NSec,
217*fe6060f1SDimitry Andric                                std::vector<NormalizedSymbol *> NSyms);
218*fe6060f1SDimitry Andric 
2198bcb0991SDimitry Andric   // Put the BumpPtrAllocator first so that we don't free any of the underlying
2208bcb0991SDimitry Andric   // memory until the Symbol/Addressable destructors have been run.
2218bcb0991SDimitry Andric   BumpPtrAllocator Allocator;
2228bcb0991SDimitry Andric 
2238bcb0991SDimitry Andric   const object::MachOObjectFile &Obj;
2248bcb0991SDimitry Andric   std::unique_ptr<LinkGraph> G;
2258bcb0991SDimitry Andric 
2268bcb0991SDimitry Andric   DenseMap<unsigned, NormalizedSection> IndexToSection;
2278bcb0991SDimitry Andric   Section *CommonSection = nullptr;
2288bcb0991SDimitry Andric 
2298bcb0991SDimitry Andric   DenseMap<uint32_t, NormalizedSymbol *> IndexToSymbol;
2308bcb0991SDimitry Andric   std::map<JITTargetAddress, Symbol *> AddrToCanonicalSymbol;
2318bcb0991SDimitry Andric   StringMap<SectionParserFunction> CustomSectionParserFunctions;
2328bcb0991SDimitry Andric };
2338bcb0991SDimitry Andric 
2348bcb0991SDimitry Andric } // end namespace jitlink
2358bcb0991SDimitry Andric } // end namespace llvm
2368bcb0991SDimitry Andric 
2378bcb0991SDimitry Andric #endif // LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H
238