xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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