LLVM 20.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
11#include "llvm/Object/COFF.h"
13#include "llvm/Object/MachO.h"
15#include <optional>
16
17#define DEBUG_TYPE "orc"
18
19namespace llvm {
20namespace orc {
21
23 StringRef ObjFileName) {
24 assert(!I.InitSymbol && "I already has an init symbol");
25 size_t Counter = 0;
26
27 do {
28 std::string InitSymString;
29 raw_string_ostream(InitSymString)
30 << "$." << ObjFileName << ".__inits." << Counter++;
31 I.InitSymbol = ES.intern(InitSymString);
32 } while (I.SymbolFlags.count(I.InitSymbol));
33
34 I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
35}
36
39 const object::MachOObjectFile &Obj) {
41
42 for (auto &Sym : Obj.symbols()) {
43 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
44 if (!SymFlagsOrErr)
45 // TODO: Test this error.
46 return SymFlagsOrErr.takeError();
47
48 // Skip symbols not defined in this object file.
49 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
50 continue;
51
52 // Skip symbols that are not global.
53 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
54 continue;
55
56 // Skip symbols that have type SF_File.
57 if (auto SymType = Sym.getType()) {
58 if (*SymType == object::SymbolRef::ST_File)
59 continue;
60 } else
61 return SymType.takeError();
62
63 auto Name = Sym.getName();
64 if (!Name)
65 return Name.takeError();
67 if (!SymFlags)
68 return SymFlags.takeError();
69
70 // Strip the 'exported' flag from MachO linker-private symbols.
71 if (Name->starts_with("l"))
72 *SymFlags &= ~JITSymbolFlags::Exported;
73
74 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
75 }
76
77 for (auto &Sec : Obj.sections()) {
78 auto SecType = Obj.getSectionType(Sec);
80 addInitSymbol(I, ES, Obj.getFileName());
81 break;
82 }
83 auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
84 auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
85 if (isMachOInitializerSection(SegName, SecName)) {
86 addInitSymbol(I, ES, Obj.getFileName());
87 break;
88 }
89 }
90
91 return I;
92}
93
96 const object::ELFObjectFileBase &Obj) {
98
99 for (auto &Sym : Obj.symbols()) {
100 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
101 if (!SymFlagsOrErr)
102 // TODO: Test this error.
103 return SymFlagsOrErr.takeError();
104
105 // Skip symbols not defined in this object file.
106 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
107 continue;
108
109 // Skip symbols that are not global.
110 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
111 continue;
112
113 // Skip symbols that have type SF_File.
114 if (auto SymType = Sym.getType()) {
115 if (*SymType == object::SymbolRef::ST_File)
116 continue;
117 } else
118 return SymType.takeError();
119
120 auto Name = Sym.getName();
121 if (!Name)
122 return Name.takeError();
123
124 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
125 if (!SymFlags)
126 return SymFlags.takeError();
127
128 // ELF STB_GNU_UNIQUE should map to Weak for ORC.
129 if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
130 *SymFlags |= JITSymbolFlags::Weak;
131
132 I.SymbolFlags[ES.intern(std::move(*Name))] = std::move(*SymFlags);
133 }
134
135 SymbolStringPtr InitSymbol;
136 for (auto &Sec : Obj.sections()) {
137 if (auto SecName = Sec.getName()) {
138 if (isELFInitializerSection(*SecName)) {
139 addInitSymbol(I, ES, Obj.getFileName());
140 break;
141 }
142 }
143 }
144
145 return I;
146}
147
150 const object::COFFObjectFile &Obj) {
152 std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(
153 Obj.getNumberOfSections() + 1);
154 for (auto &Sym : Obj.symbols()) {
155 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
156 if (!SymFlagsOrErr)
157 // TODO: Test this error.
158 return SymFlagsOrErr.takeError();
159
160 // Handle comdat symbols
161 auto COFFSym = Obj.getCOFFSymbol(Sym);
162 bool IsWeak = false;
163 if (auto *Def = COFFSym.getSectionDefinition()) {
164 auto Sec = Obj.getSection(COFFSym.getSectionNumber());
165 if (!Sec)
166 return Sec.takeError();
167 if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&
168 Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
169 ComdatDefs[COFFSym.getSectionNumber()] = *Def;
170 continue;
171 }
172 }
173 if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&
174 ComdatDefs[COFFSym.getSectionNumber()]) {
175 auto Def = ComdatDefs[COFFSym.getSectionNumber()];
176 if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
177 IsWeak = true;
178 }
179 ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt;
180 } else {
181 // Skip symbols not defined in this object file.
182 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
183 continue;
184 }
185
186 // Skip symbols that are not global.
187 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
188 continue;
189
190 // Skip symbols that have type SF_File.
191 if (auto SymType = Sym.getType()) {
192 if (*SymType == object::SymbolRef::ST_File)
193 continue;
194 } else
195 return SymType.takeError();
196
197 auto Name = Sym.getName();
198 if (!Name)
199 return Name.takeError();
200
201 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
202 if (!SymFlags)
203 return SymFlags.takeError();
204 *SymFlags |= JITSymbolFlags::Exported;
205
206 // Weak external is always a function
207 if (COFFSym.isWeakExternal())
208 *SymFlags |= JITSymbolFlags::Callable;
209
210 if (IsWeak)
211 *SymFlags |= JITSymbolFlags::Weak;
212
213 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
214 }
215
216 SymbolStringPtr InitSymbol;
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) {
234
235 for (auto &Sym : Obj.symbols()) {
236 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
237 if (!SymFlagsOrErr)
238 // TODO: Test this error.
239 return SymFlagsOrErr.takeError();
240
241 // Skip symbols not defined in this object file.
242 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
243 continue;
244
245 // Skip symbols that are not global.
246 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
247 continue;
248
249 // Skip symbols that have type SF_File.
250 if (auto SymType = Sym.getType()) {
251 if (*SymType == object::SymbolRef::ST_File)
252 continue;
253 } else
254 return SymType.takeError();
255
256 auto Name = Sym.getName();
257 if (!Name)
258 return Name.takeError();
259
260 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
261 if (!SymFlags)
262 return SymFlags.takeError();
263
264 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
265 }
266
267 return I;
268}
269
272 auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
273
274 if (!Obj)
275 return Obj.takeError();
276
277 if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
278 return getMachOObjectFileSymbolInfo(ES, *MachOObj);
279 else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
280 return getELFObjectFileSymbolInfo(ES, *ELFObj);
281 else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
282 return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
283
284 return getGenericObjectFileSymbolInfo(ES, **Obj);
285}
286
287} // End namespace orc.
288} // End namespace llvm.
std::string Name
Symbol * Sym
Definition: ELF_riscv.cpp:479
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
Flags for symbols in the JIT.
Definition: JITSymbol.h:74
static Expected< JITSymbolFlags > fromObjectSymbol(const object::SymbolRef &Symbol)
Construct a JITSymbolFlags value based on the flags of the given libobject symbol.
Definition: JITSymbol.cpp:69
@ MaterializationSideEffectsOnly
Definition: JITSymbol.h:87
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
StringRef getFileName() const
Definition: Binary.cpp:41
uint32_t getNumberOfSections() const
Definition: COFF.h:983
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:229
section_iterator_range sections() const
Definition: ObjectFile.h:329
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Definition: ObjectFile.cpp:209
symbol_iterator_range symbols() const
Definition: ObjectFile.h:321
An ExecutionSession represents a running JIT program.
Definition: Core.h:1339
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition: Core.h:1393
Pointer to a pooled string representing a symbol name.
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:661
@ IMAGE_SCN_LNK_COMDAT
Definition: COFF.h:308
@ IMAGE_COMDAT_SELECT_NODUPLICATES
Definition: COFF.h:454
@ IMAGE_COMDAT_SELECT_ASSOCIATIVE
Definition: COFF.h:458
bool isReservedSectionNumber(int32_t SectionNumber)
Definition: COFF.h:848
@ STB_GNU_UNIQUE
Definition: ELF.h:1349
@ 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
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)
bool isMachOInitializerSection(StringRef SegName, StringRef SecName)
Expected< MaterializationUnit::Interface > getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer)
Returns a MaterializationUnit::Interface for the object file contained in the given buffer,...
bool isCOFFInitializerSection(StringRef Name)
static Expected< MaterializationUnit::Interface > getCOFFObjectFileSymbolInfo(ExecutionSession &ES, const object::COFFObjectFile &Obj)
bool isELFInitializerSection(StringRef SecName)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:756