1*fe6060f1SDimitry Andric //===--------- DefineExternalSectionStartAndEndSymbols.h --------*- C++ -*-===// 2*fe6060f1SDimitry Andric // 3*fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*fe6060f1SDimitry Andric // 7*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8*fe6060f1SDimitry Andric // 9*fe6060f1SDimitry Andric // Utility class for recognizing external section start and end symbols and 10*fe6060f1SDimitry Andric // transforming them into defined symbols for the start and end blocks of the 11*fe6060f1SDimitry Andric // associated Section. 12*fe6060f1SDimitry Andric // 13*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 14*fe6060f1SDimitry Andric 15*fe6060f1SDimitry Andric #ifndef LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H 16*fe6060f1SDimitry Andric #define LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H 17*fe6060f1SDimitry Andric 18*fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h" 19*fe6060f1SDimitry Andric #include "llvm/Support/Debug.h" 20*fe6060f1SDimitry Andric 21*fe6060f1SDimitry Andric #define DEBUG_TYPE "jitlink" 22*fe6060f1SDimitry Andric 23*fe6060f1SDimitry Andric namespace llvm { 24*fe6060f1SDimitry Andric namespace jitlink { 25*fe6060f1SDimitry Andric 26*fe6060f1SDimitry Andric struct SectionRangeSymbolDesc { 27*fe6060f1SDimitry Andric SectionRangeSymbolDesc() = default; 28*fe6060f1SDimitry Andric SectionRangeSymbolDesc(Section &Sec, bool IsStart) 29*fe6060f1SDimitry Andric : Sec(&Sec), IsStart(IsStart) {} 30*fe6060f1SDimitry Andric Section *Sec = nullptr; 31*fe6060f1SDimitry Andric bool IsStart = false; 32*fe6060f1SDimitry Andric }; 33*fe6060f1SDimitry Andric 34*fe6060f1SDimitry Andric /// Pass implementation for the createDefineExternalSectionStartAndEndSymbols 35*fe6060f1SDimitry Andric /// function. 36*fe6060f1SDimitry Andric template <typename SymbolIdentifierFunction> 37*fe6060f1SDimitry Andric class DefineExternalSectionStartAndEndSymbols { 38*fe6060f1SDimitry Andric public: 39*fe6060f1SDimitry Andric DefineExternalSectionStartAndEndSymbols(SymbolIdentifierFunction F) 40*fe6060f1SDimitry Andric : F(std::move(F)) {} 41*fe6060f1SDimitry Andric 42*fe6060f1SDimitry Andric Error operator()(LinkGraph &G) { 43*fe6060f1SDimitry Andric 44*fe6060f1SDimitry Andric // This pass will affect the external symbols set, so copy them out into a 45*fe6060f1SDimitry Andric // vector and iterate over that. 46*fe6060f1SDimitry Andric std::vector<Symbol *> Externals(G.external_symbols().begin(), 47*fe6060f1SDimitry Andric G.external_symbols().end()); 48*fe6060f1SDimitry Andric 49*fe6060f1SDimitry Andric for (auto *Sym : Externals) { 50*fe6060f1SDimitry Andric SectionRangeSymbolDesc D = F(G, *Sym); 51*fe6060f1SDimitry Andric if (D.Sec) { 52*fe6060f1SDimitry Andric auto &SR = getSectionRange(*D.Sec); 53*fe6060f1SDimitry Andric if (D.IsStart) { 54*fe6060f1SDimitry Andric if (SR.empty()) 55*fe6060f1SDimitry Andric G.makeAbsolute(*Sym, 0); 56*fe6060f1SDimitry Andric else 57*fe6060f1SDimitry Andric G.makeDefined(*Sym, *SR.getFirstBlock(), 0, 0, Linkage::Strong, 58*fe6060f1SDimitry Andric Scope::Local, false); 59*fe6060f1SDimitry Andric } else { 60*fe6060f1SDimitry Andric if (SR.empty()) 61*fe6060f1SDimitry Andric G.makeAbsolute(*Sym, 0); 62*fe6060f1SDimitry Andric else 63*fe6060f1SDimitry Andric G.makeDefined(*Sym, *SR.getLastBlock(), 64*fe6060f1SDimitry Andric SR.getLastBlock()->getSize(), 0, Linkage::Strong, 65*fe6060f1SDimitry Andric Scope::Local, false); 66*fe6060f1SDimitry Andric } 67*fe6060f1SDimitry Andric } 68*fe6060f1SDimitry Andric } 69*fe6060f1SDimitry Andric return Error::success(); 70*fe6060f1SDimitry Andric } 71*fe6060f1SDimitry Andric 72*fe6060f1SDimitry Andric private: 73*fe6060f1SDimitry Andric SectionRange &getSectionRange(Section &Sec) { 74*fe6060f1SDimitry Andric auto I = SectionRanges.find(&Sec); 75*fe6060f1SDimitry Andric if (I == SectionRanges.end()) 76*fe6060f1SDimitry Andric I = SectionRanges.insert(std::make_pair(&Sec, SectionRange(Sec))).first; 77*fe6060f1SDimitry Andric return I->second; 78*fe6060f1SDimitry Andric } 79*fe6060f1SDimitry Andric 80*fe6060f1SDimitry Andric DenseMap<Section *, SectionRange> SectionRanges; 81*fe6060f1SDimitry Andric SymbolIdentifierFunction F; 82*fe6060f1SDimitry Andric }; 83*fe6060f1SDimitry Andric 84*fe6060f1SDimitry Andric /// Returns a JITLink pass (as a function class) that uses the given symbol 85*fe6060f1SDimitry Andric /// identification function to identify external section start and end symbols 86*fe6060f1SDimitry Andric /// (and their associated Section*s) and transform the identified externals 87*fe6060f1SDimitry Andric /// into defined symbols pointing to the start of the first block in the 88*fe6060f1SDimitry Andric /// section and the end of the last (start and end symbols for empty sections 89*fe6060f1SDimitry Andric /// will be transformed into absolute symbols at address 0). 90*fe6060f1SDimitry Andric /// 91*fe6060f1SDimitry Andric /// The identification function should be callable as 92*fe6060f1SDimitry Andric /// 93*fe6060f1SDimitry Andric /// SectionRangeSymbolDesc (LinkGraph &G, Symbol &Sym) 94*fe6060f1SDimitry Andric /// 95*fe6060f1SDimitry Andric /// If Sym is not a section range start or end symbol then a default 96*fe6060f1SDimitry Andric /// constructed SectionRangeSymbolDesc should be returned. If Sym is a start 97*fe6060f1SDimitry Andric /// symbol then SectionRangeSymbolDesc(Sec, true), where Sec is a reference to 98*fe6060f1SDimitry Andric /// the target Section. If Sym is an end symbol then 99*fe6060f1SDimitry Andric /// SectionRangeSymbolDesc(Sec, false) should be returned. 100*fe6060f1SDimitry Andric /// 101*fe6060f1SDimitry Andric /// This pass should be run in the PostAllocationPass pipeline, at which point 102*fe6060f1SDimitry Andric /// all blocks should have been assigned their final addresses. 103*fe6060f1SDimitry Andric template <typename SymbolIdentifierFunction> 104*fe6060f1SDimitry Andric DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction> 105*fe6060f1SDimitry Andric createDefineExternalSectionStartAndEndSymbolsPass( 106*fe6060f1SDimitry Andric SymbolIdentifierFunction &&F) { 107*fe6060f1SDimitry Andric return DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction>( 108*fe6060f1SDimitry Andric std::forward<SymbolIdentifierFunction>(F)); 109*fe6060f1SDimitry Andric } 110*fe6060f1SDimitry Andric 111*fe6060f1SDimitry Andric } // end namespace jitlink 112*fe6060f1SDimitry Andric } // end namespace llvm 113*fe6060f1SDimitry Andric 114*fe6060f1SDimitry Andric #undef DEBUG_TYPE 115*fe6060f1SDimitry Andric 116*fe6060f1SDimitry Andric #endif // LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H 117