xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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"
120eae32dcSDimitry Andric #include "llvm/Object/ELFObjectFile.h"
130eae32dcSDimitry Andric #include "llvm/Object/MachO.h"
140eae32dcSDimitry Andric #include "llvm/Object/ObjectFile.h"
150eae32dcSDimitry Andric #include "llvm/Support/Debug.h"
160eae32dcSDimitry Andric 
170eae32dcSDimitry Andric #define DEBUG_TYPE "orc"
180eae32dcSDimitry Andric 
190eae32dcSDimitry Andric namespace llvm {
200eae32dcSDimitry Andric namespace orc {
210eae32dcSDimitry Andric 
220eae32dcSDimitry Andric void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES,
230eae32dcSDimitry Andric                    StringRef ObjFileName) {
240eae32dcSDimitry Andric   assert(!I.InitSymbol && "I already has an init symbol");
250eae32dcSDimitry Andric   size_t Counter = 0;
260eae32dcSDimitry Andric 
270eae32dcSDimitry Andric   do {
280eae32dcSDimitry Andric     std::string InitSymString;
290eae32dcSDimitry Andric     raw_string_ostream(InitSymString)
300eae32dcSDimitry Andric         << "$." << ObjFileName << ".__inits." << Counter++;
310eae32dcSDimitry Andric     I.InitSymbol = ES.intern(InitSymString);
320eae32dcSDimitry Andric   } while (I.SymbolFlags.count(I.InitSymbol));
330eae32dcSDimitry Andric 
340eae32dcSDimitry Andric   I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
350eae32dcSDimitry Andric }
360eae32dcSDimitry Andric 
370eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface>
380eae32dcSDimitry Andric getMachOObjectFileSymbolInfo(ExecutionSession &ES,
390eae32dcSDimitry Andric                              const object::MachOObjectFile &Obj) {
400eae32dcSDimitry Andric   MaterializationUnit::Interface I;
410eae32dcSDimitry Andric 
420eae32dcSDimitry Andric   for (auto &Sym : Obj.symbols()) {
430eae32dcSDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
440eae32dcSDimitry Andric     if (!SymFlagsOrErr)
450eae32dcSDimitry Andric       // TODO: Test this error.
460eae32dcSDimitry Andric       return SymFlagsOrErr.takeError();
470eae32dcSDimitry Andric 
480eae32dcSDimitry Andric     // Skip symbols not defined in this object file.
490eae32dcSDimitry Andric     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
500eae32dcSDimitry Andric       continue;
510eae32dcSDimitry Andric 
520eae32dcSDimitry Andric     // Skip symbols that are not global.
530eae32dcSDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
540eae32dcSDimitry Andric       continue;
550eae32dcSDimitry Andric 
560eae32dcSDimitry Andric     // Skip symbols that have type SF_File.
570eae32dcSDimitry Andric     if (auto SymType = Sym.getType()) {
580eae32dcSDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
590eae32dcSDimitry Andric         continue;
600eae32dcSDimitry Andric     } else
610eae32dcSDimitry Andric       return SymType.takeError();
620eae32dcSDimitry Andric 
630eae32dcSDimitry Andric     auto Name = Sym.getName();
640eae32dcSDimitry Andric     if (!Name)
650eae32dcSDimitry Andric       return Name.takeError();
660eae32dcSDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
670eae32dcSDimitry Andric     if (!SymFlags)
680eae32dcSDimitry Andric       return SymFlags.takeError();
690eae32dcSDimitry Andric 
700eae32dcSDimitry Andric     // Strip the 'exported' flag from MachO linker-private symbols.
710eae32dcSDimitry Andric     if (Name->startswith("l"))
720eae32dcSDimitry Andric       *SymFlags &= ~JITSymbolFlags::Exported;
730eae32dcSDimitry Andric 
74*81ad6265SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
750eae32dcSDimitry Andric   }
760eae32dcSDimitry Andric 
770eae32dcSDimitry Andric   for (auto &Sec : Obj.sections()) {
780eae32dcSDimitry Andric     auto SecType = Obj.getSectionType(Sec);
790eae32dcSDimitry Andric     if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {
800eae32dcSDimitry Andric       addInitSymbol(I, ES, Obj.getFileName());
810eae32dcSDimitry Andric       break;
820eae32dcSDimitry Andric     }
830eae32dcSDimitry Andric     auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
840eae32dcSDimitry Andric     auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
850eae32dcSDimitry Andric     if (MachOPlatform::isInitializerSection(SegName, SecName)) {
860eae32dcSDimitry Andric       addInitSymbol(I, ES, Obj.getFileName());
870eae32dcSDimitry Andric       break;
880eae32dcSDimitry Andric     }
890eae32dcSDimitry Andric   }
900eae32dcSDimitry Andric 
910eae32dcSDimitry Andric   return I;
920eae32dcSDimitry Andric }
930eae32dcSDimitry Andric 
940eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface>
950eae32dcSDimitry Andric getELFObjectFileSymbolInfo(ExecutionSession &ES,
960eae32dcSDimitry Andric                            const object::ELFObjectFileBase &Obj) {
970eae32dcSDimitry Andric   MaterializationUnit::Interface I;
980eae32dcSDimitry Andric 
990eae32dcSDimitry Andric   for (auto &Sym : Obj.symbols()) {
1000eae32dcSDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1010eae32dcSDimitry Andric     if (!SymFlagsOrErr)
1020eae32dcSDimitry Andric       // TODO: Test this error.
1030eae32dcSDimitry Andric       return SymFlagsOrErr.takeError();
1040eae32dcSDimitry Andric 
1050eae32dcSDimitry Andric     // Skip symbols not defined in this object file.
1060eae32dcSDimitry Andric     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
1070eae32dcSDimitry Andric       continue;
1080eae32dcSDimitry Andric 
1090eae32dcSDimitry Andric     // Skip symbols that are not global.
1100eae32dcSDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
1110eae32dcSDimitry Andric       continue;
1120eae32dcSDimitry Andric 
1130eae32dcSDimitry Andric     // Skip symbols that have type SF_File.
1140eae32dcSDimitry Andric     if (auto SymType = Sym.getType()) {
1150eae32dcSDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
1160eae32dcSDimitry Andric         continue;
1170eae32dcSDimitry Andric     } else
1180eae32dcSDimitry Andric       return SymType.takeError();
1190eae32dcSDimitry Andric 
1200eae32dcSDimitry Andric     auto Name = Sym.getName();
1210eae32dcSDimitry Andric     if (!Name)
1220eae32dcSDimitry Andric       return Name.takeError();
123*81ad6265SDimitry Andric 
1240eae32dcSDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
1250eae32dcSDimitry Andric     if (!SymFlags)
1260eae32dcSDimitry Andric       return SymFlags.takeError();
1270eae32dcSDimitry Andric 
1280eae32dcSDimitry Andric     // ELF STB_GNU_UNIQUE should map to Weak for ORC.
1290eae32dcSDimitry Andric     if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
1300eae32dcSDimitry Andric       *SymFlags |= JITSymbolFlags::Weak;
1310eae32dcSDimitry Andric 
132*81ad6265SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
1330eae32dcSDimitry Andric   }
1340eae32dcSDimitry Andric 
1350eae32dcSDimitry Andric   SymbolStringPtr InitSymbol;
1360eae32dcSDimitry Andric   for (auto &Sec : Obj.sections()) {
1370eae32dcSDimitry Andric     if (auto SecName = Sec.getName()) {
1380eae32dcSDimitry Andric       if (ELFNixPlatform::isInitializerSection(*SecName)) {
1390eae32dcSDimitry Andric         addInitSymbol(I, ES, Obj.getFileName());
1400eae32dcSDimitry Andric         break;
1410eae32dcSDimitry Andric       }
1420eae32dcSDimitry Andric     }
1430eae32dcSDimitry Andric   }
1440eae32dcSDimitry Andric 
1450eae32dcSDimitry Andric   return I;
1460eae32dcSDimitry Andric }
1470eae32dcSDimitry Andric 
1480eae32dcSDimitry Andric Expected<MaterializationUnit::Interface>
1490eae32dcSDimitry Andric getGenericObjectFileSymbolInfo(ExecutionSession &ES,
1500eae32dcSDimitry Andric                                const object::ObjectFile &Obj) {
1510eae32dcSDimitry Andric   MaterializationUnit::Interface I;
1520eae32dcSDimitry Andric 
1530eae32dcSDimitry Andric   for (auto &Sym : Obj.symbols()) {
1540eae32dcSDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1550eae32dcSDimitry Andric     if (!SymFlagsOrErr)
1560eae32dcSDimitry Andric       // TODO: Test this error.
1570eae32dcSDimitry Andric       return SymFlagsOrErr.takeError();
1580eae32dcSDimitry Andric 
1590eae32dcSDimitry Andric     // Skip symbols not defined in this object file.
1600eae32dcSDimitry Andric     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
1610eae32dcSDimitry Andric       continue;
1620eae32dcSDimitry Andric 
1630eae32dcSDimitry Andric     // Skip symbols that are not global.
1640eae32dcSDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
1650eae32dcSDimitry Andric       continue;
1660eae32dcSDimitry Andric 
1670eae32dcSDimitry Andric     // Skip symbols that have type SF_File.
1680eae32dcSDimitry Andric     if (auto SymType = Sym.getType()) {
1690eae32dcSDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
1700eae32dcSDimitry Andric         continue;
1710eae32dcSDimitry Andric     } else
1720eae32dcSDimitry Andric       return SymType.takeError();
1730eae32dcSDimitry Andric 
1740eae32dcSDimitry Andric     auto Name = Sym.getName();
1750eae32dcSDimitry Andric     if (!Name)
1760eae32dcSDimitry Andric       return Name.takeError();
177*81ad6265SDimitry Andric 
1780eae32dcSDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
1790eae32dcSDimitry Andric     if (!SymFlags)
1800eae32dcSDimitry Andric       return SymFlags.takeError();
1810eae32dcSDimitry Andric 
182*81ad6265SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
1830eae32dcSDimitry Andric   }
1840eae32dcSDimitry Andric 
1850eae32dcSDimitry Andric   return I;
1860eae32dcSDimitry Andric }
1870eae32dcSDimitry Andric 
1880eae32dcSDimitry Andric Expected<MaterializationUnit::Interface>
1890eae32dcSDimitry Andric getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
1900eae32dcSDimitry Andric   auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
1910eae32dcSDimitry Andric 
1920eae32dcSDimitry Andric   if (!Obj)
1930eae32dcSDimitry Andric     return Obj.takeError();
1940eae32dcSDimitry Andric 
1950eae32dcSDimitry Andric   if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
1960eae32dcSDimitry Andric     return getMachOObjectFileSymbolInfo(ES, *MachOObj);
1970eae32dcSDimitry Andric   else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
1980eae32dcSDimitry Andric     return getELFObjectFileSymbolInfo(ES, *ELFObj);
1990eae32dcSDimitry Andric 
2000eae32dcSDimitry Andric   return getGenericObjectFileSymbolInfo(ES, **Obj);
2010eae32dcSDimitry Andric }
2020eae32dcSDimitry Andric 
2030eae32dcSDimitry Andric } // End namespace orc.
2040eae32dcSDimitry Andric } // End namespace llvm.
205