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<MaterializationUnit::Interface>
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 MaterializationUnit::Interface(std::move(SymbolFlags),
162                                         std::move(InitSymbol));
163 }
164 
165 static Expected<MaterializationUnit::Interface>
166 getELFObjectFileSymbolInfo(ExecutionSession &ES,
167                            const object::ELFObjectFileBase &Obj) {
168   SymbolFlagsMap SymbolFlags;
169   for (auto &Sym : Obj.symbols()) {
170     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
171     if (!SymFlagsOrErr)
172       // TODO: Test this error.
173       return SymFlagsOrErr.takeError();
174 
175     // Skip symbols not defined in this object file.
176     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
177       continue;
178 
179     // Skip symbols that are not global.
180     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
181       continue;
182 
183     // Skip symbols that have type SF_File.
184     if (auto SymType = Sym.getType()) {
185       if (*SymType == object::SymbolRef::ST_File)
186         continue;
187     } else
188       return SymType.takeError();
189 
190     auto Name = Sym.getName();
191     if (!Name)
192       return Name.takeError();
193     auto InternedName = ES.intern(*Name);
194     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
195     if (!SymFlags)
196       return SymFlags.takeError();
197 
198     // ELF STB_GNU_UNIQUE should map to Weak for ORC.
199     if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
200       *SymFlags |= JITSymbolFlags::Weak;
201 
202     SymbolFlags[InternedName] = std::move(*SymFlags);
203   }
204 
205   SymbolStringPtr InitSymbol;
206   for (auto &Sec : Obj.sections()) {
207     if (auto SecName = Sec.getName()) {
208       if (ELFNixPlatform::isInitializerSection(*SecName)) {
209         InitSymbol = addInitSymbol(SymbolFlags, ES, Obj.getFileName());
210         break;
211       }
212     }
213   }
214 
215   return MaterializationUnit::Interface(std::move(SymbolFlags),
216                                         std::move(InitSymbol));
217 }
218 
219 Expected<MaterializationUnit::Interface>
220 getGenericObjectFileSymbolInfo(ExecutionSession &ES,
221                                const object::ObjectFile &Obj) {
222   SymbolFlagsMap SymbolFlags;
223   for (auto &Sym : Obj.symbols()) {
224     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
225     if (!SymFlagsOrErr)
226       // TODO: Test this error.
227       return SymFlagsOrErr.takeError();
228 
229     // Skip symbols not defined in this object file.
230     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
231       continue;
232 
233     // Skip symbols that are not global.
234     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
235       continue;
236 
237     // Skip symbols that have type SF_File.
238     if (auto SymType = Sym.getType()) {
239       if (*SymType == object::SymbolRef::ST_File)
240         continue;
241     } else
242       return SymType.takeError();
243 
244     auto Name = Sym.getName();
245     if (!Name)
246       return Name.takeError();
247     auto InternedName = ES.intern(*Name);
248     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
249     if (!SymFlags)
250       return SymFlags.takeError();
251 
252     SymbolFlags[InternedName] = std::move(*SymFlags);
253   }
254 
255   return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);
256 }
257 
258 Expected<MaterializationUnit::Interface>
259 getObjectInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
260   auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
261 
262   if (!Obj)
263     return Obj.takeError();
264 
265   if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
266     return getMachOObjectFileSymbolInfo(ES, *MachOObj);
267   else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
268     return getELFObjectFileSymbolInfo(ES, *ELFObj);
269 
270   return getGenericObjectFileSymbolInfo(ES, **Obj);
271 }
272 
273 } // End namespace orc.
274 } // End namespace llvm.
275