LLVM 19.0.0git
DefineExternalSectionStartAndEndSymbols.h
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Utility class for recognizing external section start and end symbols and
10// transforming them into defined symbols for the start and end blocks of the
11// associated Section.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H
16#define LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H
17
19#include "llvm/Support/Debug.h"
20
21#define DEBUG_TYPE "jitlink"
22
23namespace llvm {
24namespace jitlink {
25
29 : Sec(&Sec), IsStart(IsStart) {}
30 Section *Sec = nullptr;
31 bool IsStart = false;
32};
33
34/// Pass implementation for the createDefineExternalSectionStartAndEndSymbols
35/// function.
36template <typename SymbolIdentifierFunction>
38public:
39 DefineExternalSectionStartAndEndSymbols(SymbolIdentifierFunction F)
40 : F(std::move(F)) {}
41
43
44 // This pass will affect the external symbols set, so copy them out into a
45 // 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) {
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 else
57 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 else
63 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 auto I = SectionRanges.find(&Sec);
75 if (I == SectionRanges.end())
76 I = SectionRanges.insert(std::make_pair(&Sec, SectionRange(Sec))).first;
77 return I->second;
78 }
79
81 SymbolIdentifierFunction F;
82};
83
84/// Returns a JITLink pass (as a function class) that uses the given symbol
85/// identification function to identify external section start and end symbols
86/// (and their associated Section*s) and transform the identified externals
87/// into defined symbols pointing to the start of the first block in the
88/// section and the end of the last (start and end symbols for empty sections
89/// will be transformed into absolute symbols at address 0).
90///
91/// The identification function should be callable as
92///
93/// SectionRangeSymbolDesc (LinkGraph &G, Symbol &Sym)
94///
95/// If Sym is not a section range start or end symbol then a default
96/// constructed SectionRangeSymbolDesc should be returned. If Sym is a start
97/// symbol then SectionRangeSymbolDesc(Sec, true), where Sec is a reference to
98/// the target Section. If Sym is an end symbol then
99/// SectionRangeSymbolDesc(Sec, false) should be returned.
100///
101/// This pass should be run in the PostAllocationPass pipeline, at which point
102/// all blocks should have been assigned their final addresses.
103template <typename SymbolIdentifierFunction>
104DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction>
106 SymbolIdentifierFunction &&F) {
108 std::forward<SymbolIdentifierFunction>(F));
109}
110
111/// ELF section start/end symbol detection.
112inline SectionRangeSymbolDesc
114 constexpr StringRef StartSymbolPrefix = "__start_";
115 constexpr StringRef EndSymbolPrefix = "__stop_";
116
117 auto SymName = Sym.getName();
118 if (SymName.starts_with(StartSymbolPrefix)) {
119 if (auto *Sec =
120 G.findSectionByName(SymName.drop_front(StartSymbolPrefix.size())))
121 return {*Sec, true};
122 } else if (SymName.starts_with(EndSymbolPrefix)) {
123 if (auto *Sec =
124 G.findSectionByName(SymName.drop_front(EndSymbolPrefix.size())))
125 return {*Sec, false};
126 }
127 return {};
128}
129
130/// MachO section start/end symbol detection.
131inline SectionRangeSymbolDesc
133 constexpr StringRef StartSymbolPrefix = "section$start$";
134 constexpr StringRef EndSymbolPrefix = "section$end$";
135
136 auto SymName = Sym.getName();
137 if (SymName.starts_with(StartSymbolPrefix)) {
138 auto [SegName, SecName] =
139 SymName.drop_front(StartSymbolPrefix.size()).split('$');
140 std::string SectionName = (SegName + "," + SecName).str();
141 if (auto *Sec = G.findSectionByName(SectionName))
142 return {*Sec, true};
143 } else if (SymName.starts_with(EndSymbolPrefix)) {
144 auto [SegName, SecName] =
145 SymName.drop_front(EndSymbolPrefix.size()).split('$');
146 std::string SectionName = (SegName + "," + SecName).str();
147 if (auto *Sec = G.findSectionByName(SectionName))
148 return {*Sec, false};
149 }
150 return {};
151}
152
153} // end namespace jitlink
154} // end namespace llvm
155
156#undef DEBUG_TYPE
157
158#endif // LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static Error split(StringRef Str, char Separator, std::pair< StringRef, StringRef > &Split)
Checked version of split, to ensure mandatory subparts.
Definition: DataLayout.cpp:235
Symbol * Sym
Definition: ELF_riscv.cpp:479
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#define G(x, y, z)
Definition: MD5.cpp:56
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:334
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:696
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:605
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
Represents an address in the executor process.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1849
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858