14299d8d0SLang Hames //===------ ObjectFileInterface.cpp - MU interface utils for objects ------===//
24299d8d0SLang Hames //
34299d8d0SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44299d8d0SLang Hames // See https://llvm.org/LICENSE.txt for license information.
54299d8d0SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64299d8d0SLang Hames //
74299d8d0SLang Hames //===----------------------------------------------------------------------===//
84299d8d0SLang Hames 
94299d8d0SLang Hames #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
104299d8d0SLang Hames #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
114299d8d0SLang Hames #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
124299d8d0SLang Hames #include "llvm/Object/ELFObjectFile.h"
134299d8d0SLang Hames #include "llvm/Object/MachO.h"
144299d8d0SLang Hames #include "llvm/Object/ObjectFile.h"
154299d8d0SLang Hames #include "llvm/Support/Debug.h"
164299d8d0SLang Hames 
174299d8d0SLang Hames #define DEBUG_TYPE "orc"
184299d8d0SLang Hames 
194299d8d0SLang Hames namespace llvm {
204299d8d0SLang Hames namespace orc {
214299d8d0SLang Hames 
224299d8d0SLang Hames void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES,
234299d8d0SLang Hames                    StringRef ObjFileName) {
244299d8d0SLang Hames   assert(!I.InitSymbol && "I already has an init symbol");
254299d8d0SLang Hames   size_t Counter = 0;
264299d8d0SLang Hames 
274299d8d0SLang Hames   do {
284299d8d0SLang Hames     std::string InitSymString;
294299d8d0SLang Hames     raw_string_ostream(InitSymString)
304299d8d0SLang Hames         << "$." << ObjFileName << ".__inits." << Counter++;
314299d8d0SLang Hames     I.InitSymbol = ES.intern(InitSymString);
324299d8d0SLang Hames   } while (I.SymbolFlags.count(I.InitSymbol));
334299d8d0SLang Hames 
344299d8d0SLang Hames   I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
354299d8d0SLang Hames }
364299d8d0SLang Hames 
374299d8d0SLang Hames static Expected<MaterializationUnit::Interface>
384299d8d0SLang Hames getMachOObjectFileSymbolInfo(ExecutionSession &ES,
394299d8d0SLang Hames                              const object::MachOObjectFile &Obj) {
404299d8d0SLang Hames   MaterializationUnit::Interface I;
414299d8d0SLang Hames 
424299d8d0SLang Hames   for (auto &Sym : Obj.symbols()) {
434299d8d0SLang Hames     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
444299d8d0SLang Hames     if (!SymFlagsOrErr)
454299d8d0SLang Hames       // TODO: Test this error.
464299d8d0SLang Hames       return SymFlagsOrErr.takeError();
474299d8d0SLang Hames 
484299d8d0SLang Hames     // Skip symbols not defined in this object file.
494299d8d0SLang Hames     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
504299d8d0SLang Hames       continue;
514299d8d0SLang Hames 
524299d8d0SLang Hames     // Skip symbols that are not global.
534299d8d0SLang Hames     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
544299d8d0SLang Hames       continue;
554299d8d0SLang Hames 
564299d8d0SLang Hames     // Skip symbols that have type SF_File.
574299d8d0SLang Hames     if (auto SymType = Sym.getType()) {
584299d8d0SLang Hames       if (*SymType == object::SymbolRef::ST_File)
594299d8d0SLang Hames         continue;
604299d8d0SLang Hames     } else
614299d8d0SLang Hames       return SymType.takeError();
624299d8d0SLang Hames 
634299d8d0SLang Hames     auto Name = Sym.getName();
644299d8d0SLang Hames     if (!Name)
654299d8d0SLang Hames       return Name.takeError();
664299d8d0SLang Hames     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
674299d8d0SLang Hames     if (!SymFlags)
684299d8d0SLang Hames       return SymFlags.takeError();
694299d8d0SLang Hames 
704299d8d0SLang Hames     // Strip the 'exported' flag from MachO linker-private symbols.
714299d8d0SLang Hames     if (Name->startswith("l"))
724299d8d0SLang Hames       *SymFlags &= ~JITSymbolFlags::Exported;
734299d8d0SLang Hames 
74*2ca81cd9SLang Hames     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
754299d8d0SLang Hames   }
764299d8d0SLang Hames 
774299d8d0SLang Hames   for (auto &Sec : Obj.sections()) {
784299d8d0SLang Hames     auto SecType = Obj.getSectionType(Sec);
794299d8d0SLang Hames     if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {
804299d8d0SLang Hames       addInitSymbol(I, ES, Obj.getFileName());
814299d8d0SLang Hames       break;
824299d8d0SLang Hames     }
834299d8d0SLang Hames     auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
844299d8d0SLang Hames     auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
854299d8d0SLang Hames     if (MachOPlatform::isInitializerSection(SegName, SecName)) {
864299d8d0SLang Hames       addInitSymbol(I, ES, Obj.getFileName());
874299d8d0SLang Hames       break;
884299d8d0SLang Hames     }
894299d8d0SLang Hames   }
904299d8d0SLang Hames 
914299d8d0SLang Hames   return I;
924299d8d0SLang Hames }
934299d8d0SLang Hames 
944299d8d0SLang Hames static Expected<MaterializationUnit::Interface>
954299d8d0SLang Hames getELFObjectFileSymbolInfo(ExecutionSession &ES,
964299d8d0SLang Hames                            const object::ELFObjectFileBase &Obj) {
974299d8d0SLang Hames   MaterializationUnit::Interface I;
984299d8d0SLang Hames 
994299d8d0SLang Hames   for (auto &Sym : Obj.symbols()) {
1004299d8d0SLang Hames     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1014299d8d0SLang Hames     if (!SymFlagsOrErr)
1024299d8d0SLang Hames       // TODO: Test this error.
1034299d8d0SLang Hames       return SymFlagsOrErr.takeError();
1044299d8d0SLang Hames 
1054299d8d0SLang Hames     // Skip symbols not defined in this object file.
1064299d8d0SLang Hames     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
1074299d8d0SLang Hames       continue;
1084299d8d0SLang Hames 
1094299d8d0SLang Hames     // Skip symbols that are not global.
1104299d8d0SLang Hames     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
1114299d8d0SLang Hames       continue;
1124299d8d0SLang Hames 
1134299d8d0SLang Hames     // Skip symbols that have type SF_File.
1144299d8d0SLang Hames     if (auto SymType = Sym.getType()) {
1154299d8d0SLang Hames       if (*SymType == object::SymbolRef::ST_File)
1164299d8d0SLang Hames         continue;
1174299d8d0SLang Hames     } else
1184299d8d0SLang Hames       return SymType.takeError();
1194299d8d0SLang Hames 
1204299d8d0SLang Hames     auto Name = Sym.getName();
1214299d8d0SLang Hames     if (!Name)
1224299d8d0SLang Hames       return Name.takeError();
123*2ca81cd9SLang Hames 
1244299d8d0SLang Hames     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
1254299d8d0SLang Hames     if (!SymFlags)
1264299d8d0SLang Hames       return SymFlags.takeError();
1274299d8d0SLang Hames 
1284299d8d0SLang Hames     // ELF STB_GNU_UNIQUE should map to Weak for ORC.
1294299d8d0SLang Hames     if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
1304299d8d0SLang Hames       *SymFlags |= JITSymbolFlags::Weak;
1314299d8d0SLang Hames 
132*2ca81cd9SLang Hames     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
1334299d8d0SLang Hames   }
1344299d8d0SLang Hames 
1354299d8d0SLang Hames   SymbolStringPtr InitSymbol;
1364299d8d0SLang Hames   for (auto &Sec : Obj.sections()) {
1374299d8d0SLang Hames     if (auto SecName = Sec.getName()) {
1384299d8d0SLang Hames       if (ELFNixPlatform::isInitializerSection(*SecName)) {
1394299d8d0SLang Hames         addInitSymbol(I, ES, Obj.getFileName());
1404299d8d0SLang Hames         break;
1414299d8d0SLang Hames       }
1424299d8d0SLang Hames     }
1434299d8d0SLang Hames   }
1444299d8d0SLang Hames 
1454299d8d0SLang Hames   return I;
1464299d8d0SLang Hames }
1474299d8d0SLang Hames 
1484299d8d0SLang Hames Expected<MaterializationUnit::Interface>
1494299d8d0SLang Hames getGenericObjectFileSymbolInfo(ExecutionSession &ES,
1504299d8d0SLang Hames                                const object::ObjectFile &Obj) {
1514299d8d0SLang Hames   MaterializationUnit::Interface I;
1524299d8d0SLang Hames 
1534299d8d0SLang Hames   for (auto &Sym : Obj.symbols()) {
1544299d8d0SLang Hames     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1554299d8d0SLang Hames     if (!SymFlagsOrErr)
1564299d8d0SLang Hames       // TODO: Test this error.
1574299d8d0SLang Hames       return SymFlagsOrErr.takeError();
1584299d8d0SLang Hames 
1594299d8d0SLang Hames     // Skip symbols not defined in this object file.
1604299d8d0SLang Hames     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
1614299d8d0SLang Hames       continue;
1624299d8d0SLang Hames 
1634299d8d0SLang Hames     // Skip symbols that are not global.
1644299d8d0SLang Hames     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
1654299d8d0SLang Hames       continue;
1664299d8d0SLang Hames 
1674299d8d0SLang Hames     // Skip symbols that have type SF_File.
1684299d8d0SLang Hames     if (auto SymType = Sym.getType()) {
1694299d8d0SLang Hames       if (*SymType == object::SymbolRef::ST_File)
1704299d8d0SLang Hames         continue;
1714299d8d0SLang Hames     } else
1724299d8d0SLang Hames       return SymType.takeError();
1734299d8d0SLang Hames 
1744299d8d0SLang Hames     auto Name = Sym.getName();
1754299d8d0SLang Hames     if (!Name)
1764299d8d0SLang Hames       return Name.takeError();
177*2ca81cd9SLang Hames 
1784299d8d0SLang Hames     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
1794299d8d0SLang Hames     if (!SymFlags)
1804299d8d0SLang Hames       return SymFlags.takeError();
1814299d8d0SLang Hames 
182*2ca81cd9SLang Hames     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
1834299d8d0SLang Hames   }
1844299d8d0SLang Hames 
1854299d8d0SLang Hames   return I;
1864299d8d0SLang Hames }
1874299d8d0SLang Hames 
1884299d8d0SLang Hames Expected<MaterializationUnit::Interface>
1894299d8d0SLang Hames getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
1904299d8d0SLang Hames   auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
1914299d8d0SLang Hames 
1924299d8d0SLang Hames   if (!Obj)
1934299d8d0SLang Hames     return Obj.takeError();
1944299d8d0SLang Hames 
1954299d8d0SLang Hames   if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
1964299d8d0SLang Hames     return getMachOObjectFileSymbolInfo(ES, *MachOObj);
1974299d8d0SLang Hames   else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
1984299d8d0SLang Hames     return getELFObjectFileSymbolInfo(ES, *ELFObj);
1994299d8d0SLang Hames 
2004299d8d0SLang Hames   return getGenericObjectFileSymbolInfo(ES, **Obj);
2014299d8d0SLang Hames }
2024299d8d0SLang Hames 
2034299d8d0SLang Hames } // End namespace orc.
2044299d8d0SLang Hames } // End namespace llvm.
205