1 //===----- MachOLinkGraphBuilder.h - MachO LinkGraph builder ----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Generic MachO LinkGraph building code. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H 14 #define LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H 15 16 #include "llvm/ADT/DenseMap.h" 17 #include "llvm/ADT/StringMap.h" 18 #include "llvm/ExecutionEngine/JITLink/JITLink.h" 19 #include "llvm/Object/MachO.h" 20 21 #include "EHFrameSupportImpl.h" 22 #include "JITLinkGeneric.h" 23 24 #include <list> 25 26 namespace llvm { 27 namespace jitlink { 28 29 class MachOLinkGraphBuilder { 30 public: 31 virtual ~MachOLinkGraphBuilder(); 32 Expected<std::unique_ptr<LinkGraph>> buildGraph(); 33 34 protected: 35 36 struct NormalizedSymbol { 37 friend class MachOLinkGraphBuilder; 38 39 private: 40 NormalizedSymbol(Optional<StringRef> Name, uint64_t Value, uint8_t Type, 41 uint8_t Sect, uint16_t Desc, Linkage L, Scope S) 42 : Name(Name), Value(Value), Type(Type), Sect(Sect), Desc(Desc), L(L), 43 S(S) { 44 assert((!Name || !Name->empty()) && "Name must be none or non-empty"); 45 } 46 47 public: 48 NormalizedSymbol(const NormalizedSymbol &) = delete; 49 NormalizedSymbol &operator=(const NormalizedSymbol &) = delete; 50 NormalizedSymbol(NormalizedSymbol &&) = delete; 51 NormalizedSymbol &operator=(NormalizedSymbol &&) = delete; 52 53 Optional<StringRef> Name; 54 uint64_t Value = 0; 55 uint8_t Type = 0; 56 uint8_t Sect = 0; 57 uint16_t Desc = 0; 58 Linkage L = Linkage::Strong; 59 Scope S = Scope::Default; 60 Symbol *GraphSymbol = nullptr; 61 }; 62 63 // Normalized section representation. Section and segment names are guaranteed 64 // to be null-terminated, hence the extra bytes on SegName and SectName. 65 class NormalizedSection { 66 friend class MachOLinkGraphBuilder; 67 68 private: 69 NormalizedSection() = default; 70 71 public: 72 char SectName[17]; 73 char SegName[17]; 74 orc::ExecutorAddr Address; 75 uint64_t Size = 0; 76 uint64_t Alignment = 0; 77 uint32_t Flags = 0; 78 const char *Data = nullptr; 79 Section *GraphSection = nullptr; 80 std::map<orc::ExecutorAddr, Symbol *> CanonicalSymbols; 81 }; 82 83 using SectionParserFunction = std::function<Error(NormalizedSection &S)>; 84 85 MachOLinkGraphBuilder(const object::MachOObjectFile &Obj, Triple TT, 86 LinkGraph::GetEdgeKindNameFunction GetEdgeKindName); 87 88 LinkGraph &getGraph() const { return *G; } 89 90 const object::MachOObjectFile &getObject() const { return Obj; } 91 92 void addCustomSectionParser(StringRef SectionName, 93 SectionParserFunction Parse); 94 95 virtual Error addRelocations() = 0; 96 97 /// Create a symbol. 98 template <typename... ArgTs> 99 NormalizedSymbol &createNormalizedSymbol(ArgTs &&... Args) { 100 NormalizedSymbol *Sym = reinterpret_cast<NormalizedSymbol *>( 101 Allocator.Allocate<NormalizedSymbol>()); 102 new (Sym) NormalizedSymbol(std::forward<ArgTs>(Args)...); 103 return *Sym; 104 } 105 106 /// Index is zero-based (MachO section indexes are usually one-based) and 107 /// assumed to be in-range. Client is responsible for checking. 108 NormalizedSection &getSectionByIndex(unsigned Index) { 109 auto I = IndexToSection.find(Index); 110 assert(I != IndexToSection.end() && "No section recorded at index"); 111 return I->second; 112 } 113 114 /// Try to get the section at the given index. Will return an error if the 115 /// given index is out of range, or if no section has been added for the given 116 /// index. 117 Expected<NormalizedSection &> findSectionByIndex(unsigned Index) { 118 auto I = IndexToSection.find(Index); 119 if (I == IndexToSection.end()) 120 return make_error<JITLinkError>("No section recorded for index " + 121 formatv("{0:d}", Index)); 122 return I->second; 123 } 124 125 /// Try to get the symbol at the given index. Will return an error if the 126 /// given index is out of range, or if no symbol has been added for the given 127 /// index. 128 Expected<NormalizedSymbol &> findSymbolByIndex(uint64_t Index) { 129 auto I = IndexToSymbol.find(Index); 130 if (I == IndexToSymbol.end()) 131 return make_error<JITLinkError>("No symbol at index " + 132 formatv("{0:d}", Index)); 133 assert(I->second && "Null symbol at index"); 134 return *I->second; 135 } 136 137 /// Returns the symbol with the highest address not greater than the search 138 /// address, or null if no such symbol exists. 139 Symbol *getSymbolByAddress(NormalizedSection &NSec, 140 orc::ExecutorAddr Address) { 141 auto I = NSec.CanonicalSymbols.upper_bound(Address); 142 if (I == NSec.CanonicalSymbols.begin()) 143 return nullptr; 144 return std::prev(I)->second; 145 } 146 147 /// Returns the symbol with the highest address not greater than the search 148 /// address, or an error if no such symbol exists. 149 Expected<Symbol &> findSymbolByAddress(NormalizedSection &NSec, 150 orc::ExecutorAddr Address) { 151 auto *Sym = getSymbolByAddress(NSec, Address); 152 if (Sym) 153 if (Address <= Sym->getAddress() + Sym->getSize()) 154 return *Sym; 155 return make_error<JITLinkError>("No symbol covering address " + 156 formatv("{0:x16}", Address)); 157 } 158 159 static Linkage getLinkage(uint16_t Desc); 160 static Scope getScope(StringRef Name, uint8_t Type); 161 static bool isAltEntry(const NormalizedSymbol &NSym); 162 163 static bool isDebugSection(const NormalizedSection &NSec); 164 static bool isZeroFillSection(const NormalizedSection &NSec); 165 166 MachO::relocation_info 167 getRelocationInfo(const object::relocation_iterator RelItr) { 168 MachO::any_relocation_info ARI = 169 getObject().getRelocation(RelItr->getRawDataRefImpl()); 170 MachO::relocation_info RI; 171 RI.r_address = ARI.r_word0; 172 RI.r_symbolnum = ARI.r_word1 & 0xffffff; 173 RI.r_pcrel = (ARI.r_word1 >> 24) & 1; 174 RI.r_length = (ARI.r_word1 >> 25) & 3; 175 RI.r_extern = (ARI.r_word1 >> 27) & 1; 176 RI.r_type = (ARI.r_word1 >> 28); 177 return RI; 178 } 179 180 private: 181 static unsigned getPointerSize(const object::MachOObjectFile &Obj); 182 static support::endianness getEndianness(const object::MachOObjectFile &Obj); 183 184 void setCanonicalSymbol(NormalizedSection &NSec, Symbol &Sym) { 185 auto *&CanonicalSymEntry = NSec.CanonicalSymbols[Sym.getAddress()]; 186 // There should be no symbol at this address, or, if there is, 187 // it should be a zero-sized symbol from an empty section (which 188 // we can safely override). 189 assert((!CanonicalSymEntry || CanonicalSymEntry->getSize() == 0) && 190 "Duplicate canonical symbol at address"); 191 CanonicalSymEntry = &Sym; 192 } 193 194 Section &getCommonSection(); 195 void addSectionStartSymAndBlock(unsigned SecIndex, Section &GraphSec, 196 orc::ExecutorAddr Address, const char *Data, 197 orc::ExecutorAddrDiff Size, 198 uint32_t Alignment, bool IsLive); 199 200 Error createNormalizedSections(); 201 Error createNormalizedSymbols(); 202 203 /// Create graph blocks and symbols for externals, absolutes, commons and 204 /// all defined symbols in sections without custom parsers. 205 Error graphifyRegularSymbols(); 206 207 /// Create and return a graph symbol for the given normalized symbol. 208 /// 209 /// NSym's GraphSymbol member will be updated to point at the newly created 210 /// symbol. 211 Symbol &createStandardGraphSymbol(NormalizedSymbol &Sym, Block &B, 212 size_t Size, bool IsText, 213 bool IsNoDeadStrip, bool IsCanonical); 214 215 /// Create graph blocks and symbols for all sections. 216 Error graphifySectionsWithCustomParsers(); 217 218 /// Graphify cstring section. 219 Error graphifyCStringSection(NormalizedSection &NSec, 220 std::vector<NormalizedSymbol *> NSyms); 221 222 // Put the BumpPtrAllocator first so that we don't free any of the underlying 223 // memory until the Symbol/Addressable destructors have been run. 224 BumpPtrAllocator Allocator; 225 226 const object::MachOObjectFile &Obj; 227 std::unique_ptr<LinkGraph> G; 228 229 DenseMap<unsigned, NormalizedSection> IndexToSection; 230 Section *CommonSection = nullptr; 231 232 DenseMap<uint32_t, NormalizedSymbol *> IndexToSymbol; 233 StringMap<SectionParserFunction> CustomSectionParserFunctions; 234 }; 235 236 /// A pass to split up __LD,__compact_unwind sections. 237 class CompactUnwindSplitter { 238 public: 239 CompactUnwindSplitter(StringRef CompactUnwindSectionName) 240 : CompactUnwindSectionName(CompactUnwindSectionName) {} 241 Error operator()(LinkGraph &G); 242 243 private: 244 StringRef CompactUnwindSectionName; 245 }; 246 247 } // end namespace jitlink 248 } // end namespace llvm 249 250 #endif // LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H 251