xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp (revision 972a253a57b6f144b0e4a3e2080a2a0076ec55a0)
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"
100eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
110eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
12753f127fSDimitry Andric #include "llvm/Object/COFF.h"
130eae32dcSDimitry Andric #include "llvm/Object/ELFObjectFile.h"
140eae32dcSDimitry Andric #include "llvm/Object/MachO.h"
150eae32dcSDimitry Andric #include "llvm/Object/ObjectFile.h"
160eae32dcSDimitry Andric #include "llvm/Support/Debug.h"
170eae32dcSDimitry Andric 
180eae32dcSDimitry Andric #define DEBUG_TYPE "orc"
190eae32dcSDimitry Andric 
200eae32dcSDimitry Andric namespace llvm {
210eae32dcSDimitry Andric namespace orc {
220eae32dcSDimitry Andric 
230eae32dcSDimitry Andric void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES,
240eae32dcSDimitry Andric                    StringRef ObjFileName) {
250eae32dcSDimitry Andric   assert(!I.InitSymbol && "I already has an init symbol");
260eae32dcSDimitry Andric   size_t Counter = 0;
270eae32dcSDimitry Andric 
280eae32dcSDimitry Andric   do {
290eae32dcSDimitry Andric     std::string InitSymString;
300eae32dcSDimitry Andric     raw_string_ostream(InitSymString)
310eae32dcSDimitry Andric         << "$." << ObjFileName << ".__inits." << Counter++;
320eae32dcSDimitry Andric     I.InitSymbol = ES.intern(InitSymString);
330eae32dcSDimitry Andric   } while (I.SymbolFlags.count(I.InitSymbol));
340eae32dcSDimitry Andric 
350eae32dcSDimitry Andric   I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
360eae32dcSDimitry Andric }
370eae32dcSDimitry Andric 
380eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface>
390eae32dcSDimitry Andric getMachOObjectFileSymbolInfo(ExecutionSession &ES,
400eae32dcSDimitry Andric                              const object::MachOObjectFile &Obj) {
410eae32dcSDimitry Andric   MaterializationUnit::Interface I;
420eae32dcSDimitry Andric 
430eae32dcSDimitry Andric   for (auto &Sym : Obj.symbols()) {
440eae32dcSDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
450eae32dcSDimitry Andric     if (!SymFlagsOrErr)
460eae32dcSDimitry Andric       // TODO: Test this error.
470eae32dcSDimitry Andric       return SymFlagsOrErr.takeError();
480eae32dcSDimitry Andric 
490eae32dcSDimitry Andric     // Skip symbols not defined in this object file.
500eae32dcSDimitry Andric     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
510eae32dcSDimitry Andric       continue;
520eae32dcSDimitry Andric 
530eae32dcSDimitry Andric     // Skip symbols that are not global.
540eae32dcSDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
550eae32dcSDimitry Andric       continue;
560eae32dcSDimitry Andric 
570eae32dcSDimitry Andric     // Skip symbols that have type SF_File.
580eae32dcSDimitry Andric     if (auto SymType = Sym.getType()) {
590eae32dcSDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
600eae32dcSDimitry Andric         continue;
610eae32dcSDimitry Andric     } else
620eae32dcSDimitry Andric       return SymType.takeError();
630eae32dcSDimitry Andric 
640eae32dcSDimitry Andric     auto Name = Sym.getName();
650eae32dcSDimitry Andric     if (!Name)
660eae32dcSDimitry Andric       return Name.takeError();
670eae32dcSDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
680eae32dcSDimitry Andric     if (!SymFlags)
690eae32dcSDimitry Andric       return SymFlags.takeError();
700eae32dcSDimitry Andric 
710eae32dcSDimitry Andric     // Strip the 'exported' flag from MachO linker-private symbols.
720eae32dcSDimitry Andric     if (Name->startswith("l"))
730eae32dcSDimitry Andric       *SymFlags &= ~JITSymbolFlags::Exported;
740eae32dcSDimitry Andric 
7581ad6265SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
760eae32dcSDimitry Andric   }
770eae32dcSDimitry Andric 
780eae32dcSDimitry Andric   for (auto &Sec : Obj.sections()) {
790eae32dcSDimitry Andric     auto SecType = Obj.getSectionType(Sec);
800eae32dcSDimitry Andric     if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {
810eae32dcSDimitry Andric       addInitSymbol(I, ES, Obj.getFileName());
820eae32dcSDimitry Andric       break;
830eae32dcSDimitry Andric     }
840eae32dcSDimitry Andric     auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
850eae32dcSDimitry Andric     auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
860eae32dcSDimitry Andric     if (MachOPlatform::isInitializerSection(SegName, SecName)) {
870eae32dcSDimitry Andric       addInitSymbol(I, ES, Obj.getFileName());
880eae32dcSDimitry Andric       break;
890eae32dcSDimitry Andric     }
900eae32dcSDimitry Andric   }
910eae32dcSDimitry Andric 
920eae32dcSDimitry Andric   return I;
930eae32dcSDimitry Andric }
940eae32dcSDimitry Andric 
950eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface>
960eae32dcSDimitry Andric getELFObjectFileSymbolInfo(ExecutionSession &ES,
970eae32dcSDimitry Andric                            const object::ELFObjectFileBase &Obj) {
980eae32dcSDimitry Andric   MaterializationUnit::Interface I;
990eae32dcSDimitry Andric 
1000eae32dcSDimitry Andric   for (auto &Sym : Obj.symbols()) {
1010eae32dcSDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1020eae32dcSDimitry Andric     if (!SymFlagsOrErr)
1030eae32dcSDimitry Andric       // TODO: Test this error.
1040eae32dcSDimitry Andric       return SymFlagsOrErr.takeError();
1050eae32dcSDimitry Andric 
1060eae32dcSDimitry Andric     // Skip symbols not defined in this object file.
1070eae32dcSDimitry Andric     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
1080eae32dcSDimitry Andric       continue;
1090eae32dcSDimitry Andric 
1100eae32dcSDimitry Andric     // Skip symbols that are not global.
1110eae32dcSDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
1120eae32dcSDimitry Andric       continue;
1130eae32dcSDimitry Andric 
1140eae32dcSDimitry Andric     // Skip symbols that have type SF_File.
1150eae32dcSDimitry Andric     if (auto SymType = Sym.getType()) {
1160eae32dcSDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
1170eae32dcSDimitry Andric         continue;
1180eae32dcSDimitry Andric     } else
1190eae32dcSDimitry Andric       return SymType.takeError();
1200eae32dcSDimitry Andric 
1210eae32dcSDimitry Andric     auto Name = Sym.getName();
1220eae32dcSDimitry Andric     if (!Name)
1230eae32dcSDimitry Andric       return Name.takeError();
12481ad6265SDimitry Andric 
1250eae32dcSDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
1260eae32dcSDimitry Andric     if (!SymFlags)
1270eae32dcSDimitry Andric       return SymFlags.takeError();
1280eae32dcSDimitry Andric 
1290eae32dcSDimitry Andric     // ELF STB_GNU_UNIQUE should map to Weak for ORC.
1300eae32dcSDimitry Andric     if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
1310eae32dcSDimitry Andric       *SymFlags |= JITSymbolFlags::Weak;
1320eae32dcSDimitry Andric 
13381ad6265SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
1340eae32dcSDimitry Andric   }
1350eae32dcSDimitry Andric 
1360eae32dcSDimitry Andric   SymbolStringPtr InitSymbol;
1370eae32dcSDimitry Andric   for (auto &Sec : Obj.sections()) {
1380eae32dcSDimitry Andric     if (auto SecName = Sec.getName()) {
1390eae32dcSDimitry Andric       if (ELFNixPlatform::isInitializerSection(*SecName)) {
1400eae32dcSDimitry Andric         addInitSymbol(I, ES, Obj.getFileName());
1410eae32dcSDimitry Andric         break;
1420eae32dcSDimitry Andric       }
1430eae32dcSDimitry Andric     }
1440eae32dcSDimitry Andric   }
1450eae32dcSDimitry Andric 
1460eae32dcSDimitry Andric   return I;
1470eae32dcSDimitry Andric }
1480eae32dcSDimitry Andric 
149753f127fSDimitry Andric static Expected<MaterializationUnit::Interface>
150753f127fSDimitry Andric getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
151753f127fSDimitry Andric                             const object::COFFObjectFile &Obj) {
152753f127fSDimitry Andric   MaterializationUnit::Interface I;
153*972a253aSDimitry Andric   std::vector<Optional<object::coff_aux_section_definition>> ComdatDefs(
154*972a253aSDimitry Andric       Obj.getNumberOfSections() + 1);
155753f127fSDimitry Andric   for (auto &Sym : Obj.symbols()) {
156753f127fSDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
157753f127fSDimitry Andric     if (!SymFlagsOrErr)
158753f127fSDimitry Andric       // TODO: Test this error.
159753f127fSDimitry Andric       return SymFlagsOrErr.takeError();
160753f127fSDimitry Andric 
161*972a253aSDimitry Andric     // Handle comdat symbols
162*972a253aSDimitry Andric     auto COFFSym = Obj.getCOFFSymbol(Sym);
163*972a253aSDimitry Andric     bool IsWeak = false;
164*972a253aSDimitry Andric     if (auto *Def = COFFSym.getSectionDefinition()) {
165*972a253aSDimitry Andric       auto Sec = Obj.getSection(COFFSym.getSectionNumber());
166*972a253aSDimitry Andric       if (!Sec)
167*972a253aSDimitry Andric         return Sec.takeError();
168*972a253aSDimitry Andric       if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&
169*972a253aSDimitry Andric           Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
170*972a253aSDimitry Andric         ComdatDefs[COFFSym.getSectionNumber()] = *Def;
171*972a253aSDimitry Andric         continue;
172*972a253aSDimitry Andric       }
173*972a253aSDimitry Andric     }
174*972a253aSDimitry Andric     if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&
175*972a253aSDimitry Andric         ComdatDefs[COFFSym.getSectionNumber()]) {
176*972a253aSDimitry Andric       auto Def = ComdatDefs[COFFSym.getSectionNumber()];
177*972a253aSDimitry Andric       if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
178*972a253aSDimitry Andric         IsWeak = true;
179*972a253aSDimitry Andric       }
180*972a253aSDimitry Andric       ComdatDefs[COFFSym.getSectionNumber()] = None;
181*972a253aSDimitry Andric     } else {
182753f127fSDimitry Andric       // Skip symbols not defined in this object file.
183753f127fSDimitry Andric       if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
184753f127fSDimitry Andric         continue;
185*972a253aSDimitry Andric     }
186753f127fSDimitry Andric 
187753f127fSDimitry Andric     // Skip symbols that are not global.
188753f127fSDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
189753f127fSDimitry Andric       continue;
190753f127fSDimitry Andric 
191753f127fSDimitry Andric     // Skip symbols that have type SF_File.
192753f127fSDimitry Andric     if (auto SymType = Sym.getType()) {
193753f127fSDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
194753f127fSDimitry Andric         continue;
195753f127fSDimitry Andric     } else
196753f127fSDimitry Andric       return SymType.takeError();
197753f127fSDimitry Andric 
198753f127fSDimitry Andric     auto Name = Sym.getName();
199753f127fSDimitry Andric     if (!Name)
200753f127fSDimitry Andric       return Name.takeError();
201753f127fSDimitry Andric 
202753f127fSDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
203753f127fSDimitry Andric     if (!SymFlags)
204753f127fSDimitry Andric       return SymFlags.takeError();
205753f127fSDimitry Andric     *SymFlags |= JITSymbolFlags::Exported;
206753f127fSDimitry Andric 
207753f127fSDimitry Andric     // Weak external is always a function
208*972a253aSDimitry Andric     if (COFFSym.isWeakExternal())
209753f127fSDimitry Andric       *SymFlags |= JITSymbolFlags::Callable;
210*972a253aSDimitry Andric 
211*972a253aSDimitry Andric     if (IsWeak)
212*972a253aSDimitry Andric       *SymFlags |= JITSymbolFlags::Weak;
213753f127fSDimitry Andric 
214753f127fSDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
215753f127fSDimitry Andric   }
216753f127fSDimitry Andric 
217753f127fSDimitry Andric   // FIXME: handle init symbols
218753f127fSDimitry Andric 
219753f127fSDimitry Andric   return I;
220753f127fSDimitry Andric }
221753f127fSDimitry Andric 
2220eae32dcSDimitry Andric Expected<MaterializationUnit::Interface>
2230eae32dcSDimitry Andric getGenericObjectFileSymbolInfo(ExecutionSession &ES,
2240eae32dcSDimitry Andric                                const object::ObjectFile &Obj) {
2250eae32dcSDimitry Andric   MaterializationUnit::Interface I;
2260eae32dcSDimitry Andric 
2270eae32dcSDimitry Andric   for (auto &Sym : Obj.symbols()) {
2280eae32dcSDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
2290eae32dcSDimitry Andric     if (!SymFlagsOrErr)
2300eae32dcSDimitry Andric       // TODO: Test this error.
2310eae32dcSDimitry Andric       return SymFlagsOrErr.takeError();
2320eae32dcSDimitry Andric 
2330eae32dcSDimitry Andric     // Skip symbols not defined in this object file.
2340eae32dcSDimitry Andric     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
2350eae32dcSDimitry Andric       continue;
2360eae32dcSDimitry Andric 
2370eae32dcSDimitry Andric     // Skip symbols that are not global.
2380eae32dcSDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
2390eae32dcSDimitry Andric       continue;
2400eae32dcSDimitry Andric 
2410eae32dcSDimitry Andric     // Skip symbols that have type SF_File.
2420eae32dcSDimitry Andric     if (auto SymType = Sym.getType()) {
2430eae32dcSDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
2440eae32dcSDimitry Andric         continue;
2450eae32dcSDimitry Andric     } else
2460eae32dcSDimitry Andric       return SymType.takeError();
2470eae32dcSDimitry Andric 
2480eae32dcSDimitry Andric     auto Name = Sym.getName();
2490eae32dcSDimitry Andric     if (!Name)
2500eae32dcSDimitry Andric       return Name.takeError();
25181ad6265SDimitry Andric 
2520eae32dcSDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
2530eae32dcSDimitry Andric     if (!SymFlags)
2540eae32dcSDimitry Andric       return SymFlags.takeError();
2550eae32dcSDimitry Andric 
25681ad6265SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
2570eae32dcSDimitry Andric   }
2580eae32dcSDimitry Andric 
2590eae32dcSDimitry Andric   return I;
2600eae32dcSDimitry Andric }
2610eae32dcSDimitry Andric 
2620eae32dcSDimitry Andric Expected<MaterializationUnit::Interface>
2630eae32dcSDimitry Andric getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
2640eae32dcSDimitry Andric   auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
2650eae32dcSDimitry Andric 
2660eae32dcSDimitry Andric   if (!Obj)
2670eae32dcSDimitry Andric     return Obj.takeError();
2680eae32dcSDimitry Andric 
2690eae32dcSDimitry Andric   if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
2700eae32dcSDimitry Andric     return getMachOObjectFileSymbolInfo(ES, *MachOObj);
2710eae32dcSDimitry Andric   else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
2720eae32dcSDimitry Andric     return getELFObjectFileSymbolInfo(ES, *ELFObj);
273753f127fSDimitry Andric   else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
274753f127fSDimitry Andric     return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
2750eae32dcSDimitry Andric 
2760eae32dcSDimitry Andric   return getGenericObjectFileSymbolInfo(ES, **Obj);
2770eae32dcSDimitry Andric }
2780eae32dcSDimitry Andric 
2790eae32dcSDimitry Andric } // End namespace orc.
2800eae32dcSDimitry Andric } // End namespace llvm.
281