LLVM 19.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
14#include "llvm/Object/COFF.h"
16#include "llvm/Object/MachO.h"
18#include "llvm/Support/Debug.h"
19#include <optional>
20
21#define DEBUG_TYPE "orc"
22
23namespace llvm {
24namespace orc {
25
27 StringRef ObjFileName) {
28 assert(!I.InitSymbol && "I already has an init symbol");
29 size_t Counter = 0;
30
31 do {
32 std::string InitSymString;
33 raw_string_ostream(InitSymString)
34 << "$." << ObjFileName << ".__inits." << Counter++;
35 I.InitSymbol = ES.intern(InitSymString);
36 } while (I.SymbolFlags.count(I.InitSymbol));
37
38 I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
39}
40
43 const object::MachOObjectFile &Obj) {
45
46 for (auto &Sym : Obj.symbols()) {
47 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
48 if (!SymFlagsOrErr)
49 // TODO: Test this error.
50 return SymFlagsOrErr.takeError();
51
52 // Skip symbols not defined in this object file.
53 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
54 continue;
55
56 // Skip symbols that are not global.
57 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
58 continue;
59
60 // Skip symbols that have type SF_File.
61 if (auto SymType = Sym.getType()) {
62 if (*SymType == object::SymbolRef::ST_File)
63 continue;
64 } else
65 return SymType.takeError();
66
67 auto Name = Sym.getName();
68 if (!Name)
69 return Name.takeError();
71 if (!SymFlags)
72 return SymFlags.takeError();
73
74 // Strip the 'exported' flag from MachO linker-private symbols.
75 if (Name->starts_with("l"))
76 *SymFlags &= ~JITSymbolFlags::Exported;
77
78 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
79 }
80
81 for (auto &Sec : Obj.sections()) {
82 auto SecType = Obj.getSectionType(Sec);
84 addInitSymbol(I, ES, Obj.getFileName());
85 break;
86 }
87 auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
88 auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
89 if (isMachOInitializerSection(SegName, SecName)) {
90 addInitSymbol(I, ES, Obj.getFileName());
91 break;
92 }
93 }
94
95 return I;
96}
97
100 const object::ELFObjectFileBase &Obj) {
102
103 for (auto &Sym : Obj.symbols()) {
104 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
105 if (!SymFlagsOrErr)
106 // TODO: Test this error.
107 return SymFlagsOrErr.takeError();
108
109 // Skip symbols not defined in this object file.
110 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
111 continue;
112
113 // Skip symbols that are not global.
114 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
115 continue;
116
117 // Skip symbols that have type SF_File.
118 if (auto SymType = Sym.getType()) {
119 if (*SymType == object::SymbolRef::ST_File)
120 continue;
121 } else
122 return SymType.takeError();
123
124 auto Name = Sym.getName();
125 if (!Name)
126 return Name.takeError();
127
128 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
129 if (!SymFlags)
130 return SymFlags.takeError();
131
132 // ELF STB_GNU_UNIQUE should map to Weak for ORC.
133 if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
134 *SymFlags |= JITSymbolFlags::Weak;
135
136 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
137 }
138
139 SymbolStringPtr InitSymbol;
140 for (auto &Sec : Obj.sections()) {
141 if (auto SecName = Sec.getName()) {
142 if (isELFInitializerSection(*SecName)) {
143 addInitSymbol(I, ES, Obj.getFileName());
144 break;
145 }
146 }
147 }
148
149 return I;
150}
151
154 const object::COFFObjectFile &Obj) {
156 std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(
157 Obj.getNumberOfSections() + 1);
158 for (auto &Sym : Obj.symbols()) {
159 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
160 if (!SymFlagsOrErr)
161 // TODO: Test this error.
162 return SymFlagsOrErr.takeError();
163
164 // Handle comdat symbols
165 auto COFFSym = Obj.getCOFFSymbol(Sym);
166 bool IsWeak = false;
167 if (auto *Def = COFFSym.getSectionDefinition()) {
168 auto Sec = Obj.getSection(COFFSym.getSectionNumber());
169 if (!Sec)
170 return Sec.takeError();
171 if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&
172 Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
173 ComdatDefs[COFFSym.getSectionNumber()] = *Def;
174 continue;
175 }
176 }
177 if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&
178 ComdatDefs[COFFSym.getSectionNumber()]) {
179 auto Def = ComdatDefs[COFFSym.getSectionNumber()];
180 if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
181 IsWeak = true;
182 }
183 ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt;
184 } else {
185 // Skip symbols not defined in this object file.
186 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
187 continue;
188 }
189
190 // Skip symbols that are not global.
191 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
192 continue;
193
194 // Skip symbols that have type SF_File.
195 if (auto SymType = Sym.getType()) {
196 if (*SymType == object::SymbolRef::ST_File)
197 continue;
198 } else
199 return SymType.takeError();
200
201 auto Name = Sym.getName();
202 if (!Name)
203 return Name.takeError();
204
205 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
206 if (!SymFlags)
207 return SymFlags.takeError();
208 *SymFlags |= JITSymbolFlags::Exported;
209
210 // Weak external is always a function
211 if (COFFSym.isWeakExternal())
212 *SymFlags |= JITSymbolFlags::Callable;
213
214 if (IsWeak)
215 *SymFlags |= JITSymbolFlags::Weak;
216
217 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
218 }
219
220 SymbolStringPtr InitSymbol;
221 for (auto &Sec : Obj.sections()) {
222 if (auto SecName = Sec.getName()) {
223 if (isCOFFInitializerSection(*SecName)) {
224 addInitSymbol(I, ES, Obj.getFileName());
225 break;
226 }
227 } else
228 return SecName.takeError();
229 }
230
231 return I;
232}
233
236 const object::ObjectFile &Obj) {
238
239 for (auto &Sym : Obj.symbols()) {
240 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
241 if (!SymFlagsOrErr)
242 // TODO: Test this error.
243 return SymFlagsOrErr.takeError();
244
245 // Skip symbols not defined in this object file.
246 if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
247 continue;
248
249 // Skip symbols that are not global.
250 if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
251 continue;
252
253 // Skip symbols that have type SF_File.
254 if (auto SymType = Sym.getType()) {
255 if (*SymType == object::SymbolRef::ST_File)
256 continue;
257 } else
258 return SymType.takeError();
259
260 auto Name = Sym.getName();
261 if (!Name)
262 return Name.takeError();
263
264 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
265 if (!SymFlags)
266 return SymFlags.takeError();
267
268 I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
269 }
270
271 return I;
272}
273
276 auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
277
278 if (!Obj)
279 return Obj.takeError();
280
281 if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
282 return getMachOObjectFileSymbolInfo(ES, *MachOObj);
283 else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
284 return getELFObjectFileSymbolInfo(ES, *ELFObj);
285 else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
286 return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
287
288 return getGenericObjectFileSymbolInfo(ES, **Obj);
289}
290
291} // End namespace orc.
292} // 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:474
Error takeError()
Take ownership of the stored error.
Definition: Error.h:601
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:50
StringRef getFileName() const
Definition: Binary.cpp:41
uint32_t getNumberOfSections() const
Definition: COFF.h:941
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:328
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Definition: ObjectFile.cpp:209
symbol_iterator_range symbols() const
Definition: ObjectFile.h:320
An ExecutionSession represents a running JIT program.
Definition: Core.h:1431
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition: Core.h:1488
Pointer to a pooled string representing a symbol name.
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:660
@ IMAGE_SCN_LNK_COMDAT
Definition: COFF.h:308
@ IMAGE_COMDAT_SELECT_NODUPLICATES
Definition: COFF.h:421
@ IMAGE_COMDAT_SELECT_ASSOCIATIVE
Definition: COFF.h:425
bool isReservedSectionNumber(int32_t SectionNumber)
Definition: COFF.h:815
@ STB_GNU_UNIQUE
Definition: ELF.h:1313
@ S_MOD_INIT_FUNC_POINTERS
S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for initialization.
Definition: MachO.h:147
@ SECTION_TYPE
Definition: MachO.h:114
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:749