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