xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10eae32dcSDimitry Andric //===------ ObjectFileInterface.cpp - MU interface utils for objects ------===//
20eae32dcSDimitry Andric //
30eae32dcSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40eae32dcSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60eae32dcSDimitry Andric //
70eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
80eae32dcSDimitry Andric 
90eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
10*bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
110eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
120eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
13753f127fSDimitry Andric #include "llvm/Object/COFF.h"
140eae32dcSDimitry Andric #include "llvm/Object/ELFObjectFile.h"
150eae32dcSDimitry Andric #include "llvm/Object/MachO.h"
160eae32dcSDimitry Andric #include "llvm/Object/ObjectFile.h"
170eae32dcSDimitry Andric #include "llvm/Support/Debug.h"
18*bdd1243dSDimitry Andric #include <optional>
190eae32dcSDimitry Andric 
200eae32dcSDimitry Andric #define DEBUG_TYPE "orc"
210eae32dcSDimitry Andric 
220eae32dcSDimitry Andric namespace llvm {
230eae32dcSDimitry Andric namespace orc {
240eae32dcSDimitry Andric 
250eae32dcSDimitry Andric void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES,
260eae32dcSDimitry Andric                    StringRef ObjFileName) {
270eae32dcSDimitry Andric   assert(!I.InitSymbol && "I already has an init symbol");
280eae32dcSDimitry Andric   size_t Counter = 0;
290eae32dcSDimitry Andric 
300eae32dcSDimitry Andric   do {
310eae32dcSDimitry Andric     std::string InitSymString;
320eae32dcSDimitry Andric     raw_string_ostream(InitSymString)
330eae32dcSDimitry Andric         << "$." << ObjFileName << ".__inits." << Counter++;
340eae32dcSDimitry Andric     I.InitSymbol = ES.intern(InitSymString);
350eae32dcSDimitry Andric   } while (I.SymbolFlags.count(I.InitSymbol));
360eae32dcSDimitry Andric 
370eae32dcSDimitry Andric   I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
380eae32dcSDimitry Andric }
390eae32dcSDimitry Andric 
400eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface>
410eae32dcSDimitry Andric getMachOObjectFileSymbolInfo(ExecutionSession &ES,
420eae32dcSDimitry Andric                              const object::MachOObjectFile &Obj) {
430eae32dcSDimitry Andric   MaterializationUnit::Interface I;
440eae32dcSDimitry Andric 
450eae32dcSDimitry Andric   for (auto &Sym : Obj.symbols()) {
460eae32dcSDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
470eae32dcSDimitry Andric     if (!SymFlagsOrErr)
480eae32dcSDimitry Andric       // TODO: Test this error.
490eae32dcSDimitry Andric       return SymFlagsOrErr.takeError();
500eae32dcSDimitry Andric 
510eae32dcSDimitry Andric     // Skip symbols not defined in this object file.
520eae32dcSDimitry Andric     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
530eae32dcSDimitry Andric       continue;
540eae32dcSDimitry Andric 
550eae32dcSDimitry Andric     // Skip symbols that are not global.
560eae32dcSDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
570eae32dcSDimitry Andric       continue;
580eae32dcSDimitry Andric 
590eae32dcSDimitry Andric     // Skip symbols that have type SF_File.
600eae32dcSDimitry Andric     if (auto SymType = Sym.getType()) {
610eae32dcSDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
620eae32dcSDimitry Andric         continue;
630eae32dcSDimitry Andric     } else
640eae32dcSDimitry Andric       return SymType.takeError();
650eae32dcSDimitry Andric 
660eae32dcSDimitry Andric     auto Name = Sym.getName();
670eae32dcSDimitry Andric     if (!Name)
680eae32dcSDimitry Andric       return Name.takeError();
690eae32dcSDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
700eae32dcSDimitry Andric     if (!SymFlags)
710eae32dcSDimitry Andric       return SymFlags.takeError();
720eae32dcSDimitry Andric 
730eae32dcSDimitry Andric     // Strip the 'exported' flag from MachO linker-private symbols.
740eae32dcSDimitry Andric     if (Name->startswith("l"))
750eae32dcSDimitry Andric       *SymFlags &= ~JITSymbolFlags::Exported;
760eae32dcSDimitry Andric 
7781ad6265SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
780eae32dcSDimitry Andric   }
790eae32dcSDimitry Andric 
800eae32dcSDimitry Andric   for (auto &Sec : Obj.sections()) {
810eae32dcSDimitry Andric     auto SecType = Obj.getSectionType(Sec);
820eae32dcSDimitry Andric     if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {
830eae32dcSDimitry Andric       addInitSymbol(I, ES, Obj.getFileName());
840eae32dcSDimitry Andric       break;
850eae32dcSDimitry Andric     }
860eae32dcSDimitry Andric     auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
870eae32dcSDimitry Andric     auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
880eae32dcSDimitry Andric     if (MachOPlatform::isInitializerSection(SegName, SecName)) {
890eae32dcSDimitry Andric       addInitSymbol(I, ES, Obj.getFileName());
900eae32dcSDimitry Andric       break;
910eae32dcSDimitry Andric     }
920eae32dcSDimitry Andric   }
930eae32dcSDimitry Andric 
940eae32dcSDimitry Andric   return I;
950eae32dcSDimitry Andric }
960eae32dcSDimitry Andric 
970eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface>
980eae32dcSDimitry Andric getELFObjectFileSymbolInfo(ExecutionSession &ES,
990eae32dcSDimitry Andric                            const object::ELFObjectFileBase &Obj) {
1000eae32dcSDimitry Andric   MaterializationUnit::Interface I;
1010eae32dcSDimitry Andric 
1020eae32dcSDimitry Andric   for (auto &Sym : Obj.symbols()) {
1030eae32dcSDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1040eae32dcSDimitry Andric     if (!SymFlagsOrErr)
1050eae32dcSDimitry Andric       // TODO: Test this error.
1060eae32dcSDimitry Andric       return SymFlagsOrErr.takeError();
1070eae32dcSDimitry Andric 
1080eae32dcSDimitry Andric     // Skip symbols not defined in this object file.
1090eae32dcSDimitry Andric     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
1100eae32dcSDimitry Andric       continue;
1110eae32dcSDimitry Andric 
1120eae32dcSDimitry Andric     // Skip symbols that are not global.
1130eae32dcSDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
1140eae32dcSDimitry Andric       continue;
1150eae32dcSDimitry Andric 
1160eae32dcSDimitry Andric     // Skip symbols that have type SF_File.
1170eae32dcSDimitry Andric     if (auto SymType = Sym.getType()) {
1180eae32dcSDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
1190eae32dcSDimitry Andric         continue;
1200eae32dcSDimitry Andric     } else
1210eae32dcSDimitry Andric       return SymType.takeError();
1220eae32dcSDimitry Andric 
1230eae32dcSDimitry Andric     auto Name = Sym.getName();
1240eae32dcSDimitry Andric     if (!Name)
1250eae32dcSDimitry Andric       return Name.takeError();
12681ad6265SDimitry Andric 
1270eae32dcSDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
1280eae32dcSDimitry Andric     if (!SymFlags)
1290eae32dcSDimitry Andric       return SymFlags.takeError();
1300eae32dcSDimitry Andric 
1310eae32dcSDimitry Andric     // ELF STB_GNU_UNIQUE should map to Weak for ORC.
1320eae32dcSDimitry Andric     if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
1330eae32dcSDimitry Andric       *SymFlags |= JITSymbolFlags::Weak;
1340eae32dcSDimitry Andric 
13581ad6265SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
1360eae32dcSDimitry Andric   }
1370eae32dcSDimitry Andric 
1380eae32dcSDimitry Andric   SymbolStringPtr InitSymbol;
1390eae32dcSDimitry Andric   for (auto &Sec : Obj.sections()) {
1400eae32dcSDimitry Andric     if (auto SecName = Sec.getName()) {
1410eae32dcSDimitry Andric       if (ELFNixPlatform::isInitializerSection(*SecName)) {
1420eae32dcSDimitry Andric         addInitSymbol(I, ES, Obj.getFileName());
1430eae32dcSDimitry Andric         break;
1440eae32dcSDimitry Andric       }
1450eae32dcSDimitry Andric     }
1460eae32dcSDimitry Andric   }
1470eae32dcSDimitry Andric 
1480eae32dcSDimitry Andric   return I;
1490eae32dcSDimitry Andric }
1500eae32dcSDimitry Andric 
151753f127fSDimitry Andric static Expected<MaterializationUnit::Interface>
152753f127fSDimitry Andric getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
153753f127fSDimitry Andric                             const object::COFFObjectFile &Obj) {
154753f127fSDimitry Andric   MaterializationUnit::Interface I;
155*bdd1243dSDimitry Andric   std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(
156972a253aSDimitry Andric       Obj.getNumberOfSections() + 1);
157753f127fSDimitry Andric   for (auto &Sym : Obj.symbols()) {
158753f127fSDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
159753f127fSDimitry Andric     if (!SymFlagsOrErr)
160753f127fSDimitry Andric       // TODO: Test this error.
161753f127fSDimitry Andric       return SymFlagsOrErr.takeError();
162753f127fSDimitry Andric 
163972a253aSDimitry Andric     // Handle comdat symbols
164972a253aSDimitry Andric     auto COFFSym = Obj.getCOFFSymbol(Sym);
165972a253aSDimitry Andric     bool IsWeak = false;
166972a253aSDimitry Andric     if (auto *Def = COFFSym.getSectionDefinition()) {
167972a253aSDimitry Andric       auto Sec = Obj.getSection(COFFSym.getSectionNumber());
168972a253aSDimitry Andric       if (!Sec)
169972a253aSDimitry Andric         return Sec.takeError();
170972a253aSDimitry Andric       if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&
171972a253aSDimitry Andric           Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
172972a253aSDimitry Andric         ComdatDefs[COFFSym.getSectionNumber()] = *Def;
173972a253aSDimitry Andric         continue;
174972a253aSDimitry Andric       }
175972a253aSDimitry Andric     }
176972a253aSDimitry Andric     if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&
177972a253aSDimitry Andric         ComdatDefs[COFFSym.getSectionNumber()]) {
178972a253aSDimitry Andric       auto Def = ComdatDefs[COFFSym.getSectionNumber()];
179972a253aSDimitry Andric       if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
180972a253aSDimitry Andric         IsWeak = true;
181972a253aSDimitry Andric       }
182*bdd1243dSDimitry Andric       ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt;
183972a253aSDimitry Andric     } else {
184753f127fSDimitry Andric       // Skip symbols not defined in this object file.
185753f127fSDimitry Andric       if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
186753f127fSDimitry Andric         continue;
187972a253aSDimitry Andric     }
188753f127fSDimitry Andric 
189753f127fSDimitry Andric     // Skip symbols that are not global.
190753f127fSDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
191753f127fSDimitry Andric       continue;
192753f127fSDimitry Andric 
193753f127fSDimitry Andric     // Skip symbols that have type SF_File.
194753f127fSDimitry Andric     if (auto SymType = Sym.getType()) {
195753f127fSDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
196753f127fSDimitry Andric         continue;
197753f127fSDimitry Andric     } else
198753f127fSDimitry Andric       return SymType.takeError();
199753f127fSDimitry Andric 
200753f127fSDimitry Andric     auto Name = Sym.getName();
201753f127fSDimitry Andric     if (!Name)
202753f127fSDimitry Andric       return Name.takeError();
203753f127fSDimitry Andric 
204753f127fSDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
205753f127fSDimitry Andric     if (!SymFlags)
206753f127fSDimitry Andric       return SymFlags.takeError();
207753f127fSDimitry Andric     *SymFlags |= JITSymbolFlags::Exported;
208753f127fSDimitry Andric 
209753f127fSDimitry Andric     // Weak external is always a function
210972a253aSDimitry Andric     if (COFFSym.isWeakExternal())
211753f127fSDimitry Andric       *SymFlags |= JITSymbolFlags::Callable;
212972a253aSDimitry Andric 
213972a253aSDimitry Andric     if (IsWeak)
214972a253aSDimitry Andric       *SymFlags |= JITSymbolFlags::Weak;
215753f127fSDimitry Andric 
216753f127fSDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
217753f127fSDimitry Andric   }
218753f127fSDimitry Andric 
219*bdd1243dSDimitry Andric   SymbolStringPtr InitSymbol;
220*bdd1243dSDimitry Andric   for (auto &Sec : Obj.sections()) {
221*bdd1243dSDimitry Andric     if (auto SecName = Sec.getName()) {
222*bdd1243dSDimitry Andric       if (COFFPlatform::isInitializerSection(*SecName)) {
223*bdd1243dSDimitry Andric         addInitSymbol(I, ES, Obj.getFileName());
224*bdd1243dSDimitry Andric         break;
225*bdd1243dSDimitry Andric       }
226*bdd1243dSDimitry Andric     } else
227*bdd1243dSDimitry Andric       return SecName.takeError();
228*bdd1243dSDimitry Andric   }
229753f127fSDimitry Andric 
230753f127fSDimitry Andric   return I;
231753f127fSDimitry Andric }
232753f127fSDimitry Andric 
2330eae32dcSDimitry Andric Expected<MaterializationUnit::Interface>
2340eae32dcSDimitry Andric getGenericObjectFileSymbolInfo(ExecutionSession &ES,
2350eae32dcSDimitry Andric                                const object::ObjectFile &Obj) {
2360eae32dcSDimitry Andric   MaterializationUnit::Interface I;
2370eae32dcSDimitry Andric 
2380eae32dcSDimitry Andric   for (auto &Sym : Obj.symbols()) {
2390eae32dcSDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
2400eae32dcSDimitry Andric     if (!SymFlagsOrErr)
2410eae32dcSDimitry Andric       // TODO: Test this error.
2420eae32dcSDimitry Andric       return SymFlagsOrErr.takeError();
2430eae32dcSDimitry Andric 
2440eae32dcSDimitry Andric     // Skip symbols not defined in this object file.
2450eae32dcSDimitry Andric     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
2460eae32dcSDimitry Andric       continue;
2470eae32dcSDimitry Andric 
2480eae32dcSDimitry Andric     // Skip symbols that are not global.
2490eae32dcSDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
2500eae32dcSDimitry Andric       continue;
2510eae32dcSDimitry Andric 
2520eae32dcSDimitry Andric     // Skip symbols that have type SF_File.
2530eae32dcSDimitry Andric     if (auto SymType = Sym.getType()) {
2540eae32dcSDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
2550eae32dcSDimitry Andric         continue;
2560eae32dcSDimitry Andric     } else
2570eae32dcSDimitry Andric       return SymType.takeError();
2580eae32dcSDimitry Andric 
2590eae32dcSDimitry Andric     auto Name = Sym.getName();
2600eae32dcSDimitry Andric     if (!Name)
2610eae32dcSDimitry Andric       return Name.takeError();
26281ad6265SDimitry Andric 
2630eae32dcSDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
2640eae32dcSDimitry Andric     if (!SymFlags)
2650eae32dcSDimitry Andric       return SymFlags.takeError();
2660eae32dcSDimitry Andric 
26781ad6265SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
2680eae32dcSDimitry Andric   }
2690eae32dcSDimitry Andric 
2700eae32dcSDimitry Andric   return I;
2710eae32dcSDimitry Andric }
2720eae32dcSDimitry Andric 
2730eae32dcSDimitry Andric Expected<MaterializationUnit::Interface>
2740eae32dcSDimitry Andric getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
2750eae32dcSDimitry Andric   auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
2760eae32dcSDimitry Andric 
2770eae32dcSDimitry Andric   if (!Obj)
2780eae32dcSDimitry Andric     return Obj.takeError();
2790eae32dcSDimitry Andric 
2800eae32dcSDimitry Andric   if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
2810eae32dcSDimitry Andric     return getMachOObjectFileSymbolInfo(ES, *MachOObj);
2820eae32dcSDimitry Andric   else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
2830eae32dcSDimitry Andric     return getELFObjectFileSymbolInfo(ES, *ELFObj);
284753f127fSDimitry Andric   else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
285753f127fSDimitry Andric     return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
2860eae32dcSDimitry Andric 
2870eae32dcSDimitry Andric   return getGenericObjectFileSymbolInfo(ES, **Obj);
2880eae32dcSDimitry Andric }
2890eae32dcSDimitry Andric 
290*bdd1243dSDimitry Andric bool hasInitializerSection(jitlink::LinkGraph &G) {
291*bdd1243dSDimitry Andric   bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
292*bdd1243dSDimitry Andric   bool IsElf = G.getTargetTriple().isOSBinFormatELF();
293*bdd1243dSDimitry Andric   if (!IsMachO && !IsElf)
294*bdd1243dSDimitry Andric     return false;
295*bdd1243dSDimitry Andric 
296*bdd1243dSDimitry Andric   for (auto &Sec : G.sections()) {
297*bdd1243dSDimitry Andric     if (IsMachO && std::apply(MachOPlatform::isInitializerSection,
298*bdd1243dSDimitry Andric                               Sec.getName().split(",")))
299*bdd1243dSDimitry Andric       return true;
300*bdd1243dSDimitry Andric     if (IsElf && ELFNixPlatform::isInitializerSection(Sec.getName()))
301*bdd1243dSDimitry Andric       return true;
302*bdd1243dSDimitry Andric   }
303*bdd1243dSDimitry Andric 
304*bdd1243dSDimitry Andric   return false;
305*bdd1243dSDimitry Andric }
306*bdd1243dSDimitry Andric 
3070eae32dcSDimitry Andric } // End namespace orc.
3080eae32dcSDimitry Andric } // End namespace llvm.
309