brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.6 KiB · c7a2f07 Raw
156 lines · c
1//===--------- DefineExternalSectionStartAndEndSymbols.h --------*- 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-exception6//7//===----------------------------------------------------------------------===//8//9// Utility class for recognizing external section start and end symbols and10// transforming them into defined symbols for the start and end blocks of the11// associated Section.12//13//===----------------------------------------------------------------------===//14 15#ifndef LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H16#define LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H17 18#include "llvm/ExecutionEngine/JITLink/JITLink.h"19#include "llvm/Support/Debug.h"20 21#define DEBUG_TYPE "jitlink"22 23namespace llvm {24namespace jitlink {25 26struct SectionRangeSymbolDesc {27  SectionRangeSymbolDesc() = default;28  SectionRangeSymbolDesc(Section &Sec, bool IsStart)29      : Sec(&Sec), IsStart(IsStart) {}30  Section *Sec = nullptr;31  bool IsStart = false;32};33 34/// Pass implementation for the createDefineExternalSectionStartAndEndSymbols35/// function.36template <typename SymbolIdentifierFunction>37class DefineExternalSectionStartAndEndSymbols {38public:39  DefineExternalSectionStartAndEndSymbols(SymbolIdentifierFunction F)40      : F(std::move(F)) {}41 42  Error operator()(LinkGraph &G) {43 44    // This pass will affect the external symbols set, so copy them out into a45    // vector and iterate over that.46    std::vector<Symbol *> Externals(G.external_symbols().begin(),47                                    G.external_symbols().end());48 49    for (auto *Sym : Externals) {50      SectionRangeSymbolDesc D = F(G, *Sym);51      if (D.Sec) {52        auto &SR = getSectionRange(*D.Sec);53        if (D.IsStart) {54          if (SR.empty())55            G.makeAbsolute(*Sym, orc::ExecutorAddr());56          else57            G.makeDefined(*Sym, *SR.getFirstBlock(), 0, 0, Linkage::Strong,58                          Scope::Local, false);59        } else {60          if (SR.empty())61            G.makeAbsolute(*Sym, orc::ExecutorAddr());62          else63            G.makeDefined(*Sym, *SR.getLastBlock(),64                          SR.getLastBlock()->getSize(), 0, Linkage::Strong,65                          Scope::Local, false);66        }67      }68    }69    return Error::success();70  }71 72private:73  SectionRange &getSectionRange(Section &Sec) {74    return SectionRanges.try_emplace(&Sec, Sec).first->second;75  }76 77  DenseMap<Section *, SectionRange> SectionRanges;78  SymbolIdentifierFunction F;79};80 81/// Returns a JITLink pass (as a function class) that uses the given symbol82/// identification function to identify external section start and end symbols83/// (and their associated Section*s) and transform the identified externals84/// into defined symbols pointing to the start of the first block in the85/// section and the end of the last (start and end symbols for empty sections86/// will be transformed into absolute symbols at address 0).87///88/// The identification function should be callable as89///90///   SectionRangeSymbolDesc (LinkGraph &G, Symbol &Sym)91///92/// If Sym is not a section range start or end symbol then a default93/// constructed SectionRangeSymbolDesc should be returned. If Sym is a start94/// symbol then SectionRangeSymbolDesc(Sec, true), where Sec is a reference to95/// the target Section. If Sym is an end symbol then96/// SectionRangeSymbolDesc(Sec, false) should be returned.97///98/// This pass should be run in the PostAllocationPass pipeline, at which point99/// all blocks should have been assigned their final addresses.100template <typename SymbolIdentifierFunction>101DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction>102createDefineExternalSectionStartAndEndSymbolsPass(103    SymbolIdentifierFunction &&F) {104  return DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction>(105      std::forward<SymbolIdentifierFunction>(F));106}107 108/// ELF section start/end symbol detection.109inline SectionRangeSymbolDesc110identifyELFSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym) {111  constexpr StringRef StartSymbolPrefix = "__start_";112  constexpr StringRef EndSymbolPrefix = "__stop_";113 114  auto SymName = Sym.getName();115  if ((*SymName).starts_with(StartSymbolPrefix)) {116    if (auto *Sec = G.findSectionByName(117            (*SymName).drop_front(StartSymbolPrefix.size())))118      return {*Sec, true};119  } else if ((*SymName).starts_with(EndSymbolPrefix)) {120    if (auto *Sec =121            G.findSectionByName((*SymName).drop_front(EndSymbolPrefix.size())))122      return {*Sec, false};123  }124  return {};125}126 127/// MachO section start/end symbol detection.128inline SectionRangeSymbolDesc129identifyMachOSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym) {130  constexpr StringRef StartSymbolPrefix = "section$start$";131  constexpr StringRef EndSymbolPrefix = "section$end$";132 133  auto SymName = Sym.getName();134  if ((*SymName).starts_with(StartSymbolPrefix)) {135    auto [SegName, SecName] =136        (*SymName).drop_front(StartSymbolPrefix.size()).split('$');137    std::string SectionName = (SegName + "," + SecName).str();138    if (auto *Sec = G.findSectionByName(SectionName))139      return {*Sec, true};140  } else if ((*SymName).starts_with(EndSymbolPrefix)) {141    auto [SegName, SecName] =142        (*SymName).drop_front(EndSymbolPrefix.size()).split('$');143    std::string SectionName = (SegName + "," + SecName).str();144    if (auto *Sec = G.findSectionByName(SectionName))145      return {*Sec, false};146  }147  return {};148}149 150} // end namespace jitlink151} // end namespace llvm152 153#undef DEBUG_TYPE154 155#endif // LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H156