xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Mangling.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
1 //===----------- Mangling.cpp -- Name Mangling Utilities for ORC ----------===//
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 #include "llvm/ExecutionEngine/Orc/Mangling.h"
10 #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
11 #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
12 #include "llvm/IR/Constants.h"
13 #include "llvm/IR/Mangler.h"
14 #include "llvm/Object/ELFObjectFile.h"
15 #include "llvm/Object/MachO.h"
16 #include "llvm/Object/ObjectFile.h"
17 #include "llvm/Support/Debug.h"
18 
19 #define DEBUG_TYPE "orc"
20 
21 namespace llvm {
22 namespace orc {
23 
24 MangleAndInterner::MangleAndInterner(ExecutionSession &ES, const DataLayout &DL)
25     : ES(ES), DL(DL) {}
26 
27 SymbolStringPtr MangleAndInterner::operator()(StringRef Name) {
28   std::string MangledName;
29   {
30     raw_string_ostream MangledNameStream(MangledName);
31     Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
32   }
33   return ES.intern(MangledName);
34 }
35 
36 void IRSymbolMapper::add(ExecutionSession &ES, const ManglingOptions &MO,
37                          ArrayRef<GlobalValue *> GVs,
38                          SymbolFlagsMap &SymbolFlags,
39                          SymbolNameToDefinitionMap *SymbolToDefinition) {
40   if (GVs.empty())
41     return;
42 
43   MangleAndInterner Mangle(ES, GVs[0]->getParent()->getDataLayout());
44   for (auto *G : GVs) {
45     assert(G && "GVs cannot contain null elements");
46     if (!G->hasName() || G->isDeclaration() || G->hasLocalLinkage() ||
47         G->hasAvailableExternallyLinkage() || G->hasAppendingLinkage())
48       continue;
49 
50     if (G->isThreadLocal() && MO.EmulatedTLS) {
51       auto *GV = cast<GlobalVariable>(G);
52 
53       auto Flags = JITSymbolFlags::fromGlobalValue(*GV);
54 
55       auto EmuTLSV = Mangle(("__emutls_v." + GV->getName()).str());
56       SymbolFlags[EmuTLSV] = Flags;
57       if (SymbolToDefinition)
58         (*SymbolToDefinition)[EmuTLSV] = GV;
59 
60       // If this GV has a non-zero initializer we'll need to emit an
61       // __emutls.t symbol too.
62       if (GV->hasInitializer()) {
63         const auto *InitVal = GV->getInitializer();
64 
65         // Skip zero-initializers.
66         if (isa<ConstantAggregateZero>(InitVal))
67           continue;
68         const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
69         if (InitIntValue && InitIntValue->isZero())
70           continue;
71 
72         auto EmuTLST = Mangle(("__emutls_t." + GV->getName()).str());
73         SymbolFlags[EmuTLST] = Flags;
74         if (SymbolToDefinition)
75           (*SymbolToDefinition)[EmuTLST] = GV;
76       }
77       continue;
78     }
79 
80     // Otherwise we just need a normal linker mangling.
81     auto MangledName = Mangle(G->getName());
82     SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(*G);
83     if (SymbolToDefinition)
84       (*SymbolToDefinition)[MangledName] = G;
85   }
86 }
87 
88 static SymbolStringPtr addInitSymbol(SymbolFlagsMap &SymbolFlags,
89                                      ExecutionSession &ES,
90                                      StringRef ObjFileName) {
91   SymbolStringPtr InitSymbol;
92   size_t Counter = 0;
93 
94   do {
95     std::string InitSymString;
96     raw_string_ostream(InitSymString)
97       << "$." << ObjFileName << ".__inits." << Counter++;
98     InitSymbol = ES.intern(InitSymString);
99   } while (SymbolFlags.count(InitSymbol));
100 
101   SymbolFlags[InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
102   return InitSymbol;
103 }
104 
105 static Expected<std::pair<SymbolFlagsMap, SymbolStringPtr>>
106 getMachOObjectFileSymbolInfo(ExecutionSession &ES,
107                              const object::MachOObjectFile &Obj) {
108   SymbolFlagsMap SymbolFlags;
109 
110   for (auto &Sym : Obj.symbols()) {
111     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
112     if (!SymFlagsOrErr)
113       // TODO: Test this error.
114       return SymFlagsOrErr.takeError();
115 
116     // Skip symbols not defined in this object file.
117     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
118       continue;
119 
120     // Skip symbols that are not global.
121     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
122       continue;
123 
124     // Skip symbols that have type SF_File.
125     if (auto SymType = Sym.getType()) {
126       if (*SymType == object::SymbolRef::ST_File)
127         continue;
128     } else
129       return SymType.takeError();
130 
131     auto Name = Sym.getName();
132     if (!Name)
133       return Name.takeError();
134     auto InternedName = ES.intern(*Name);
135     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
136     if (!SymFlags)
137       return SymFlags.takeError();
138 
139     // Strip the 'exported' flag from MachO linker-private symbols.
140     if (Name->startswith("l"))
141       *SymFlags &= ~JITSymbolFlags::Exported;
142 
143     SymbolFlags[InternedName] = std::move(*SymFlags);
144   }
145 
146   SymbolStringPtr InitSymbol;
147   for (auto &Sec : Obj.sections()) {
148     auto SecType = Obj.getSectionType(Sec);
149     if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {
150       InitSymbol = addInitSymbol(SymbolFlags, ES, Obj.getFileName());
151       break;
152     }
153     auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
154     auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
155     if (MachOPlatform::isInitializerSection(SegName, SecName)) {
156       InitSymbol = addInitSymbol(SymbolFlags, ES, Obj.getFileName());
157       break;
158     }
159   }
160 
161   return std::make_pair(std::move(SymbolFlags), std::move(InitSymbol));
162 }
163 
164 static Expected<std::pair<SymbolFlagsMap, SymbolStringPtr>>
165 getELFObjectFileSymbolInfo(ExecutionSession &ES,
166                            const object::ELFObjectFileBase &Obj) {
167   SymbolFlagsMap SymbolFlags;
168   for (auto &Sym : Obj.symbols()) {
169     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
170     if (!SymFlagsOrErr)
171       // TODO: Test this error.
172       return SymFlagsOrErr.takeError();
173 
174     // Skip symbols not defined in this object file.
175     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
176       continue;
177 
178     // Skip symbols that are not global.
179     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
180       continue;
181 
182     // Skip symbols that have type SF_File.
183     if (auto SymType = Sym.getType()) {
184       if (*SymType == object::SymbolRef::ST_File)
185         continue;
186     } else
187       return SymType.takeError();
188 
189     auto Name = Sym.getName();
190     if (!Name)
191       return Name.takeError();
192     auto InternedName = ES.intern(*Name);
193     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
194     if (!SymFlags)
195       return SymFlags.takeError();
196 
197     // ELF STB_GNU_UNIQUE should map to Weak for ORC.
198     if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
199       *SymFlags |= JITSymbolFlags::Weak;
200 
201     SymbolFlags[InternedName] = std::move(*SymFlags);
202   }
203 
204   SymbolStringPtr InitSymbol;
205   for (auto &Sec : Obj.sections()) {
206     if (auto SecName = Sec.getName()) {
207       if (ELFNixPlatform::isInitializerSection(*SecName)) {
208         InitSymbol = addInitSymbol(SymbolFlags, ES, Obj.getFileName());
209         break;
210       }
211     }
212   }
213 
214   return std::make_pair(std::move(SymbolFlags), InitSymbol);
215 }
216 
217 Expected<std::pair<SymbolFlagsMap, SymbolStringPtr>>
218 getGenericObjectFileSymbolInfo(ExecutionSession &ES,
219                                const object::ObjectFile &Obj) {
220   SymbolFlagsMap SymbolFlags;
221   for (auto &Sym : Obj.symbols()) {
222     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
223     if (!SymFlagsOrErr)
224       // TODO: Test this error.
225       return SymFlagsOrErr.takeError();
226 
227     // Skip symbols not defined in this object file.
228     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
229       continue;
230 
231     // Skip symbols that are not global.
232     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
233       continue;
234 
235     // Skip symbols that have type SF_File.
236     if (auto SymType = Sym.getType()) {
237       if (*SymType == object::SymbolRef::ST_File)
238         continue;
239     } else
240       return SymType.takeError();
241 
242     auto Name = Sym.getName();
243     if (!Name)
244       return Name.takeError();
245     auto InternedName = ES.intern(*Name);
246     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
247     if (!SymFlags)
248       return SymFlags.takeError();
249 
250     SymbolFlags[InternedName] = std::move(*SymFlags);
251   }
252 
253   return std::make_pair(std::move(SymbolFlags), nullptr);
254 }
255 
256 Expected<std::pair<SymbolFlagsMap, SymbolStringPtr>>
257 getObjectSymbolInfo(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
258   auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
259 
260   if (!Obj)
261     return Obj.takeError();
262 
263   if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
264     return getMachOObjectFileSymbolInfo(ES, *MachOObj);
265   else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
266     return getELFObjectFileSymbolInfo(ES, *ELFObj);
267 
268   return getGenericObjectFileSymbolInfo(ES, **Obj);
269 }
270 
271 } // End namespace orc.
272 } // End namespace llvm.
273