LLVM 24.0.0git
ObjectFileInterface.cpp
Go to the documentation of this file.
1//===------ ObjectFileInterface.cpp - MU interface utils for objects ------===//
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
12#include "llvm/Object/COFF.h"
14#include "llvm/Object/MachO.h"
17#include <optional>
18
19#define DEBUG_TYPE "orc"
20
21namespace llvm {
22namespace orc {
23
25 StringRef ObjFileName) {
26 assert(!I.InitSymbol && "I already has an init symbol");
27 size_t Counter = 0;
28
29 do {
30 std::string InitSymString;
31 raw_string_ostream(InitSymString)
32 << "$." << ObjFileName << ".__inits." << Counter++;
33 I.InitSymbol = ES.intern(InitSymString);
34 } while (I.SymbolFlags.count(I.InitSymbol));
35
36 I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
37}
38
41 const object::MachOObjectFile &Obj) {
43
44 for (auto &Sym : Obj.symbols()) {
45 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
46 if (!SymFlagsOrErr)
47 // TODO: Test this error.
48 return SymFlagsOrErr.takeError();
49
50 // Skip symbols not defined in this object file.
51 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
52 continue;
53
54 // Skip symbols that are not global.
55 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
56 continue;
57
58 // Skip symbols that have type SF_File.
59 if (auto SymType = Sym.getType()) {
60 if (*SymType == object::SymbolRef::ST_File)
61 continue;
62 } else
63 return SymType.takeError();
64
65 auto Name = Sym.getName();
66 if (!Name)
67 return Name.takeError();
68 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
69 if (!SymFlags)
70 return SymFlags.takeError();
71
72 // Strip the 'exported' flag from MachO linker-private symbols.
73 if (Name->starts_with("l"))
74 *SymFlags &= ~JITSymbolFlags::Exported;
75
76 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
77 }
78
79 for (auto &Sec : Obj.sections()) {
80 auto SecType = Obj.getSectionType(Sec);
82 addInitSymbol(I, ES, Obj.getFileName());
83 break;
84 }
85 auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
86 auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
87 if (isMachOInitializerSection(SegName, SecName)) {
88 addInitSymbol(I, ES, Obj.getFileName());
89 break;
90 }
91 }
92
93 return I;
94}
95
98 const object::ELFObjectFileBase &Obj) {
100
101 for (auto &Sym : Obj.symbols()) {
102 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
103 if (!SymFlagsOrErr)
104 // TODO: Test this error.
105 return SymFlagsOrErr.takeError();
106
107 // Skip symbols not defined in this object file.
108 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
109 continue;
110
111 // Skip symbols that are not global.
112 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
113 continue;
114
115 // Skip symbols that have type SF_File.
116 if (auto SymType = Sym.getType()) {
117 if (*SymType == object::SymbolRef::ST_File)
118 continue;
119 } else
120 return SymType.takeError();
121
122 auto Name = Sym.getName();
123 if (!Name)
124 return Name.takeError();
125
126 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
127 if (!SymFlags)
128 return SymFlags.takeError();
129
130 // ELF STB_GNU_UNIQUE should map to Weak for ORC.
131 if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
132 *SymFlags |= JITSymbolFlags::Weak;
133
134 I.SymbolFlags[ES.intern(std::move(*Name))] = std::move(*SymFlags);
135 }
136
137 for (auto &Sec : Obj.sections()) {
138 if (auto SecName = Sec.getName()) {
139 if (isELFInitializerSection(*SecName)) {
140 addInitSymbol(I, ES, Obj.getFileName());
141 break;
142 }
143 }
144 }
145
146 return I;
147}
148
151 const object::COFFObjectFile &Obj) {
153 std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(
154 Obj.getNumberOfSections() + 1);
155 for (auto &Sym : Obj.symbols()) {
156 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
157 if (!SymFlagsOrErr)
158 // TODO: Test this error.
159 return SymFlagsOrErr.takeError();
160
161 // Handle comdat symbols
162 auto COFFSym = Obj.getCOFFSymbol(Sym);
163 bool IsWeak = false;
164 if (auto *Def = COFFSym.getSectionDefinition()) {
165 auto Sec = Obj.getSection(COFFSym.getSectionNumber());
166 if (!Sec)
167 return Sec.takeError();
168 if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&
169 Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
170 ComdatDefs[COFFSym.getSectionNumber()] = *Def;
171 continue;
172 }
173 }
174 if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&
175 ComdatDefs[COFFSym.getSectionNumber()]) {
176 auto Def = ComdatDefs[COFFSym.getSectionNumber()];
177 if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
178 IsWeak = true;
179 }
180 ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt;
181 } else {
182 // Skip symbols not defined in this object file.
183 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
184 continue;
185 }
186
187 // Skip symbols that are not global.
188 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
189 continue;
190
191 // Skip symbols that have type SF_File.
192 if (auto SymType = Sym.getType()) {
193 if (*SymType == object::SymbolRef::ST_File)
194 continue;
195 } else
196 return SymType.takeError();
197
198 auto Name = Sym.getName();
199 if (!Name)
200 return Name.takeError();
201
202 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
203 if (!SymFlags)
204 return SymFlags.takeError();
205 *SymFlags |= JITSymbolFlags::Exported;
206
207 // Weak external is always a function
208 if (COFFSym.isWeakExternal())
209 *SymFlags |= JITSymbolFlags::Callable;
210
211 if (IsWeak)
212 *SymFlags |= JITSymbolFlags::Weak;
213
214 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
215 }
216
217 for (auto &Sec : Obj.sections()) {
218 if (auto SecName = Sec.getName()) {
219 if (isCOFFInitializerSection(*SecName)) {
220 addInitSymbol(I, ES, Obj.getFileName());
221 break;
222 }
223 } else
224 return SecName.takeError();
225 }
226
227 return I;
228}
229
232 const object::ObjectFile &Obj) {
233
235
236 for (auto &Sym : Obj.symbols()) {
237 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
238 if (!SymFlagsOrErr)
239 return SymFlagsOrErr.takeError();
240 uint32_t Flags = *SymFlagsOrErr;
241
242 // Skip undefined, non global and ST_File
244 continue;
245 if (!(Flags & object::SymbolRef::SF_Global))
246 continue;
247
248 auto SymbolType = Sym.getType();
249 if (!SymbolType)
250 return SymbolType.takeError();
251
253 continue;
254
255 auto Name = Sym.getName();
256 if (!Name)
257 return Name.takeError();
258 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
259 if (!SymFlags)
260 return SymFlags.takeError();
261
262 // TODO: Revisit symbol visibility
263 // On AIX, symbols with C_EXT and C_WEAKEXT symbols have no specified
264 // visibility are considered to have Default scope for LinkGraph. When the
265 // object is not a DSO, symbol visibility is not specified. In the absence
266 // of an Export List, its reasonable to minimic roughly the behaviour of
267 // -bexpall or CreateExportList.
268 *SymFlags |= JITSymbolFlags::Exported;
269
270 I.SymbolFlags[ES.intern(std::move(*Name))] = std::move(*SymFlags);
271 }
272 // TODO: Find all initialization symbols for c++ static initializers
273 return I;
274}
275
278 const object::ObjectFile &Obj) {
280
281 for (auto &Sym : Obj.symbols()) {
282 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
283 if (!SymFlagsOrErr)
284 // TODO: Test this error.
285 return SymFlagsOrErr.takeError();
286
287 // Skip symbols not defined in this object file.
288 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
289 continue;
290
291 // Skip symbols that are not global.
292 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
293 continue;
294
295 // Skip symbols that have type SF_File.
296 if (auto SymType = Sym.getType()) {
297 if (*SymType == object::SymbolRef::ST_File)
298 continue;
299 } else
300 return SymType.takeError();
301
302 auto Name = Sym.getName();
303 if (!Name)
304 return Name.takeError();
305
306 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
307 if (!SymFlags)
308 return SymFlags.takeError();
309
310 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
311 }
312
313 return I;
314}
315
318 auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
319
320 if (!Obj)
321 return Obj.takeError();
322
323 if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
324 return getMachOObjectFileSymbolInfo(ES, *MachOObj);
325 else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
326 return getELFObjectFileSymbolInfo(ES, *ELFObj);
327 else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
328 return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
329 else if (auto *XCOFFObj = dyn_cast<object::XCOFFObjectFile>(Obj->get()))
330 return getXCOFFObjectFileSymbolInfo(ES, *XCOFFObj);
331
332 return getGenericObjectFileSymbolInfo(ES, **Obj);
333}
334
335} // End namespace orc.
336} // End namespace llvm.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define I(x, y, z)
Definition MD5.cpp:57
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
Flags for symbols in the JIT.
Definition JITSymbol.h:75
static LLVM_ABI Expected< JITSymbolFlags > fromObjectSymbol(const object::SymbolRef &Symbol)
Construct a JITSymbolFlags value based on the flags of the given libobject symbol.
Definition JITSymbol.cpp:69
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
This class is the base class for all object file types.
Definition ObjectFile.h:231
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
An ExecutionSession represents a running JIT program.
Definition Core.h:1104
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition Core.h:1185
A raw_ostream that writes to an std::string.
@ IMAGE_SCN_LNK_COMDAT
Definition COFF.h:309
@ IMAGE_COMDAT_SELECT_NODUPLICATES
Definition COFF.h:455
@ IMAGE_COMDAT_SELECT_ASSOCIATIVE
Definition COFF.h:459
bool isReservedSectionNumber(int32_t SectionNumber)
Definition COFF.h:866
@ STB_GNU_UNIQUE
Definition ELF.h:1232
@ SECTION_TYPE
Definition MachO.h:114
@ S_MOD_INIT_FUNC_POINTERS
S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for initialization.
Definition MachO.h:147
LLVM_ABI void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES, StringRef ObjFileName)
Adds an initializer symbol to the given MU interface.
static Expected< MaterializationUnit::Interface > getMachOObjectFileSymbolInfo(ExecutionSession &ES, const object::MachOObjectFile &Obj)
Expected< MaterializationUnit::Interface > getGenericObjectFileSymbolInfo(ExecutionSession &ES, const object::ObjectFile &Obj)
static Expected< MaterializationUnit::Interface > getELFObjectFileSymbolInfo(ExecutionSession &ES, const object::ELFObjectFileBase &Obj)
Expected< MaterializationUnit::Interface > getXCOFFObjectFileSymbolInfo(ExecutionSession &ES, const object::ObjectFile &Obj)
LLVM_ABI bool isMachOInitializerSection(StringRef SegName, StringRef SecName)
LLVM_ABI Expected< MaterializationUnit::Interface > getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer)
Returns a MaterializationUnit::Interface for the object file contained in the given buffer,...
LLVM_ABI bool isCOFFInitializerSection(StringRef Name)
static Expected< MaterializationUnit::Interface > getCOFFObjectFileSymbolInfo(ExecutionSession &ES, const object::COFFObjectFile &Obj)
LLVM_ABI bool isELFInitializerSection(StringRef SecName)
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition Error.h:769