1 //===------ ObjectFileInterface.cpp - MU interface utils for objects ------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
10 #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
11 #include "llvm/Object/COFF.h"
12 #include "llvm/Object/ELFObjectFile.h"
13 #include "llvm/Object/MachO.h"
14 #include "llvm/Object/ObjectFile.h"
17 #define DEBUG_TYPE "orc"
22 void addInitSymbol(MaterializationUnit::Interface
&I
, ExecutionSession
&ES
,
23 StringRef ObjFileName
) {
24 assert(!I
.InitSymbol
&& "I already has an init symbol");
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
));
34 I
.SymbolFlags
[I
.InitSymbol
] = JITSymbolFlags::MaterializationSideEffectsOnly
;
37 static Expected
<MaterializationUnit::Interface
>
38 getMachOObjectFileSymbolInfo(ExecutionSession
&ES
,
39 const object::MachOObjectFile
&Obj
) {
40 MaterializationUnit::Interface I
;
42 for (auto &Sym
: Obj
.symbols()) {
43 Expected
<uint32_t> SymFlagsOrErr
= Sym
.getFlags();
45 // TODO: Test this error.
46 return SymFlagsOrErr
.takeError();
48 // Skip symbols not defined in this object file.
49 if (*SymFlagsOrErr
& object::BasicSymbolRef::SF_Undefined
)
52 // Skip symbols that are not global.
53 if (!(*SymFlagsOrErr
& object::BasicSymbolRef::SF_Global
))
56 // Skip symbols that have type SF_File.
57 if (auto SymType
= Sym
.getType()) {
58 if (*SymType
== object::SymbolRef::ST_File
)
61 return SymType
.takeError();
63 auto Name
= Sym
.getName();
65 return Name
.takeError();
66 auto SymFlags
= JITSymbolFlags::fromObjectSymbol(Sym
);
68 return SymFlags
.takeError();
70 // Strip the 'exported' flag from MachO linker-private symbols.
71 if (Name
->starts_with("l"))
72 *SymFlags
&= ~JITSymbolFlags::Exported
;
74 I
.SymbolFlags
[ES
.intern(*Name
)] = std::move(*SymFlags
);
77 for (auto &Sec
: Obj
.sections()) {
78 auto SecType
= Obj
.getSectionType(Sec
);
79 if ((SecType
& MachO::SECTION_TYPE
) == MachO::S_MOD_INIT_FUNC_POINTERS
) {
80 addInitSymbol(I
, ES
, Obj
.getFileName());
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());
94 static Expected
<MaterializationUnit::Interface
>
95 getELFObjectFileSymbolInfo(ExecutionSession
&ES
,
96 const object::ELFObjectFileBase
&Obj
) {
97 MaterializationUnit::Interface I
;
99 for (auto &Sym
: Obj
.symbols()) {
100 Expected
<uint32_t> SymFlagsOrErr
= Sym
.getFlags();
102 // TODO: Test this error.
103 return SymFlagsOrErr
.takeError();
105 // Skip symbols not defined in this object file.
106 if (*SymFlagsOrErr
& object::BasicSymbolRef::SF_Undefined
)
109 // Skip symbols that are not global.
110 if (!(*SymFlagsOrErr
& object::BasicSymbolRef::SF_Global
))
113 // Skip symbols that have type SF_File.
114 if (auto SymType
= Sym
.getType()) {
115 if (*SymType
== object::SymbolRef::ST_File
)
118 return SymType
.takeError();
120 auto Name
= Sym
.getName();
122 return Name
.takeError();
124 auto SymFlags
= JITSymbolFlags::fromObjectSymbol(Sym
);
126 return SymFlags
.takeError();
128 // ELF STB_GNU_UNIQUE should map to Weak for ORC.
129 if (Sym
.getBinding() == ELF::STB_GNU_UNIQUE
)
130 *SymFlags
|= JITSymbolFlags::Weak
;
132 I
.SymbolFlags
[ES
.intern(*Name
)] = std::move(*SymFlags
);
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());
148 static Expected
<MaterializationUnit::Interface
>
149 getCOFFObjectFileSymbolInfo(ExecutionSession
&ES
,
150 const object::COFFObjectFile
&Obj
) {
151 MaterializationUnit::Interface I
;
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();
157 // TODO: Test this error.
158 return SymFlagsOrErr
.takeError();
160 // Handle comdat symbols
161 auto COFFSym
= Obj
.getCOFFSymbol(Sym
);
163 if (auto *Def
= COFFSym
.getSectionDefinition()) {
164 auto Sec
= Obj
.getSection(COFFSym
.getSectionNumber());
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
;
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
) {
179 ComdatDefs
[COFFSym
.getSectionNumber()] = std::nullopt
;
181 // Skip symbols not defined in this object file.
182 if (*SymFlagsOrErr
& object::BasicSymbolRef::SF_Undefined
)
186 // Skip symbols that are not global.
187 if (!(*SymFlagsOrErr
& object::BasicSymbolRef::SF_Global
))
190 // Skip symbols that have type SF_File.
191 if (auto SymType
= Sym
.getType()) {
192 if (*SymType
== object::SymbolRef::ST_File
)
195 return SymType
.takeError();
197 auto Name
= Sym
.getName();
199 return Name
.takeError();
201 auto SymFlags
= JITSymbolFlags::fromObjectSymbol(Sym
);
203 return SymFlags
.takeError();
204 *SymFlags
|= JITSymbolFlags::Exported
;
206 // Weak external is always a function
207 if (COFFSym
.isWeakExternal())
208 *SymFlags
|= JITSymbolFlags::Callable
;
211 *SymFlags
|= JITSymbolFlags::Weak
;
213 I
.SymbolFlags
[ES
.intern(*Name
)] = std::move(*SymFlags
);
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());
224 return SecName
.takeError();
230 Expected
<MaterializationUnit::Interface
>
231 getGenericObjectFileSymbolInfo(ExecutionSession
&ES
,
232 const object::ObjectFile
&Obj
) {
233 MaterializationUnit::Interface I
;
235 for (auto &Sym
: Obj
.symbols()) {
236 Expected
<uint32_t> SymFlagsOrErr
= Sym
.getFlags();
238 // TODO: Test this error.
239 return SymFlagsOrErr
.takeError();
241 // Skip symbols not defined in this object file.
242 if (*SymFlagsOrErr
& object::BasicSymbolRef::SF_Undefined
)
245 // Skip symbols that are not global.
246 if (!(*SymFlagsOrErr
& object::BasicSymbolRef::SF_Global
))
249 // Skip symbols that have type SF_File.
250 if (auto SymType
= Sym
.getType()) {
251 if (*SymType
== object::SymbolRef::ST_File
)
254 return SymType
.takeError();
256 auto Name
= Sym
.getName();
258 return Name
.takeError();
260 auto SymFlags
= JITSymbolFlags::fromObjectSymbol(Sym
);
262 return SymFlags
.takeError();
264 I
.SymbolFlags
[ES
.intern(*Name
)] = std::move(*SymFlags
);
270 Expected
<MaterializationUnit::Interface
>
271 getObjectFileInterface(ExecutionSession
&ES
, MemoryBufferRef ObjBuffer
) {
272 auto Obj
= object::ObjectFile::createObjectFile(ObjBuffer
);
275 return Obj
.takeError();
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
);
284 return getGenericObjectFileSymbolInfo(ES
, **Obj
);
287 } // End namespace orc.
288 } // End namespace llvm.