xref: /src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
177fc4c14SDimitry Andric //===------ ObjectFileInterface.cpp - MU interface utils for objects ------===//
277fc4c14SDimitry Andric //
377fc4c14SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
477fc4c14SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
577fc4c14SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
677fc4c14SDimitry Andric //
777fc4c14SDimitry Andric //===----------------------------------------------------------------------===//
877fc4c14SDimitry Andric 
977fc4c14SDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
10e3b55780SDimitry Andric #include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
1177fc4c14SDimitry Andric #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
1277fc4c14SDimitry Andric #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
137fa27ce4SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
141f917f69SDimitry Andric #include "llvm/Object/COFF.h"
1577fc4c14SDimitry Andric #include "llvm/Object/ELFObjectFile.h"
1677fc4c14SDimitry Andric #include "llvm/Object/MachO.h"
1777fc4c14SDimitry Andric #include "llvm/Object/ObjectFile.h"
1877fc4c14SDimitry Andric #include "llvm/Support/Debug.h"
19e3b55780SDimitry Andric #include <optional>
2077fc4c14SDimitry Andric 
2177fc4c14SDimitry Andric #define DEBUG_TYPE "orc"
2277fc4c14SDimitry Andric 
2377fc4c14SDimitry Andric namespace llvm {
2477fc4c14SDimitry Andric namespace orc {
2577fc4c14SDimitry Andric 
addInitSymbol(MaterializationUnit::Interface & I,ExecutionSession & ES,StringRef ObjFileName)2677fc4c14SDimitry Andric void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES,
2777fc4c14SDimitry Andric                    StringRef ObjFileName) {
2877fc4c14SDimitry Andric   assert(!I.InitSymbol && "I already has an init symbol");
2977fc4c14SDimitry Andric   size_t Counter = 0;
3077fc4c14SDimitry Andric 
3177fc4c14SDimitry Andric   do {
3277fc4c14SDimitry Andric     std::string InitSymString;
3377fc4c14SDimitry Andric     raw_string_ostream(InitSymString)
3477fc4c14SDimitry Andric         << "$." << ObjFileName << ".__inits." << Counter++;
3577fc4c14SDimitry Andric     I.InitSymbol = ES.intern(InitSymString);
3677fc4c14SDimitry Andric   } while (I.SymbolFlags.count(I.InitSymbol));
3777fc4c14SDimitry Andric 
3877fc4c14SDimitry Andric   I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
3977fc4c14SDimitry Andric }
4077fc4c14SDimitry Andric 
4177fc4c14SDimitry Andric static Expected<MaterializationUnit::Interface>
getMachOObjectFileSymbolInfo(ExecutionSession & ES,const object::MachOObjectFile & Obj)4277fc4c14SDimitry Andric getMachOObjectFileSymbolInfo(ExecutionSession &ES,
4377fc4c14SDimitry Andric                              const object::MachOObjectFile &Obj) {
4477fc4c14SDimitry Andric   MaterializationUnit::Interface I;
4577fc4c14SDimitry Andric 
4677fc4c14SDimitry Andric   for (auto &Sym : Obj.symbols()) {
4777fc4c14SDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
4877fc4c14SDimitry Andric     if (!SymFlagsOrErr)
4977fc4c14SDimitry Andric       // TODO: Test this error.
5077fc4c14SDimitry Andric       return SymFlagsOrErr.takeError();
5177fc4c14SDimitry Andric 
5277fc4c14SDimitry Andric     // Skip symbols not defined in this object file.
5377fc4c14SDimitry Andric     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
5477fc4c14SDimitry Andric       continue;
5577fc4c14SDimitry Andric 
5677fc4c14SDimitry Andric     // Skip symbols that are not global.
5777fc4c14SDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
5877fc4c14SDimitry Andric       continue;
5977fc4c14SDimitry Andric 
6077fc4c14SDimitry Andric     // Skip symbols that have type SF_File.
6177fc4c14SDimitry Andric     if (auto SymType = Sym.getType()) {
6277fc4c14SDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
6377fc4c14SDimitry Andric         continue;
6477fc4c14SDimitry Andric     } else
6577fc4c14SDimitry Andric       return SymType.takeError();
6677fc4c14SDimitry Andric 
6777fc4c14SDimitry Andric     auto Name = Sym.getName();
6877fc4c14SDimitry Andric     if (!Name)
6977fc4c14SDimitry Andric       return Name.takeError();
7077fc4c14SDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
7177fc4c14SDimitry Andric     if (!SymFlags)
7277fc4c14SDimitry Andric       return SymFlags.takeError();
7377fc4c14SDimitry Andric 
7477fc4c14SDimitry Andric     // Strip the 'exported' flag from MachO linker-private symbols.
75312c0ed1SDimitry Andric     if (Name->starts_with("l"))
7677fc4c14SDimitry Andric       *SymFlags &= ~JITSymbolFlags::Exported;
7777fc4c14SDimitry Andric 
78145449b1SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
7977fc4c14SDimitry Andric   }
8077fc4c14SDimitry Andric 
8177fc4c14SDimitry Andric   for (auto &Sec : Obj.sections()) {
8277fc4c14SDimitry Andric     auto SecType = Obj.getSectionType(Sec);
8377fc4c14SDimitry Andric     if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {
8477fc4c14SDimitry Andric       addInitSymbol(I, ES, Obj.getFileName());
8577fc4c14SDimitry Andric       break;
8677fc4c14SDimitry Andric     }
8777fc4c14SDimitry Andric     auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
8877fc4c14SDimitry Andric     auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
897fa27ce4SDimitry Andric     if (isMachOInitializerSection(SegName, SecName)) {
9077fc4c14SDimitry Andric       addInitSymbol(I, ES, Obj.getFileName());
9177fc4c14SDimitry Andric       break;
9277fc4c14SDimitry Andric     }
9377fc4c14SDimitry Andric   }
9477fc4c14SDimitry Andric 
9577fc4c14SDimitry Andric   return I;
9677fc4c14SDimitry Andric }
9777fc4c14SDimitry Andric 
9877fc4c14SDimitry Andric static Expected<MaterializationUnit::Interface>
getELFObjectFileSymbolInfo(ExecutionSession & ES,const object::ELFObjectFileBase & Obj)9977fc4c14SDimitry Andric getELFObjectFileSymbolInfo(ExecutionSession &ES,
10077fc4c14SDimitry Andric                            const object::ELFObjectFileBase &Obj) {
10177fc4c14SDimitry Andric   MaterializationUnit::Interface I;
10277fc4c14SDimitry Andric 
10377fc4c14SDimitry Andric   for (auto &Sym : Obj.symbols()) {
10477fc4c14SDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
10577fc4c14SDimitry Andric     if (!SymFlagsOrErr)
10677fc4c14SDimitry Andric       // TODO: Test this error.
10777fc4c14SDimitry Andric       return SymFlagsOrErr.takeError();
10877fc4c14SDimitry Andric 
10977fc4c14SDimitry Andric     // Skip symbols not defined in this object file.
11077fc4c14SDimitry Andric     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
11177fc4c14SDimitry Andric       continue;
11277fc4c14SDimitry Andric 
11377fc4c14SDimitry Andric     // Skip symbols that are not global.
11477fc4c14SDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
11577fc4c14SDimitry Andric       continue;
11677fc4c14SDimitry Andric 
11777fc4c14SDimitry Andric     // Skip symbols that have type SF_File.
11877fc4c14SDimitry Andric     if (auto SymType = Sym.getType()) {
11977fc4c14SDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
12077fc4c14SDimitry Andric         continue;
12177fc4c14SDimitry Andric     } else
12277fc4c14SDimitry Andric       return SymType.takeError();
12377fc4c14SDimitry Andric 
12477fc4c14SDimitry Andric     auto Name = Sym.getName();
12577fc4c14SDimitry Andric     if (!Name)
12677fc4c14SDimitry Andric       return Name.takeError();
127145449b1SDimitry Andric 
12877fc4c14SDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
12977fc4c14SDimitry Andric     if (!SymFlags)
13077fc4c14SDimitry Andric       return SymFlags.takeError();
13177fc4c14SDimitry Andric 
13277fc4c14SDimitry Andric     // ELF STB_GNU_UNIQUE should map to Weak for ORC.
13377fc4c14SDimitry Andric     if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
13477fc4c14SDimitry Andric       *SymFlags |= JITSymbolFlags::Weak;
13577fc4c14SDimitry Andric 
136145449b1SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
13777fc4c14SDimitry Andric   }
13877fc4c14SDimitry Andric 
13977fc4c14SDimitry Andric   SymbolStringPtr InitSymbol;
14077fc4c14SDimitry Andric   for (auto &Sec : Obj.sections()) {
14177fc4c14SDimitry Andric     if (auto SecName = Sec.getName()) {
1427fa27ce4SDimitry Andric       if (isELFInitializerSection(*SecName)) {
14377fc4c14SDimitry Andric         addInitSymbol(I, ES, Obj.getFileName());
14477fc4c14SDimitry Andric         break;
14577fc4c14SDimitry Andric       }
14677fc4c14SDimitry Andric     }
14777fc4c14SDimitry Andric   }
14877fc4c14SDimitry Andric 
14977fc4c14SDimitry Andric   return I;
15077fc4c14SDimitry Andric }
15177fc4c14SDimitry Andric 
1521f917f69SDimitry Andric static Expected<MaterializationUnit::Interface>
getCOFFObjectFileSymbolInfo(ExecutionSession & ES,const object::COFFObjectFile & Obj)1531f917f69SDimitry Andric getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
1541f917f69SDimitry Andric                             const object::COFFObjectFile &Obj) {
1551f917f69SDimitry Andric   MaterializationUnit::Interface I;
156e3b55780SDimitry Andric   std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(
15708e8dd7bSDimitry Andric       Obj.getNumberOfSections() + 1);
1581f917f69SDimitry Andric   for (auto &Sym : Obj.symbols()) {
1591f917f69SDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1601f917f69SDimitry Andric     if (!SymFlagsOrErr)
1611f917f69SDimitry Andric       // TODO: Test this error.
1621f917f69SDimitry Andric       return SymFlagsOrErr.takeError();
1631f917f69SDimitry Andric 
16408e8dd7bSDimitry Andric     // Handle comdat symbols
16508e8dd7bSDimitry Andric     auto COFFSym = Obj.getCOFFSymbol(Sym);
16608e8dd7bSDimitry Andric     bool IsWeak = false;
16708e8dd7bSDimitry Andric     if (auto *Def = COFFSym.getSectionDefinition()) {
16808e8dd7bSDimitry Andric       auto Sec = Obj.getSection(COFFSym.getSectionNumber());
16908e8dd7bSDimitry Andric       if (!Sec)
17008e8dd7bSDimitry Andric         return Sec.takeError();
17108e8dd7bSDimitry Andric       if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&
17208e8dd7bSDimitry Andric           Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
17308e8dd7bSDimitry Andric         ComdatDefs[COFFSym.getSectionNumber()] = *Def;
17408e8dd7bSDimitry Andric         continue;
17508e8dd7bSDimitry Andric       }
17608e8dd7bSDimitry Andric     }
17708e8dd7bSDimitry Andric     if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&
17808e8dd7bSDimitry Andric         ComdatDefs[COFFSym.getSectionNumber()]) {
17908e8dd7bSDimitry Andric       auto Def = ComdatDefs[COFFSym.getSectionNumber()];
18008e8dd7bSDimitry Andric       if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
18108e8dd7bSDimitry Andric         IsWeak = true;
18208e8dd7bSDimitry Andric       }
183e3b55780SDimitry Andric       ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt;
18408e8dd7bSDimitry Andric     } else {
1851f917f69SDimitry Andric       // Skip symbols not defined in this object file.
1861f917f69SDimitry Andric       if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
1871f917f69SDimitry Andric         continue;
18808e8dd7bSDimitry Andric     }
1891f917f69SDimitry Andric 
1901f917f69SDimitry Andric     // Skip symbols that are not global.
1911f917f69SDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
1921f917f69SDimitry Andric       continue;
1931f917f69SDimitry Andric 
1941f917f69SDimitry Andric     // Skip symbols that have type SF_File.
1951f917f69SDimitry Andric     if (auto SymType = Sym.getType()) {
1961f917f69SDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
1971f917f69SDimitry Andric         continue;
1981f917f69SDimitry Andric     } else
1991f917f69SDimitry Andric       return SymType.takeError();
2001f917f69SDimitry Andric 
2011f917f69SDimitry Andric     auto Name = Sym.getName();
2021f917f69SDimitry Andric     if (!Name)
2031f917f69SDimitry Andric       return Name.takeError();
2041f917f69SDimitry Andric 
2051f917f69SDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
2061f917f69SDimitry Andric     if (!SymFlags)
2071f917f69SDimitry Andric       return SymFlags.takeError();
2081f917f69SDimitry Andric     *SymFlags |= JITSymbolFlags::Exported;
2091f917f69SDimitry Andric 
2101f917f69SDimitry Andric     // Weak external is always a function
21108e8dd7bSDimitry Andric     if (COFFSym.isWeakExternal())
2121f917f69SDimitry Andric       *SymFlags |= JITSymbolFlags::Callable;
21308e8dd7bSDimitry Andric 
21408e8dd7bSDimitry Andric     if (IsWeak)
21508e8dd7bSDimitry Andric       *SymFlags |= JITSymbolFlags::Weak;
2161f917f69SDimitry Andric 
2171f917f69SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
2181f917f69SDimitry Andric   }
2191f917f69SDimitry Andric 
220e3b55780SDimitry Andric   SymbolStringPtr InitSymbol;
221e3b55780SDimitry Andric   for (auto &Sec : Obj.sections()) {
222e3b55780SDimitry Andric     if (auto SecName = Sec.getName()) {
2237fa27ce4SDimitry Andric       if (isCOFFInitializerSection(*SecName)) {
224e3b55780SDimitry Andric         addInitSymbol(I, ES, Obj.getFileName());
225e3b55780SDimitry Andric         break;
226e3b55780SDimitry Andric       }
227e3b55780SDimitry Andric     } else
228e3b55780SDimitry Andric       return SecName.takeError();
229e3b55780SDimitry Andric   }
2301f917f69SDimitry Andric 
2311f917f69SDimitry Andric   return I;
2321f917f69SDimitry Andric }
2331f917f69SDimitry Andric 
23477fc4c14SDimitry Andric Expected<MaterializationUnit::Interface>
getGenericObjectFileSymbolInfo(ExecutionSession & ES,const object::ObjectFile & Obj)23577fc4c14SDimitry Andric getGenericObjectFileSymbolInfo(ExecutionSession &ES,
23677fc4c14SDimitry Andric                                const object::ObjectFile &Obj) {
23777fc4c14SDimitry Andric   MaterializationUnit::Interface I;
23877fc4c14SDimitry Andric 
23977fc4c14SDimitry Andric   for (auto &Sym : Obj.symbols()) {
24077fc4c14SDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
24177fc4c14SDimitry Andric     if (!SymFlagsOrErr)
24277fc4c14SDimitry Andric       // TODO: Test this error.
24377fc4c14SDimitry Andric       return SymFlagsOrErr.takeError();
24477fc4c14SDimitry Andric 
24577fc4c14SDimitry Andric     // Skip symbols not defined in this object file.
24677fc4c14SDimitry Andric     if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
24777fc4c14SDimitry Andric       continue;
24877fc4c14SDimitry Andric 
24977fc4c14SDimitry Andric     // Skip symbols that are not global.
25077fc4c14SDimitry Andric     if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
25177fc4c14SDimitry Andric       continue;
25277fc4c14SDimitry Andric 
25377fc4c14SDimitry Andric     // Skip symbols that have type SF_File.
25477fc4c14SDimitry Andric     if (auto SymType = Sym.getType()) {
25577fc4c14SDimitry Andric       if (*SymType == object::SymbolRef::ST_File)
25677fc4c14SDimitry Andric         continue;
25777fc4c14SDimitry Andric     } else
25877fc4c14SDimitry Andric       return SymType.takeError();
25977fc4c14SDimitry Andric 
26077fc4c14SDimitry Andric     auto Name = Sym.getName();
26177fc4c14SDimitry Andric     if (!Name)
26277fc4c14SDimitry Andric       return Name.takeError();
263145449b1SDimitry Andric 
26477fc4c14SDimitry Andric     auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
26577fc4c14SDimitry Andric     if (!SymFlags)
26677fc4c14SDimitry Andric       return SymFlags.takeError();
26777fc4c14SDimitry Andric 
268145449b1SDimitry Andric     I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
26977fc4c14SDimitry Andric   }
27077fc4c14SDimitry Andric 
27177fc4c14SDimitry Andric   return I;
27277fc4c14SDimitry Andric }
27377fc4c14SDimitry Andric 
27477fc4c14SDimitry Andric Expected<MaterializationUnit::Interface>
getObjectFileInterface(ExecutionSession & ES,MemoryBufferRef ObjBuffer)27577fc4c14SDimitry Andric getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
27677fc4c14SDimitry Andric   auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
27777fc4c14SDimitry Andric 
27877fc4c14SDimitry Andric   if (!Obj)
27977fc4c14SDimitry Andric     return Obj.takeError();
28077fc4c14SDimitry Andric 
28177fc4c14SDimitry Andric   if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
28277fc4c14SDimitry Andric     return getMachOObjectFileSymbolInfo(ES, *MachOObj);
28377fc4c14SDimitry Andric   else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
28477fc4c14SDimitry Andric     return getELFObjectFileSymbolInfo(ES, *ELFObj);
2851f917f69SDimitry Andric   else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
2861f917f69SDimitry Andric     return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
28777fc4c14SDimitry Andric 
28877fc4c14SDimitry Andric   return getGenericObjectFileSymbolInfo(ES, **Obj);
28977fc4c14SDimitry Andric }
29077fc4c14SDimitry Andric 
29177fc4c14SDimitry Andric } // End namespace orc.
29277fc4c14SDimitry Andric } // End namespace llvm.
293