10a74ec32SLang Hames //===--------- DefineExternalSectionStartAndEndSymbols.h --------*- C++ -*-===// 20a74ec32SLang Hames // 30a74ec32SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40a74ec32SLang Hames // See https://llvm.org/LICENSE.txt for license information. 50a74ec32SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60a74ec32SLang Hames // 70a74ec32SLang Hames //===----------------------------------------------------------------------===// 80a74ec32SLang Hames // 90a74ec32SLang Hames // Utility class for recognizing external section start and end symbols and 100a74ec32SLang Hames // transforming them into defined symbols for the start and end blocks of the 110a74ec32SLang Hames // associated Section. 120a74ec32SLang Hames // 130a74ec32SLang Hames //===----------------------------------------------------------------------===// 140a74ec32SLang Hames 150a74ec32SLang Hames #ifndef LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H 160a74ec32SLang Hames #define LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H 170a74ec32SLang Hames 180a74ec32SLang Hames #include "llvm/ExecutionEngine/JITLink/JITLink.h" 190a74ec32SLang Hames #include "llvm/Support/Debug.h" 200a74ec32SLang Hames 210a74ec32SLang Hames #define DEBUG_TYPE "jitlink" 220a74ec32SLang Hames 230a74ec32SLang Hames namespace llvm { 240a74ec32SLang Hames namespace jitlink { 250a74ec32SLang Hames 260a74ec32SLang Hames struct SectionRangeSymbolDesc { 270a74ec32SLang Hames SectionRangeSymbolDesc() = default; 280a74ec32SLang Hames SectionRangeSymbolDesc(Section &Sec, bool IsStart) 290a74ec32SLang Hames : Sec(&Sec), IsStart(IsStart) {} 300a74ec32SLang Hames Section *Sec = nullptr; 310a74ec32SLang Hames bool IsStart = false; 320a74ec32SLang Hames }; 330a74ec32SLang Hames 340a74ec32SLang Hames /// Pass implementation for the createDefineExternalSectionStartAndEndSymbols 350a74ec32SLang Hames /// function. 360a74ec32SLang Hames template <typename SymbolIdentifierFunction> 370a74ec32SLang Hames class DefineExternalSectionStartAndEndSymbols { 380a74ec32SLang Hames public: 390a74ec32SLang Hames DefineExternalSectionStartAndEndSymbols(SymbolIdentifierFunction F) 400a74ec32SLang Hames : F(std::move(F)) {} 410a74ec32SLang Hames 420a74ec32SLang Hames Error operator()(LinkGraph &G) { 43fc36a511SLang Hames 44fc36a511SLang Hames // This pass will affect the external symbols set, so copy them out into a 45fc36a511SLang Hames // vector and iterate over that. 46fc36a511SLang Hames std::vector<Symbol *> Externals(G.external_symbols().begin(), 47fc36a511SLang Hames G.external_symbols().end()); 48fc36a511SLang Hames 49fc36a511SLang Hames for (auto *Sym : Externals) { 500a74ec32SLang Hames SectionRangeSymbolDesc D = F(G, *Sym); 510a74ec32SLang Hames if (D.Sec) { 520a74ec32SLang Hames auto &SR = getSectionRange(*D.Sec); 530a74ec32SLang Hames if (D.IsStart) { 54fc36a511SLang Hames if (SR.empty()) 55118e953bSLang Hames G.makeAbsolute(*Sym, orc::ExecutorAddr()); 560a74ec32SLang Hames else 570a74ec32SLang Hames G.makeDefined(*Sym, *SR.getFirstBlock(), 0, 0, Linkage::Strong, 580a74ec32SLang Hames Scope::Local, false); 590a74ec32SLang Hames } else { 60fc36a511SLang Hames if (SR.empty()) 61118e953bSLang Hames G.makeAbsolute(*Sym, orc::ExecutorAddr()); 620a74ec32SLang Hames else 630a74ec32SLang Hames G.makeDefined(*Sym, *SR.getLastBlock(), 640a74ec32SLang Hames SR.getLastBlock()->getSize(), 0, Linkage::Strong, 650a74ec32SLang Hames Scope::Local, false); 660a74ec32SLang Hames } 670a74ec32SLang Hames } 680a74ec32SLang Hames } 690a74ec32SLang Hames return Error::success(); 700a74ec32SLang Hames } 710a74ec32SLang Hames 720a74ec32SLang Hames private: 730a74ec32SLang Hames SectionRange &getSectionRange(Section &Sec) { 74c219ebd9SKazu Hirata return SectionRanges.try_emplace(&Sec, Sec).first->second; 750a74ec32SLang Hames } 760a74ec32SLang Hames 770a74ec32SLang Hames DenseMap<Section *, SectionRange> SectionRanges; 780a74ec32SLang Hames SymbolIdentifierFunction F; 790a74ec32SLang Hames }; 800a74ec32SLang Hames 810a74ec32SLang Hames /// Returns a JITLink pass (as a function class) that uses the given symbol 820a74ec32SLang Hames /// identification function to identify external section start and end symbols 830a74ec32SLang Hames /// (and their associated Section*s) and transform the identified externals 840a74ec32SLang Hames /// into defined symbols pointing to the start of the first block in the 850a74ec32SLang Hames /// section and the end of the last (start and end symbols for empty sections 860a74ec32SLang Hames /// will be transformed into absolute symbols at address 0). 870a74ec32SLang Hames /// 880a74ec32SLang Hames /// The identification function should be callable as 890a74ec32SLang Hames /// 900a74ec32SLang Hames /// SectionRangeSymbolDesc (LinkGraph &G, Symbol &Sym) 910a74ec32SLang Hames /// 920a74ec32SLang Hames /// If Sym is not a section range start or end symbol then a default 930a74ec32SLang Hames /// constructed SectionRangeSymbolDesc should be returned. If Sym is a start 940a74ec32SLang Hames /// symbol then SectionRangeSymbolDesc(Sec, true), where Sec is a reference to 950a74ec32SLang Hames /// the target Section. If Sym is an end symbol then 960a74ec32SLang Hames /// SectionRangeSymbolDesc(Sec, false) should be returned. 970a74ec32SLang Hames /// 980a74ec32SLang Hames /// This pass should be run in the PostAllocationPass pipeline, at which point 990a74ec32SLang Hames /// all blocks should have been assigned their final addresses. 1000a74ec32SLang Hames template <typename SymbolIdentifierFunction> 1010a74ec32SLang Hames DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction> 1020a74ec32SLang Hames createDefineExternalSectionStartAndEndSymbolsPass( 1030a74ec32SLang Hames SymbolIdentifierFunction &&F) { 1040a74ec32SLang Hames return DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction>( 1050a74ec32SLang Hames std::forward<SymbolIdentifierFunction>(F)); 1060a74ec32SLang Hames } 1070a74ec32SLang Hames 108488a1873SLang Hames /// ELF section start/end symbol detection. 109488a1873SLang Hames inline SectionRangeSymbolDesc 110488a1873SLang Hames identifyELFSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym) { 111488a1873SLang Hames constexpr StringRef StartSymbolPrefix = "__start_"; 112488a1873SLang Hames constexpr StringRef EndSymbolPrefix = "__stop_"; 113488a1873SLang Hames 114488a1873SLang Hames auto SymName = Sym.getName(); 115*2ccf7ed2SJared Wyles if ((*SymName).starts_with(StartSymbolPrefix)) { 116*2ccf7ed2SJared Wyles if (auto *Sec = G.findSectionByName( 117*2ccf7ed2SJared Wyles (*SymName).drop_front(StartSymbolPrefix.size()))) 118488a1873SLang Hames return {*Sec, true}; 119*2ccf7ed2SJared Wyles } else if ((*SymName).starts_with(EndSymbolPrefix)) { 120488a1873SLang Hames if (auto *Sec = 121*2ccf7ed2SJared Wyles G.findSectionByName((*SymName).drop_front(EndSymbolPrefix.size()))) 122488a1873SLang Hames return {*Sec, false}; 123488a1873SLang Hames } 124488a1873SLang Hames return {}; 125488a1873SLang Hames } 126488a1873SLang Hames 127c4d58815SLang Hames /// MachO section start/end symbol detection. 128c4d58815SLang Hames inline SectionRangeSymbolDesc 129c4d58815SLang Hames identifyMachOSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym) { 130c4d58815SLang Hames constexpr StringRef StartSymbolPrefix = "section$start$"; 131c4d58815SLang Hames constexpr StringRef EndSymbolPrefix = "section$end$"; 132c4d58815SLang Hames 133c4d58815SLang Hames auto SymName = Sym.getName(); 134*2ccf7ed2SJared Wyles if ((*SymName).starts_with(StartSymbolPrefix)) { 135c4d58815SLang Hames auto [SegName, SecName] = 136*2ccf7ed2SJared Wyles (*SymName).drop_front(StartSymbolPrefix.size()).split('$'); 137c4d58815SLang Hames std::string SectionName = (SegName + "," + SecName).str(); 138c4d58815SLang Hames if (auto *Sec = G.findSectionByName(SectionName)) 139c4d58815SLang Hames return {*Sec, true}; 140*2ccf7ed2SJared Wyles } else if ((*SymName).starts_with(EndSymbolPrefix)) { 141c4d58815SLang Hames auto [SegName, SecName] = 142*2ccf7ed2SJared Wyles (*SymName).drop_front(EndSymbolPrefix.size()).split('$'); 143c4d58815SLang Hames std::string SectionName = (SegName + "," + SecName).str(); 144c4d58815SLang Hames if (auto *Sec = G.findSectionByName(SectionName)) 145c4d58815SLang Hames return {*Sec, false}; 146c4d58815SLang Hames } 147c4d58815SLang Hames return {}; 148c4d58815SLang Hames } 149c4d58815SLang Hames 1500a74ec32SLang Hames } // end namespace jitlink 1510a74ec32SLang Hames } // end namespace llvm 1520a74ec32SLang Hames 1530a74ec32SLang Hames #undef DEBUG_TYPE 1540a74ec32SLang Hames 1550a74ec32SLang Hames #endif // LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H 156