LLVM 22.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 SymbolStringPtr InitSymbol;
138 for (auto &Sec : Obj.sections()) {
139 if (auto SecName = Sec.getName()) {
140 if (isELFInitializerSection(*SecName)) {
141 addInitSymbol(I, ES, Obj.getFileName());
142 break;
143 }
144 }
145 }
146
147 return I;
148}
149
152 const object::COFFObjectFile &Obj) {
154 std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(
155 Obj.getNumberOfSections() + 1);
156 for (auto &Sym : Obj.symbols()) {
157 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
158 if (!SymFlagsOrErr)
159 // TODO: Test this error.
160 return SymFlagsOrErr.takeError();
161
162 // Handle comdat symbols
163 auto COFFSym = Obj.getCOFFSymbol(Sym);
164 bool IsWeak = false;
165 if (auto *Def = COFFSym.getSectionDefinition()) {
166 auto Sec = Obj.getSection(COFFSym.getSectionNumber());
167 if (!Sec)
168 return Sec.takeError();
169 if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&
170 Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
171 ComdatDefs[COFFSym.getSectionNumber()] = *Def;
172 continue;
173 }
174 }
175 if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&
176 ComdatDefs[COFFSym.getSectionNumber()]) {
177 auto Def = ComdatDefs[COFFSym.getSectionNumber()];
178 if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
179 IsWeak = true;
180 }
181 ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt;
182 } else {
183 // Skip symbols not defined in this object file.
184 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
185 continue;
186 }
187
188 // Skip symbols that are not global.
189 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
190 continue;
191
192 // Skip symbols that have type SF_File.
193 if (auto SymType = Sym.getType()) {
194 if (*SymType == object::SymbolRef::ST_File)
195 continue;
196 } else
197 return SymType.takeError();
198
199 auto Name = Sym.getName();
200 if (!Name)
201 return Name.takeError();
202
203 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
204 if (!SymFlags)
205 return SymFlags.takeError();
206 *SymFlags |= JITSymbolFlags::Exported;
207
208 // Weak external is always a function
209 if (COFFSym.isWeakExternal())
210 *SymFlags |= JITSymbolFlags::Callable;
211
212 if (IsWeak)
213 *SymFlags |= JITSymbolFlags::Weak;
214
215 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
216 }
217
218 SymbolStringPtr InitSymbol;
219 for (auto &Sec : Obj.sections()) {
220 if (auto SecName = Sec.getName()) {
221 if (isCOFFInitializerSection(*SecName)) {
222 addInitSymbol(I, ES, Obj.getFileName());
223 break;
224 }
225 } else
226 return SecName.takeError();
227 }
228
229 return I;
230}
231
234 const object::ObjectFile &Obj) {
235
237
238 for (auto &Sym : Obj.symbols()) {
239 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
240 if (!SymFlagsOrErr)
241 return SymFlagsOrErr.takeError();
242 uint32_t Flags = *SymFlagsOrErr;
243
244 // Skip undefined, non global and ST_File
246 continue;
247 if (!(Flags & object::SymbolRef::SF_Global))
248 continue;
249
250 auto SymbolType = Sym.getType();
251 if (!SymbolType)
252 return SymbolType.takeError();
253
255 continue;
256
257 auto Name = Sym.getName();
258 if (!Name)
259 return Name.takeError();
260 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
261 if (!SymFlags)
262 return SymFlags.takeError();
263
264 // TODO: Revisit symbol visibility
265 // On AIX, symbols with C_EXT and C_WEAKEXT symbols have no specified
266 // visibility are considered to have Default scope for LinkGraph. When the
267 // object is not a DSO, symbol visibility is not specified. In the absence
268 // of an Export List, its reasonable to minimic roughly the behaviour of
269 // -bexpall or CreateExportList.
270 *SymFlags |= JITSymbolFlags::Exported;
271
272 I.SymbolFlags[ES.intern(std::move(*Name))] = std::move(*SymFlags);
273 }
274 // TODO: Find all initialization symbols for c++ static initializers
275 return I;
276}
277
280 const object::ObjectFile &Obj) {
282
283 for (auto &Sym : Obj.symbols()) {
284 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
285 if (!SymFlagsOrErr)
286 // TODO: Test this error.
287 return SymFlagsOrErr.takeError();
288
289 // Skip symbols not defined in this object file.
290 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
291 continue;
292
293 // Skip symbols that are not global.
294 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
295 continue;
296
297 // Skip symbols that have type SF_File.
298 if (auto SymType = Sym.getType()) {
299 if (*SymType == object::SymbolRef::ST_File)
300 continue;
301 } else
302 return SymType.takeError();
303
304 auto Name = Sym.getName();
305 if (!Name)
306 return Name.takeError();
307
308 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
309 if (!SymFlags)
310 return SymFlags.takeError();
311
312 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
313 }
314
315 return I;
316}
317
320 auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
321
322 if (!Obj)
323 return Obj.takeError();
324
325 if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
326 return getMachOObjectFileSymbolInfo(ES, *MachOObj);
327 else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
328 return getELFObjectFileSymbolInfo(ES, *ELFObj);
329 else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
330 return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
331 else if (auto *XCOFFObj = dyn_cast<object::XCOFFObjectFile>(Obj->get()))
332 return getXCOFFObjectFileSymbolInfo(ES, *XCOFFObj);
333
334 return getGenericObjectFileSymbolInfo(ES, **Obj);
335}
336
337} // End namespace orc.
338} // End namespace llvm.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define I(x, y, z)
Definition MD5.cpp:58
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
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
StringRef getFileName() const
Definition Binary.cpp:41
uint32_t getNumberOfSections() const
Definition COFF.h:992
Expected< const coff_section * > getSection(int32_t index) const
COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const
elf_symbol_iterator_range symbols() const
unsigned getSectionType(SectionRef Sec) const
StringRef getSectionFinalSegmentName(DataRefImpl Sec) const
Expected< StringRef > getSectionName(DataRefImpl Sec) const override
This class is the base class for all object file types.
Definition ObjectFile.h:231
section_iterator_range sections() const
Definition ObjectFile.h:331
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
symbol_iterator_range symbols() const
Definition ObjectFile.h:323
An ExecutionSession represents a running JIT program.
Definition Core.h:1355
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition Core.h:1409
Pointer to a pooled string representing a symbol name.
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:1399
@ 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:649
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition Error.h:769