LLVM  16.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 
13 #include "llvm/Object/COFF.h"
15 #include "llvm/Object/MachO.h"
16 #include "llvm/Object/ObjectFile.h"
17 #include "llvm/Support/Debug.h"
18 #include <optional>
19 
20 #define DEBUG_TYPE "orc"
21 
22 namespace llvm {
23 namespace orc {
24 
26  StringRef ObjFileName) {
27  assert(!I.InitSymbol && "I already has an init symbol");
28  size_t Counter = 0;
29 
30  do {
31  std::string InitSymString;
32  raw_string_ostream(InitSymString)
33  << "$." << ObjFileName << ".__inits." << Counter++;
34  I.InitSymbol = ES.intern(InitSymString);
35  } while (I.SymbolFlags.count(I.InitSymbol));
36 
37  I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
38 }
39 
42  const object::MachOObjectFile &Obj) {
44 
45  for (auto &Sym : Obj.symbols()) {
46  Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
47  if (!SymFlagsOrErr)
48  // TODO: Test this error.
49  return SymFlagsOrErr.takeError();
50 
51  // Skip symbols not defined in this object file.
52  if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
53  continue;
54 
55  // Skip symbols that are not global.
56  if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
57  continue;
58 
59  // Skip symbols that have type SF_File.
60  if (auto SymType = Sym.getType()) {
61  if (*SymType == object::SymbolRef::ST_File)
62  continue;
63  } else
64  return SymType.takeError();
65 
66  auto Name = Sym.getName();
67  if (!Name)
68  return Name.takeError();
69  auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
70  if (!SymFlags)
71  return SymFlags.takeError();
72 
73  // Strip the 'exported' flag from MachO linker-private symbols.
74  if (Name->startswith("l"))
75  *SymFlags &= ~JITSymbolFlags::Exported;
76 
77  I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
78  }
79 
80  for (auto &Sec : Obj.sections()) {
81  auto SecType = Obj.getSectionType(Sec);
83  addInitSymbol(I, ES, Obj.getFileName());
84  break;
85  }
86  auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
87  auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
88  if (MachOPlatform::isInitializerSection(SegName, SecName)) {
89  addInitSymbol(I, ES, Obj.getFileName());
90  break;
91  }
92  }
93 
94  return I;
95 }
96 
99  const object::ELFObjectFileBase &Obj) {
101 
102  for (auto &Sym : Obj.symbols()) {
103  Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
104  if (!SymFlagsOrErr)
105  // TODO: Test this error.
106  return SymFlagsOrErr.takeError();
107 
108  // Skip symbols not defined in this object file.
109  if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
110  continue;
111 
112  // Skip symbols that are not global.
113  if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
114  continue;
115 
116  // Skip symbols that have type SF_File.
117  if (auto SymType = Sym.getType()) {
118  if (*SymType == object::SymbolRef::ST_File)
119  continue;
120  } else
121  return SymType.takeError();
122 
123  auto Name = Sym.getName();
124  if (!Name)
125  return Name.takeError();
126 
127  auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
128  if (!SymFlags)
129  return SymFlags.takeError();
130 
131  // ELF STB_GNU_UNIQUE should map to Weak for ORC.
132  if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
133  *SymFlags |= JITSymbolFlags::Weak;
134 
135  I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
136  }
137 
138  SymbolStringPtr InitSymbol;
139  for (auto &Sec : Obj.sections()) {
140  if (auto SecName = Sec.getName()) {
141  if (ELFNixPlatform::isInitializerSection(*SecName)) {
142  addInitSymbol(I, ES, Obj.getFileName());
143  break;
144  }
145  }
146  }
147 
148  return I;
149 }
150 
153  const object::COFFObjectFile &Obj) {
155  std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(
156  Obj.getNumberOfSections() + 1);
157  for (auto &Sym : Obj.symbols()) {
158  Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
159  if (!SymFlagsOrErr)
160  // TODO: Test this error.
161  return SymFlagsOrErr.takeError();
162 
163  // Handle comdat symbols
164  auto COFFSym = Obj.getCOFFSymbol(Sym);
165  bool IsWeak = false;
166  if (auto *Def = COFFSym.getSectionDefinition()) {
167  auto Sec = Obj.getSection(COFFSym.getSectionNumber());
168  if (!Sec)
169  return Sec.takeError();
170  if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&
172  ComdatDefs[COFFSym.getSectionNumber()] = *Def;
173  continue;
174  }
175  }
176  if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&
177  ComdatDefs[COFFSym.getSectionNumber()]) {
178  auto Def = ComdatDefs[COFFSym.getSectionNumber()];
179  if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
180  IsWeak = true;
181  }
182  ComdatDefs[COFFSym.getSectionNumber()] = None;
183  } else {
184  // Skip symbols not defined in this object file.
185  if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
186  continue;
187  }
188 
189  // Skip symbols that are not global.
190  if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
191  continue;
192 
193  // Skip symbols that have type SF_File.
194  if (auto SymType = Sym.getType()) {
195  if (*SymType == object::SymbolRef::ST_File)
196  continue;
197  } else
198  return SymType.takeError();
199 
200  auto Name = Sym.getName();
201  if (!Name)
202  return Name.takeError();
203 
204  auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
205  if (!SymFlags)
206  return SymFlags.takeError();
207  *SymFlags |= JITSymbolFlags::Exported;
208 
209  // Weak external is always a function
210  if (COFFSym.isWeakExternal())
211  *SymFlags |= JITSymbolFlags::Callable;
212 
213  if (IsWeak)
214  *SymFlags |= JITSymbolFlags::Weak;
215 
216  I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
217  }
218 
219  SymbolStringPtr InitSymbol;
220  for (auto &Sec : Obj.sections()) {
221  if (auto SecName = Sec.getName()) {
222  if (COFFPlatform::isInitializerSection(*SecName)) {
223  addInitSymbol(I, ES, Obj.getFileName());
224  break;
225  }
226  } else
227  return SecName.takeError();
228  }
229 
230  return I;
231 }
232 
235  const object::ObjectFile &Obj) {
237 
238  for (auto &Sym : Obj.symbols()) {
239  Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
240  if (!SymFlagsOrErr)
241  // TODO: Test this error.
242  return SymFlagsOrErr.takeError();
243 
244  // Skip symbols not defined in this object file.
245  if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
246  continue;
247 
248  // Skip symbols that are not global.
249  if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
250  continue;
251 
252  // Skip symbols that have type SF_File.
253  if (auto SymType = Sym.getType()) {
254  if (*SymType == object::SymbolRef::ST_File)
255  continue;
256  } else
257  return SymType.takeError();
258 
259  auto Name = Sym.getName();
260  if (!Name)
261  return Name.takeError();
262 
263  auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
264  if (!SymFlags)
265  return SymFlags.takeError();
266 
267  I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
268  }
269 
270  return I;
271 }
272 
275  auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
276 
277  if (!Obj)
278  return Obj.takeError();
279 
280  if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
281  return getMachOObjectFileSymbolInfo(ES, *MachOObj);
282  else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
283  return getELFObjectFileSymbolInfo(ES, *ELFObj);
284  else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
285  return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
286 
287  return getGenericObjectFileSymbolInfo(ES, **Obj);
288 }
289 
290 } // End namespace orc.
291 } // End namespace llvm.
llvm::orc::COFFPlatform::isInitializerSection
static bool isInitializerSection(StringRef Name)
Definition: COFFPlatform.h:70
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::tgtok::Def
@ Def
Definition: TGLexer.h:50
ELFNixPlatform.h
llvm::COFF::IMAGE_COMDAT_SELECT_NODUPLICATES
@ IMAGE_COMDAT_SELECT_NODUPLICATES
Definition: COFF.h:407
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:629
llvm::orc::getGenericObjectFileSymbolInfo
Expected< MaterializationUnit::Interface > getGenericObjectFileSymbolInfo(ExecutionSession &ES, const object::ObjectFile &Obj)
Definition: ObjectFileInterface.cpp:234
llvm::orc::SymbolStringPtr
Pointer to a pooled string representing a symbol name.
Definition: SymbolStringPool.h:57
llvm::COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE
@ IMAGE_COMDAT_SELECT_ASSOCIATIVE
Definition: COFF.h:411
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::object::SymbolRef::ST_File
@ ST_File
Definition: ObjectFile.h:176
llvm::MachO::SECTION_TYPE
@ SECTION_TYPE
Definition: MachO.h:114
COFFPlatform.h
llvm::JITSymbolFlags
Flags for symbols in the JIT.
Definition: JITSymbol.h:74
llvm::MemoryBufferRef
Definition: MemoryBufferRef.h:22
llvm::object::ObjectFile::symbols
symbol_iterator_range symbols() const
Definition: ObjectFile.h:319
MachO.h
llvm::object::ELFObjectFileBase
Definition: ELFObjectFile.h:51
llvm::JITSymbolFlags::MaterializationSideEffectsOnly
@ MaterializationSideEffectsOnly
Definition: JITSymbol.h:87
llvm::ELF::STB_GNU_UNIQUE
@ STB_GNU_UNIQUE
Definition: ELF.h:1220
llvm::orc::getCOFFObjectFileSymbolInfo
static Expected< MaterializationUnit::Interface > getCOFFObjectFileSymbolInfo(ExecutionSession &ES, const object::COFFObjectFile &Obj)
Definition: ObjectFileInterface.cpp:152
llvm::orc::ExecutionSession::intern
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition: Core.h:1416
llvm::orc::MaterializationUnit::Interface
Definition: Core.h:672
llvm::orc::MachOPlatform::isInitializerSection
static bool isInitializerSection(StringRef SegName, StringRef SectName)
Returns true if the given section name is an initializer section.
Definition: MachOPlatform.cpp:318
llvm::object::MachOObjectFile
Definition: MachO.h:406
llvm::object::MachOObjectFile::getSectionType
unsigned getSectionType(SectionRef Sec) const
Definition: MachOObjectFile.cpp:1783
llvm::orc::ELFNixPlatform::isInitializerSection
static bool isInitializerSection(StringRef SecName)
Returns true if the given section name is an initializer section.
Definition: ELFNixPlatform.cpp:275
llvm::MachO::S_MOD_INIT_FUNC_POINTERS
@ S_MOD_INIT_FUNC_POINTERS
S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for initialization.
Definition: MachO.h:147
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::orc::getELFObjectFileSymbolInfo
static Expected< MaterializationUnit::Interface > getELFObjectFileSymbolInfo(ExecutionSession &ES, const object::ELFObjectFileBase &Obj)
Definition: ObjectFileInterface.cpp:98
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::object::BasicSymbolRef::SF_Undefined
@ SF_Undefined
Definition: SymbolicFile.h:110
llvm::object::COFFObjectFile::getNumberOfSections
uint32_t getNumberOfSections() const
Definition: COFF.h:884
llvm::JITSymbolFlags::Callable
@ Callable
Definition: JITSymbol.h:86
llvm::object::ObjectFile::createObjectFile
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Definition: ObjectFile.cpp:194
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ObjectFile.h
llvm::COFF::IMAGE_SCN_LNK_COMDAT
@ IMAGE_SCN_LNK_COMDAT
Definition: COFF.h:294
llvm::object::COFFObjectFile::getCOFFSymbol
COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const
Definition: COFFObjectFile.cpp:1244
llvm::JITSymbolFlags::Weak
@ Weak
Definition: JITSymbol.h:82
llvm::object::ELFObjectFileBase::symbols
elf_symbol_iterator_range symbols() const
Definition: ELFObjectFile.h:236
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::object::ObjectFile
This class is the base class for all object file types.
Definition: ObjectFile.h:228
MachOPlatform.h
llvm::cantFail
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:744
llvm::object::COFFObjectFile::getSection
Expected< const coff_section * > getSection(int32_t index) const
Definition: COFFObjectFile.cpp:1077
ELFObjectFile.h
llvm::None
constexpr std::nullopt_t None
Definition: None.h:27
llvm::orc::ExecutionSession
An ExecutionSession represents a running JIT program.
Definition: Core.h:1365
llvm::orc::getMachOObjectFileSymbolInfo
static Expected< MaterializationUnit::Interface > getMachOObjectFileSymbolInfo(ExecutionSession &ES, const object::MachOObjectFile &Obj)
Definition: ObjectFileInterface.cpp:41
llvm::sampleprof::SecType
SecType
Definition: SampleProf.h:121
llvm::object::COFFObjectFile
Definition: COFF.h:788
llvm::orc::addInitSymbol
void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES, StringRef ObjFileName)
Adds an initializer symbol to the given MU interface.
Definition: ObjectFileInterface.cpp:25
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:596
llvm::object::Binary::getFileName
StringRef getFileName() const
Definition: Binary.cpp:41
COFF.h
llvm::COFF::isReservedSectionNumber
bool isReservedSectionNumber(int32_t SectionNumber)
Definition: COFF.h:792
llvm::object::MachOObjectFile::getSectionFinalSegmentName
StringRef getSectionFinalSegmentName(DataRefImpl Sec) const
Definition: MachOObjectFile.cpp:4507
llvm::orc::getObjectFileInterface
Expected< MaterializationUnit::Interface > getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer)
Returns a MaterializationUnit::Interface for the object file contained in the given buffer,...
Definition: ObjectFileInterface.cpp:274
llvm::object::BasicSymbolRef::SF_Global
@ SF_Global
Definition: SymbolicFile.h:111
llvm::JITSymbolFlags::fromObjectSymbol
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
llvm::object::ObjectFile::sections
section_iterator_range sections() const
Definition: ObjectFile.h:327
llvm::object::MachOObjectFile::getSectionName
Expected< StringRef > getSectionName(DataRefImpl Sec) const override
Definition: MachOObjectFile.cpp:1926
Debug.h
ObjectFileInterface.h
llvm::JITSymbolFlags::Exported
@ Exported
Definition: JITSymbol.h:85