xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp (revision aadaaface2ec96ee30d92bf46faa41dd9e68b64d)
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"
109189a266SSunho Kim #include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
114299d8d0SLang Hames #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
124299d8d0SLang Hames #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
13db995d72SSunho Kim #include "llvm/Object/COFF.h"
144299d8d0SLang Hames #include "llvm/Object/ELFObjectFile.h"
154299d8d0SLang Hames #include "llvm/Object/MachO.h"
164299d8d0SLang Hames #include "llvm/Object/ObjectFile.h"
174299d8d0SLang Hames #include "llvm/Support/Debug.h"
1854ea422dSKazu Hirata #include <optional>
194299d8d0SLang Hames 
204299d8d0SLang Hames #define DEBUG_TYPE "orc"
214299d8d0SLang Hames 
224299d8d0SLang Hames namespace llvm {
234299d8d0SLang Hames namespace orc {
244299d8d0SLang Hames 
254299d8d0SLang Hames void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES,
264299d8d0SLang Hames                    StringRef ObjFileName) {
274299d8d0SLang Hames   assert(!I.InitSymbol && "I already has an init symbol");
284299d8d0SLang Hames   size_t Counter = 0;
294299d8d0SLang Hames 
304299d8d0SLang Hames   do {
314299d8d0SLang Hames     std::string InitSymString;
324299d8d0SLang Hames     raw_string_ostream(InitSymString)
334299d8d0SLang Hames         << "$." << ObjFileName << ".__inits." << Counter++;
344299d8d0SLang Hames     I.InitSymbol = ES.intern(InitSymString);
354299d8d0SLang Hames   } while (I.SymbolFlags.count(I.InitSymbol));
364299d8d0SLang Hames 
374299d8d0SLang Hames   I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
384299d8d0SLang Hames }
394299d8d0SLang Hames 
404299d8d0SLang Hames static Expected<MaterializationUnit::Interface>
414299d8d0SLang Hames getMachOObjectFileSymbolInfo(ExecutionSession &ES,
424299d8d0SLang Hames                              const object::MachOObjectFile &Obj) {
434299d8d0SLang Hames   MaterializationUnit::Interface I;
444299d8d0SLang Hames 
454299d8d0SLang Hames   for (auto &Sym : Obj.symbols()) {
464299d8d0SLang Hames     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
474299d8d0SLang Hames     if (!SymFlagsOrErr)
484299d8d0SLang Hames       // TODO: Test this error.
494299d8d0SLang Hames       return SymFlagsOrErr.takeError();
504299d8d0SLang Hames 
514299d8d0SLang Hames     // Skip symbols not defined in this object file.
524299d8d0SLang Hames     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
534299d8d0SLang Hames       continue;
544299d8d0SLang Hames 
554299d8d0SLang Hames     // Skip symbols that are not global.
564299d8d0SLang Hames     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
574299d8d0SLang Hames       continue;
584299d8d0SLang Hames 
594299d8d0SLang Hames     // Skip symbols that have type SF_File.
604299d8d0SLang Hames     if (auto SymType = Sym.getType()) {
614299d8d0SLang Hames       if (*SymType == object::SymbolRef::ST_File)
624299d8d0SLang Hames         continue;
634299d8d0SLang Hames     } else
644299d8d0SLang Hames       return SymType.takeError();
654299d8d0SLang Hames 
664299d8d0SLang Hames     auto Name = Sym.getName();
674299d8d0SLang Hames     if (!Name)
684299d8d0SLang Hames       return Name.takeError();
694299d8d0SLang Hames     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
704299d8d0SLang Hames     if (!SymFlags)
714299d8d0SLang Hames       return SymFlags.takeError();
724299d8d0SLang Hames 
734299d8d0SLang Hames     // Strip the 'exported' flag from MachO linker-private symbols.
744299d8d0SLang Hames     if (Name->startswith("l"))
754299d8d0SLang Hames       *SymFlags &= ~JITSymbolFlags::Exported;
764299d8d0SLang Hames 
772ca81cd9SLang Hames     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
784299d8d0SLang Hames   }
794299d8d0SLang Hames 
804299d8d0SLang Hames   for (auto &Sec : Obj.sections()) {
814299d8d0SLang Hames     auto SecType = Obj.getSectionType(Sec);
824299d8d0SLang Hames     if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {
834299d8d0SLang Hames       addInitSymbol(I, ES, Obj.getFileName());
844299d8d0SLang Hames       break;
854299d8d0SLang Hames     }
864299d8d0SLang Hames     auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
874299d8d0SLang Hames     auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
884299d8d0SLang Hames     if (MachOPlatform::isInitializerSection(SegName, SecName)) {
894299d8d0SLang Hames       addInitSymbol(I, ES, Obj.getFileName());
904299d8d0SLang Hames       break;
914299d8d0SLang Hames     }
924299d8d0SLang Hames   }
934299d8d0SLang Hames 
944299d8d0SLang Hames   return I;
954299d8d0SLang Hames }
964299d8d0SLang Hames 
974299d8d0SLang Hames static Expected<MaterializationUnit::Interface>
984299d8d0SLang Hames getELFObjectFileSymbolInfo(ExecutionSession &ES,
994299d8d0SLang Hames                            const object::ELFObjectFileBase &Obj) {
1004299d8d0SLang Hames   MaterializationUnit::Interface I;
1014299d8d0SLang Hames 
1024299d8d0SLang Hames   for (auto &Sym : Obj.symbols()) {
1034299d8d0SLang Hames     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1044299d8d0SLang Hames     if (!SymFlagsOrErr)
1054299d8d0SLang Hames       // TODO: Test this error.
1064299d8d0SLang Hames       return SymFlagsOrErr.takeError();
1074299d8d0SLang Hames 
1084299d8d0SLang Hames     // Skip symbols not defined in this object file.
1094299d8d0SLang Hames     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
1104299d8d0SLang Hames       continue;
1114299d8d0SLang Hames 
1124299d8d0SLang Hames     // Skip symbols that are not global.
1134299d8d0SLang Hames     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
1144299d8d0SLang Hames       continue;
1154299d8d0SLang Hames 
1164299d8d0SLang Hames     // Skip symbols that have type SF_File.
1174299d8d0SLang Hames     if (auto SymType = Sym.getType()) {
1184299d8d0SLang Hames       if (*SymType == object::SymbolRef::ST_File)
1194299d8d0SLang Hames         continue;
1204299d8d0SLang Hames     } else
1214299d8d0SLang Hames       return SymType.takeError();
1224299d8d0SLang Hames 
1234299d8d0SLang Hames     auto Name = Sym.getName();
1244299d8d0SLang Hames     if (!Name)
1254299d8d0SLang Hames       return Name.takeError();
1262ca81cd9SLang Hames 
1274299d8d0SLang Hames     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
1284299d8d0SLang Hames     if (!SymFlags)
1294299d8d0SLang Hames       return SymFlags.takeError();
1304299d8d0SLang Hames 
1314299d8d0SLang Hames     // ELF STB_GNU_UNIQUE should map to Weak for ORC.
1324299d8d0SLang Hames     if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
1334299d8d0SLang Hames       *SymFlags |= JITSymbolFlags::Weak;
1344299d8d0SLang Hames 
1352ca81cd9SLang Hames     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
1364299d8d0SLang Hames   }
1374299d8d0SLang Hames 
1384299d8d0SLang Hames   SymbolStringPtr InitSymbol;
1394299d8d0SLang Hames   for (auto &Sec : Obj.sections()) {
1404299d8d0SLang Hames     if (auto SecName = Sec.getName()) {
1414299d8d0SLang Hames       if (ELFNixPlatform::isInitializerSection(*SecName)) {
1424299d8d0SLang Hames         addInitSymbol(I, ES, Obj.getFileName());
1434299d8d0SLang Hames         break;
1444299d8d0SLang Hames       }
1454299d8d0SLang Hames     }
1464299d8d0SLang Hames   }
1474299d8d0SLang Hames 
1484299d8d0SLang Hames   return I;
1494299d8d0SLang Hames }
1504299d8d0SLang Hames 
151db995d72SSunho Kim static Expected<MaterializationUnit::Interface>
152db995d72SSunho Kim getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
153db995d72SSunho Kim                             const object::COFFObjectFile &Obj) {
154db995d72SSunho Kim   MaterializationUnit::Interface I;
15554ea422dSKazu Hirata   std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(
156c7ea2090SSunho Kim       Obj.getNumberOfSections() + 1);
157db995d72SSunho Kim   for (auto &Sym : Obj.symbols()) {
158db995d72SSunho Kim     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
159db995d72SSunho Kim     if (!SymFlagsOrErr)
160db995d72SSunho Kim       // TODO: Test this error.
161db995d72SSunho Kim       return SymFlagsOrErr.takeError();
162db995d72SSunho Kim 
163c7ea2090SSunho Kim     // Handle comdat symbols
164c7ea2090SSunho Kim     auto COFFSym = Obj.getCOFFSymbol(Sym);
165c7ea2090SSunho Kim     bool IsWeak = false;
166c7ea2090SSunho Kim     if (auto *Def = COFFSym.getSectionDefinition()) {
167c7ea2090SSunho Kim       auto Sec = Obj.getSection(COFFSym.getSectionNumber());
168c7ea2090SSunho Kim       if (!Sec)
169c7ea2090SSunho Kim         return Sec.takeError();
170c7ea2090SSunho Kim       if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&
171c7ea2090SSunho Kim           Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
172c7ea2090SSunho Kim         ComdatDefs[COFFSym.getSectionNumber()] = *Def;
173c7ea2090SSunho Kim         continue;
174c7ea2090SSunho Kim       }
175c7ea2090SSunho Kim     }
176c7ea2090SSunho Kim     if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&
177c7ea2090SSunho Kim         ComdatDefs[COFFSym.getSectionNumber()]) {
178c7ea2090SSunho Kim       auto Def = ComdatDefs[COFFSym.getSectionNumber()];
179c7ea2090SSunho Kim       if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
180c7ea2090SSunho Kim         IsWeak = true;
181c7ea2090SSunho Kim       }
182*aadaafacSKazu Hirata       ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt;
183c7ea2090SSunho Kim     } else {
184db995d72SSunho Kim       // Skip symbols not defined in this object file.
185db995d72SSunho Kim       if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
186db995d72SSunho Kim         continue;
187c7ea2090SSunho Kim     }
188db995d72SSunho Kim 
189db995d72SSunho Kim     // Skip symbols that are not global.
190db995d72SSunho Kim     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
191db995d72SSunho Kim       continue;
192db995d72SSunho Kim 
193db995d72SSunho Kim     // Skip symbols that have type SF_File.
194db995d72SSunho Kim     if (auto SymType = Sym.getType()) {
195db995d72SSunho Kim       if (*SymType == object::SymbolRef::ST_File)
196db995d72SSunho Kim         continue;
197db995d72SSunho Kim     } else
198db995d72SSunho Kim       return SymType.takeError();
199db995d72SSunho Kim 
200db995d72SSunho Kim     auto Name = Sym.getName();
201db995d72SSunho Kim     if (!Name)
202db995d72SSunho Kim       return Name.takeError();
203db995d72SSunho Kim 
204db995d72SSunho Kim     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
205db995d72SSunho Kim     if (!SymFlags)
206db995d72SSunho Kim       return SymFlags.takeError();
207db995d72SSunho Kim     *SymFlags |= JITSymbolFlags::Exported;
208db995d72SSunho Kim 
209db995d72SSunho Kim     // Weak external is always a function
210c7ea2090SSunho Kim     if (COFFSym.isWeakExternal())
211db995d72SSunho Kim       *SymFlags |= JITSymbolFlags::Callable;
212c7ea2090SSunho Kim 
213c7ea2090SSunho Kim     if (IsWeak)
214c7ea2090SSunho Kim       *SymFlags |= JITSymbolFlags::Weak;
215db995d72SSunho Kim 
216db995d72SSunho Kim     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
217db995d72SSunho Kim   }
218db995d72SSunho Kim 
2199189a266SSunho Kim   SymbolStringPtr InitSymbol;
2209189a266SSunho Kim   for (auto &Sec : Obj.sections()) {
2219189a266SSunho Kim     if (auto SecName = Sec.getName()) {
2229189a266SSunho Kim       if (COFFPlatform::isInitializerSection(*SecName)) {
2239189a266SSunho Kim         addInitSymbol(I, ES, Obj.getFileName());
2249189a266SSunho Kim         break;
2259189a266SSunho Kim       }
2269189a266SSunho Kim     } else
2279189a266SSunho Kim       return SecName.takeError();
2289189a266SSunho Kim   }
229db995d72SSunho Kim 
230db995d72SSunho Kim   return I;
231db995d72SSunho Kim }
232db995d72SSunho Kim 
2334299d8d0SLang Hames Expected<MaterializationUnit::Interface>
2344299d8d0SLang Hames getGenericObjectFileSymbolInfo(ExecutionSession &ES,
2354299d8d0SLang Hames                                const object::ObjectFile &Obj) {
2364299d8d0SLang Hames   MaterializationUnit::Interface I;
2374299d8d0SLang Hames 
2384299d8d0SLang Hames   for (auto &Sym : Obj.symbols()) {
2394299d8d0SLang Hames     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
2404299d8d0SLang Hames     if (!SymFlagsOrErr)
2414299d8d0SLang Hames       // TODO: Test this error.
2424299d8d0SLang Hames       return SymFlagsOrErr.takeError();
2434299d8d0SLang Hames 
2444299d8d0SLang Hames     // Skip symbols not defined in this object file.
2454299d8d0SLang Hames     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
2464299d8d0SLang Hames       continue;
2474299d8d0SLang Hames 
2484299d8d0SLang Hames     // Skip symbols that are not global.
2494299d8d0SLang Hames     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
2504299d8d0SLang Hames       continue;
2514299d8d0SLang Hames 
2524299d8d0SLang Hames     // Skip symbols that have type SF_File.
2534299d8d0SLang Hames     if (auto SymType = Sym.getType()) {
2544299d8d0SLang Hames       if (*SymType == object::SymbolRef::ST_File)
2554299d8d0SLang Hames         continue;
2564299d8d0SLang Hames     } else
2574299d8d0SLang Hames       return SymType.takeError();
2584299d8d0SLang Hames 
2594299d8d0SLang Hames     auto Name = Sym.getName();
2604299d8d0SLang Hames     if (!Name)
2614299d8d0SLang Hames       return Name.takeError();
2622ca81cd9SLang Hames 
2634299d8d0SLang Hames     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
2644299d8d0SLang Hames     if (!SymFlags)
2654299d8d0SLang Hames       return SymFlags.takeError();
2664299d8d0SLang Hames 
2672ca81cd9SLang Hames     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
2684299d8d0SLang Hames   }
2694299d8d0SLang Hames 
2704299d8d0SLang Hames   return I;
2714299d8d0SLang Hames }
2724299d8d0SLang Hames 
2734299d8d0SLang Hames Expected<MaterializationUnit::Interface>
2744299d8d0SLang Hames getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
2754299d8d0SLang Hames   auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
2764299d8d0SLang Hames 
2774299d8d0SLang Hames   if (!Obj)
2784299d8d0SLang Hames     return Obj.takeError();
2794299d8d0SLang Hames 
2804299d8d0SLang Hames   if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
2814299d8d0SLang Hames     return getMachOObjectFileSymbolInfo(ES, *MachOObj);
2824299d8d0SLang Hames   else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
2834299d8d0SLang Hames     return getELFObjectFileSymbolInfo(ES, *ELFObj);
284db995d72SSunho Kim   else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
285db995d72SSunho Kim     return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
2864299d8d0SLang Hames 
2874299d8d0SLang Hames   return getGenericObjectFileSymbolInfo(ES, **Obj);
2884299d8d0SLang Hames }
2894299d8d0SLang Hames 
2904299d8d0SLang Hames } // End namespace orc.
2914299d8d0SLang Hames } // End namespace llvm.
292