Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/DefineExternalSectionStartAndEndSymbols.h
35271 views
//===--------- DefineExternalSectionStartAndEndSymbols.h --------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Utility class for recognizing external section start and end symbols and9// transforming them into defined symbols for the start and end blocks of the10// associated Section.11//12//===----------------------------------------------------------------------===//1314#ifndef LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H15#define LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H1617#include "llvm/ExecutionEngine/JITLink/JITLink.h"18#include "llvm/Support/Debug.h"1920#define DEBUG_TYPE "jitlink"2122namespace llvm {23namespace jitlink {2425struct SectionRangeSymbolDesc {26SectionRangeSymbolDesc() = default;27SectionRangeSymbolDesc(Section &Sec, bool IsStart)28: Sec(&Sec), IsStart(IsStart) {}29Section *Sec = nullptr;30bool IsStart = false;31};3233/// Pass implementation for the createDefineExternalSectionStartAndEndSymbols34/// function.35template <typename SymbolIdentifierFunction>36class DefineExternalSectionStartAndEndSymbols {37public:38DefineExternalSectionStartAndEndSymbols(SymbolIdentifierFunction F)39: F(std::move(F)) {}4041Error operator()(LinkGraph &G) {4243// This pass will affect the external symbols set, so copy them out into a44// vector and iterate over that.45std::vector<Symbol *> Externals(G.external_symbols().begin(),46G.external_symbols().end());4748for (auto *Sym : Externals) {49SectionRangeSymbolDesc D = F(G, *Sym);50if (D.Sec) {51auto &SR = getSectionRange(*D.Sec);52if (D.IsStart) {53if (SR.empty())54G.makeAbsolute(*Sym, orc::ExecutorAddr());55else56G.makeDefined(*Sym, *SR.getFirstBlock(), 0, 0, Linkage::Strong,57Scope::Local, false);58} else {59if (SR.empty())60G.makeAbsolute(*Sym, orc::ExecutorAddr());61else62G.makeDefined(*Sym, *SR.getLastBlock(),63SR.getLastBlock()->getSize(), 0, Linkage::Strong,64Scope::Local, false);65}66}67}68return Error::success();69}7071private:72SectionRange &getSectionRange(Section &Sec) {73auto I = SectionRanges.find(&Sec);74if (I == SectionRanges.end())75I = SectionRanges.insert(std::make_pair(&Sec, SectionRange(Sec))).first;76return I->second;77}7879DenseMap<Section *, SectionRange> SectionRanges;80SymbolIdentifierFunction F;81};8283/// Returns a JITLink pass (as a function class) that uses the given symbol84/// identification function to identify external section start and end symbols85/// (and their associated Section*s) and transform the identified externals86/// into defined symbols pointing to the start of the first block in the87/// section and the end of the last (start and end symbols for empty sections88/// will be transformed into absolute symbols at address 0).89///90/// The identification function should be callable as91///92/// SectionRangeSymbolDesc (LinkGraph &G, Symbol &Sym)93///94/// If Sym is not a section range start or end symbol then a default95/// constructed SectionRangeSymbolDesc should be returned. If Sym is a start96/// symbol then SectionRangeSymbolDesc(Sec, true), where Sec is a reference to97/// the target Section. If Sym is an end symbol then98/// SectionRangeSymbolDesc(Sec, false) should be returned.99///100/// This pass should be run in the PostAllocationPass pipeline, at which point101/// all blocks should have been assigned their final addresses.102template <typename SymbolIdentifierFunction>103DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction>104createDefineExternalSectionStartAndEndSymbolsPass(105SymbolIdentifierFunction &&F) {106return DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction>(107std::forward<SymbolIdentifierFunction>(F));108}109110/// ELF section start/end symbol detection.111inline SectionRangeSymbolDesc112identifyELFSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym) {113constexpr StringRef StartSymbolPrefix = "__start_";114constexpr StringRef EndSymbolPrefix = "__stop_";115116auto SymName = Sym.getName();117if (SymName.starts_with(StartSymbolPrefix)) {118if (auto *Sec =119G.findSectionByName(SymName.drop_front(StartSymbolPrefix.size())))120return {*Sec, true};121} else if (SymName.starts_with(EndSymbolPrefix)) {122if (auto *Sec =123G.findSectionByName(SymName.drop_front(EndSymbolPrefix.size())))124return {*Sec, false};125}126return {};127}128129/// MachO section start/end symbol detection.130inline SectionRangeSymbolDesc131identifyMachOSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym) {132constexpr StringRef StartSymbolPrefix = "section$start$";133constexpr StringRef EndSymbolPrefix = "section$end$";134135auto SymName = Sym.getName();136if (SymName.starts_with(StartSymbolPrefix)) {137auto [SegName, SecName] =138SymName.drop_front(StartSymbolPrefix.size()).split('$');139std::string SectionName = (SegName + "," + SecName).str();140if (auto *Sec = G.findSectionByName(SectionName))141return {*Sec, true};142} else if (SymName.starts_with(EndSymbolPrefix)) {143auto [SegName, SecName] =144SymName.drop_front(EndSymbolPrefix.size()).split('$');145std::string SectionName = (SegName + "," + SecName).str();146if (auto *Sec = G.findSectionByName(SectionName))147return {*Sec, false};148}149return {};150}151152} // end namespace jitlink153} // end namespace llvm154155#undef DEBUG_TYPE156157#endif // LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H158159160