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 | |
18 | #include "llvm/ExecutionEngine/JITLink/JITLink.h" |
19 | #include "llvm/Support/Debug.h" |
20 | |
21 | #define DEBUG_TYPE "jitlink" |
22 | |
23 | namespace llvm { |
24 | namespace jitlink { |
25 | |
26 | struct 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 createDefineExternalSectionStartAndEndSymbols |
35 | /// function. |
36 | template <typename SymbolIdentifierFunction> |
37 | class DefineExternalSectionStartAndEndSymbols { |
38 | public: |
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 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) { |
50 | SectionRangeSymbolDesc D = F(G, *Sym); |
51 | if (D.Sec) { |
52 | auto &SR = getSectionRange(Sec&: *D.Sec); |
53 | if (D.IsStart) { |
54 | if (SR.empty()) |
55 | G.makeAbsolute(Sym&: *Sym, Address: orc::ExecutorAddr()); |
56 | else |
57 | G.makeDefined(Sym&: *Sym, Content&: *SR.getFirstBlock(), Offset: 0, Size: 0, L: Linkage::Strong, |
58 | S: Scope::Local, IsLive: false); |
59 | } else { |
60 | if (SR.empty()) |
61 | G.makeAbsolute(Sym&: *Sym, Address: orc::ExecutorAddr()); |
62 | else |
63 | G.makeDefined(Sym&: *Sym, Content&: *SR.getLastBlock(), |
64 | Offset: SR.getLastBlock()->getSize(), Size: 0, L: Linkage::Strong, |
65 | S: Scope::Local, IsLive: false); |
66 | } |
67 | } |
68 | } |
69 | return Error::success(); |
70 | } |
71 | |
72 | private: |
73 | SectionRange &getSectionRange(Section &Sec) { |
74 | return SectionRanges.try_emplace(Key: &Sec, Args&: 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 symbol |
82 | /// identification function to identify external section start and end symbols |
83 | /// (and their associated Section*s) and transform the identified externals |
84 | /// into defined symbols pointing to the start of the first block in the |
85 | /// section and the end of the last (start and end symbols for empty sections |
86 | /// will be transformed into absolute symbols at address 0). |
87 | /// |
88 | /// The identification function should be callable as |
89 | /// |
90 | /// SectionRangeSymbolDesc (LinkGraph &G, Symbol &Sym) |
91 | /// |
92 | /// If Sym is not a section range start or end symbol then a default |
93 | /// constructed SectionRangeSymbolDesc should be returned. If Sym is a start |
94 | /// symbol then SectionRangeSymbolDesc(Sec, true), where Sec is a reference to |
95 | /// the target Section. If Sym is an end symbol then |
96 | /// SectionRangeSymbolDesc(Sec, false) should be returned. |
97 | /// |
98 | /// This pass should be run in the PostAllocationPass pipeline, at which point |
99 | /// all blocks should have been assigned their final addresses. |
100 | template <typename SymbolIdentifierFunction> |
101 | DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction> |
102 | createDefineExternalSectionStartAndEndSymbolsPass( |
103 | SymbolIdentifierFunction &&F) { |
104 | return DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction>( |
105 | std::forward<SymbolIdentifierFunction>(F)); |
106 | } |
107 | |
108 | /// ELF section start/end symbol detection. |
109 | inline SectionRangeSymbolDesc |
110 | identifyELFSectionStartAndEndSymbols(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(Prefix: StartSymbolPrefix)) { |
116 | if (auto *Sec = G.findSectionByName( |
117 | Name: (*SymName).drop_front(N: StartSymbolPrefix.size()))) |
118 | return {*Sec, true}; |
119 | } else if ((*SymName).starts_with(Prefix: EndSymbolPrefix)) { |
120 | if (auto *Sec = |
121 | G.findSectionByName(Name: (*SymName).drop_front(N: EndSymbolPrefix.size()))) |
122 | return {*Sec, false}; |
123 | } |
124 | return {}; |
125 | } |
126 | |
127 | /// MachO section start/end symbol detection. |
128 | inline SectionRangeSymbolDesc |
129 | identifyMachOSectionStartAndEndSymbols(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(Prefix: StartSymbolPrefix)) { |
135 | auto [SegName, SecName] = |
136 | (*SymName).drop_front(N: StartSymbolPrefix.size()).split(Separator: '$'); |
137 | std::string SectionName = (SegName + "," + SecName).str(); |
138 | if (auto *Sec = G.findSectionByName(Name: SectionName)) |
139 | return {*Sec, true}; |
140 | } else if ((*SymName).starts_with(Prefix: EndSymbolPrefix)) { |
141 | auto [SegName, SecName] = |
142 | (*SymName).drop_front(N: EndSymbolPrefix.size()).split(Separator: '$'); |
143 | std::string SectionName = (SegName + "," + SecName).str(); |
144 | if (auto *Sec = G.findSectionByName(Name: SectionName)) |
145 | return {*Sec, false}; |
146 | } |
147 | return {}; |
148 | } |
149 | |
150 | } // end namespace jitlink |
151 | } // end namespace llvm |
152 | |
153 | #undef DEBUG_TYPE |
154 | |
155 | #endif // LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H |
156 | |