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"
10bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
110eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
120eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
1306c3fb27SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
14753f127fSDimitry Andric #include "llvm/Object/COFF.h"
150eae32dcSDimitry Andric #include "llvm/Object/ELFObjectFile.h"
160eae32dcSDimitry Andric #include "llvm/Object/MachO.h"
170eae32dcSDimitry Andric #include "llvm/Object/ObjectFile.h"
180eae32dcSDimitry Andric #include "llvm/Support/Debug.h"
19bdd1243dSDimitry Andric #include <optional>
200eae32dcSDimitry Andric
210eae32dcSDimitry Andric #define DEBUG_TYPE "orc"
220eae32dcSDimitry Andric
230eae32dcSDimitry Andric namespace llvm {
240eae32dcSDimitry Andric namespace orc {
250eae32dcSDimitry Andric
addInitSymbol(MaterializationUnit::Interface & I,ExecutionSession & ES,StringRef ObjFileName)260eae32dcSDimitry Andric void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES,
270eae32dcSDimitry Andric StringRef ObjFileName) {
280eae32dcSDimitry Andric assert(!I.InitSymbol && "I already has an init symbol");
290eae32dcSDimitry Andric size_t Counter = 0;
300eae32dcSDimitry Andric
310eae32dcSDimitry Andric do {
320eae32dcSDimitry Andric std::string InitSymString;
330eae32dcSDimitry Andric raw_string_ostream(InitSymString)
340eae32dcSDimitry Andric << "$." << ObjFileName << ".__inits." << Counter++;
350eae32dcSDimitry Andric I.InitSymbol = ES.intern(InitSymString);
360eae32dcSDimitry Andric } while (I.SymbolFlags.count(I.InitSymbol));
370eae32dcSDimitry Andric
380eae32dcSDimitry Andric I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
390eae32dcSDimitry Andric }
400eae32dcSDimitry Andric
410eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface>
getMachOObjectFileSymbolInfo(ExecutionSession & ES,const object::MachOObjectFile & Obj)420eae32dcSDimitry Andric getMachOObjectFileSymbolInfo(ExecutionSession &ES,
430eae32dcSDimitry Andric const object::MachOObjectFile &Obj) {
440eae32dcSDimitry Andric MaterializationUnit::Interface I;
450eae32dcSDimitry Andric
460eae32dcSDimitry Andric for (auto &Sym : Obj.symbols()) {
470eae32dcSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
480eae32dcSDimitry Andric if (!SymFlagsOrErr)
490eae32dcSDimitry Andric // TODO: Test this error.
500eae32dcSDimitry Andric return SymFlagsOrErr.takeError();
510eae32dcSDimitry Andric
520eae32dcSDimitry Andric // Skip symbols not defined in this object file.
530eae32dcSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
540eae32dcSDimitry Andric continue;
550eae32dcSDimitry Andric
560eae32dcSDimitry Andric // Skip symbols that are not global.
570eae32dcSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
580eae32dcSDimitry Andric continue;
590eae32dcSDimitry Andric
600eae32dcSDimitry Andric // Skip symbols that have type SF_File.
610eae32dcSDimitry Andric if (auto SymType = Sym.getType()) {
620eae32dcSDimitry Andric if (*SymType == object::SymbolRef::ST_File)
630eae32dcSDimitry Andric continue;
640eae32dcSDimitry Andric } else
650eae32dcSDimitry Andric return SymType.takeError();
660eae32dcSDimitry Andric
670eae32dcSDimitry Andric auto Name = Sym.getName();
680eae32dcSDimitry Andric if (!Name)
690eae32dcSDimitry Andric return Name.takeError();
700eae32dcSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
710eae32dcSDimitry Andric if (!SymFlags)
720eae32dcSDimitry Andric return SymFlags.takeError();
730eae32dcSDimitry Andric
740eae32dcSDimitry Andric // Strip the 'exported' flag from MachO linker-private symbols.
75*5f757f3fSDimitry Andric if (Name->starts_with("l"))
760eae32dcSDimitry Andric *SymFlags &= ~JITSymbolFlags::Exported;
770eae32dcSDimitry Andric
7881ad6265SDimitry Andric I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
790eae32dcSDimitry Andric }
800eae32dcSDimitry Andric
810eae32dcSDimitry Andric for (auto &Sec : Obj.sections()) {
820eae32dcSDimitry Andric auto SecType = Obj.getSectionType(Sec);
830eae32dcSDimitry Andric if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {
840eae32dcSDimitry Andric addInitSymbol(I, ES, Obj.getFileName());
850eae32dcSDimitry Andric break;
860eae32dcSDimitry Andric }
870eae32dcSDimitry Andric auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
880eae32dcSDimitry Andric auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
8906c3fb27SDimitry Andric if (isMachOInitializerSection(SegName, SecName)) {
900eae32dcSDimitry Andric addInitSymbol(I, ES, Obj.getFileName());
910eae32dcSDimitry Andric break;
920eae32dcSDimitry Andric }
930eae32dcSDimitry Andric }
940eae32dcSDimitry Andric
950eae32dcSDimitry Andric return I;
960eae32dcSDimitry Andric }
970eae32dcSDimitry Andric
980eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface>
getELFObjectFileSymbolInfo(ExecutionSession & ES,const object::ELFObjectFileBase & Obj)990eae32dcSDimitry Andric getELFObjectFileSymbolInfo(ExecutionSession &ES,
1000eae32dcSDimitry Andric const object::ELFObjectFileBase &Obj) {
1010eae32dcSDimitry Andric MaterializationUnit::Interface I;
1020eae32dcSDimitry Andric
1030eae32dcSDimitry Andric for (auto &Sym : Obj.symbols()) {
1040eae32dcSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1050eae32dcSDimitry Andric if (!SymFlagsOrErr)
1060eae32dcSDimitry Andric // TODO: Test this error.
1070eae32dcSDimitry Andric return SymFlagsOrErr.takeError();
1080eae32dcSDimitry Andric
1090eae32dcSDimitry Andric // Skip symbols not defined in this object file.
1100eae32dcSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
1110eae32dcSDimitry Andric continue;
1120eae32dcSDimitry Andric
1130eae32dcSDimitry Andric // Skip symbols that are not global.
1140eae32dcSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
1150eae32dcSDimitry Andric continue;
1160eae32dcSDimitry Andric
1170eae32dcSDimitry Andric // Skip symbols that have type SF_File.
1180eae32dcSDimitry Andric if (auto SymType = Sym.getType()) {
1190eae32dcSDimitry Andric if (*SymType == object::SymbolRef::ST_File)
1200eae32dcSDimitry Andric continue;
1210eae32dcSDimitry Andric } else
1220eae32dcSDimitry Andric return SymType.takeError();
1230eae32dcSDimitry Andric
1240eae32dcSDimitry Andric auto Name = Sym.getName();
1250eae32dcSDimitry Andric if (!Name)
1260eae32dcSDimitry Andric return Name.takeError();
12781ad6265SDimitry Andric
1280eae32dcSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
1290eae32dcSDimitry Andric if (!SymFlags)
1300eae32dcSDimitry Andric return SymFlags.takeError();
1310eae32dcSDimitry Andric
1320eae32dcSDimitry Andric // ELF STB_GNU_UNIQUE should map to Weak for ORC.
1330eae32dcSDimitry Andric if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)
1340eae32dcSDimitry Andric *SymFlags |= JITSymbolFlags::Weak;
1350eae32dcSDimitry Andric
13681ad6265SDimitry Andric I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
1370eae32dcSDimitry Andric }
1380eae32dcSDimitry Andric
1390eae32dcSDimitry Andric SymbolStringPtr InitSymbol;
1400eae32dcSDimitry Andric for (auto &Sec : Obj.sections()) {
1410eae32dcSDimitry Andric if (auto SecName = Sec.getName()) {
14206c3fb27SDimitry Andric if (isELFInitializerSection(*SecName)) {
1430eae32dcSDimitry Andric addInitSymbol(I, ES, Obj.getFileName());
1440eae32dcSDimitry Andric break;
1450eae32dcSDimitry Andric }
1460eae32dcSDimitry Andric }
1470eae32dcSDimitry Andric }
1480eae32dcSDimitry Andric
1490eae32dcSDimitry Andric return I;
1500eae32dcSDimitry Andric }
1510eae32dcSDimitry Andric
152753f127fSDimitry Andric static Expected<MaterializationUnit::Interface>
getCOFFObjectFileSymbolInfo(ExecutionSession & ES,const object::COFFObjectFile & Obj)153753f127fSDimitry Andric getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
154753f127fSDimitry Andric const object::COFFObjectFile &Obj) {
155753f127fSDimitry Andric MaterializationUnit::Interface I;
156bdd1243dSDimitry Andric std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(
157972a253aSDimitry Andric Obj.getNumberOfSections() + 1);
158753f127fSDimitry Andric for (auto &Sym : Obj.symbols()) {
159753f127fSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
160753f127fSDimitry Andric if (!SymFlagsOrErr)
161753f127fSDimitry Andric // TODO: Test this error.
162753f127fSDimitry Andric return SymFlagsOrErr.takeError();
163753f127fSDimitry Andric
164972a253aSDimitry Andric // Handle comdat symbols
165972a253aSDimitry Andric auto COFFSym = Obj.getCOFFSymbol(Sym);
166972a253aSDimitry Andric bool IsWeak = false;
167972a253aSDimitry Andric if (auto *Def = COFFSym.getSectionDefinition()) {
168972a253aSDimitry Andric auto Sec = Obj.getSection(COFFSym.getSectionNumber());
169972a253aSDimitry Andric if (!Sec)
170972a253aSDimitry Andric return Sec.takeError();
171972a253aSDimitry Andric if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&
172972a253aSDimitry Andric Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
173972a253aSDimitry Andric ComdatDefs[COFFSym.getSectionNumber()] = *Def;
174972a253aSDimitry Andric continue;
175972a253aSDimitry Andric }
176972a253aSDimitry Andric }
177972a253aSDimitry Andric if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&
178972a253aSDimitry Andric ComdatDefs[COFFSym.getSectionNumber()]) {
179972a253aSDimitry Andric auto Def = ComdatDefs[COFFSym.getSectionNumber()];
180972a253aSDimitry Andric if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
181972a253aSDimitry Andric IsWeak = true;
182972a253aSDimitry Andric }
183bdd1243dSDimitry Andric ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt;
184972a253aSDimitry Andric } else {
185753f127fSDimitry Andric // Skip symbols not defined in this object file.
186753f127fSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
187753f127fSDimitry Andric continue;
188972a253aSDimitry Andric }
189753f127fSDimitry Andric
190753f127fSDimitry Andric // Skip symbols that are not global.
191753f127fSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
192753f127fSDimitry Andric continue;
193753f127fSDimitry Andric
194753f127fSDimitry Andric // Skip symbols that have type SF_File.
195753f127fSDimitry Andric if (auto SymType = Sym.getType()) {
196753f127fSDimitry Andric if (*SymType == object::SymbolRef::ST_File)
197753f127fSDimitry Andric continue;
198753f127fSDimitry Andric } else
199753f127fSDimitry Andric return SymType.takeError();
200753f127fSDimitry Andric
201753f127fSDimitry Andric auto Name = Sym.getName();
202753f127fSDimitry Andric if (!Name)
203753f127fSDimitry Andric return Name.takeError();
204753f127fSDimitry Andric
205753f127fSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
206753f127fSDimitry Andric if (!SymFlags)
207753f127fSDimitry Andric return SymFlags.takeError();
208753f127fSDimitry Andric *SymFlags |= JITSymbolFlags::Exported;
209753f127fSDimitry Andric
210753f127fSDimitry Andric // Weak external is always a function
211972a253aSDimitry Andric if (COFFSym.isWeakExternal())
212753f127fSDimitry Andric *SymFlags |= JITSymbolFlags::Callable;
213972a253aSDimitry Andric
214972a253aSDimitry Andric if (IsWeak)
215972a253aSDimitry Andric *SymFlags |= JITSymbolFlags::Weak;
216753f127fSDimitry Andric
217753f127fSDimitry Andric I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
218753f127fSDimitry Andric }
219753f127fSDimitry Andric
220bdd1243dSDimitry Andric SymbolStringPtr InitSymbol;
221bdd1243dSDimitry Andric for (auto &Sec : Obj.sections()) {
222bdd1243dSDimitry Andric if (auto SecName = Sec.getName()) {
22306c3fb27SDimitry Andric if (isCOFFInitializerSection(*SecName)) {
224bdd1243dSDimitry Andric addInitSymbol(I, ES, Obj.getFileName());
225bdd1243dSDimitry Andric break;
226bdd1243dSDimitry Andric }
227bdd1243dSDimitry Andric } else
228bdd1243dSDimitry Andric return SecName.takeError();
229bdd1243dSDimitry Andric }
230753f127fSDimitry Andric
231753f127fSDimitry Andric return I;
232753f127fSDimitry Andric }
233753f127fSDimitry Andric
2340eae32dcSDimitry Andric Expected<MaterializationUnit::Interface>
getGenericObjectFileSymbolInfo(ExecutionSession & ES,const object::ObjectFile & Obj)2350eae32dcSDimitry Andric getGenericObjectFileSymbolInfo(ExecutionSession &ES,
2360eae32dcSDimitry Andric const object::ObjectFile &Obj) {
2370eae32dcSDimitry Andric MaterializationUnit::Interface I;
2380eae32dcSDimitry Andric
2390eae32dcSDimitry Andric for (auto &Sym : Obj.symbols()) {
2400eae32dcSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
2410eae32dcSDimitry Andric if (!SymFlagsOrErr)
2420eae32dcSDimitry Andric // TODO: Test this error.
2430eae32dcSDimitry Andric return SymFlagsOrErr.takeError();
2440eae32dcSDimitry Andric
2450eae32dcSDimitry Andric // Skip symbols not defined in this object file.
2460eae32dcSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
2470eae32dcSDimitry Andric continue;
2480eae32dcSDimitry Andric
2490eae32dcSDimitry Andric // Skip symbols that are not global.
2500eae32dcSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
2510eae32dcSDimitry Andric continue;
2520eae32dcSDimitry Andric
2530eae32dcSDimitry Andric // Skip symbols that have type SF_File.
2540eae32dcSDimitry Andric if (auto SymType = Sym.getType()) {
2550eae32dcSDimitry Andric if (*SymType == object::SymbolRef::ST_File)
2560eae32dcSDimitry Andric continue;
2570eae32dcSDimitry Andric } else
2580eae32dcSDimitry Andric return SymType.takeError();
2590eae32dcSDimitry Andric
2600eae32dcSDimitry Andric auto Name = Sym.getName();
2610eae32dcSDimitry Andric if (!Name)
2620eae32dcSDimitry Andric return Name.takeError();
26381ad6265SDimitry Andric
2640eae32dcSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
2650eae32dcSDimitry Andric if (!SymFlags)
2660eae32dcSDimitry Andric return SymFlags.takeError();
2670eae32dcSDimitry Andric
26881ad6265SDimitry Andric I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
2690eae32dcSDimitry Andric }
2700eae32dcSDimitry Andric
2710eae32dcSDimitry Andric return I;
2720eae32dcSDimitry Andric }
2730eae32dcSDimitry Andric
2740eae32dcSDimitry Andric Expected<MaterializationUnit::Interface>
getObjectFileInterface(ExecutionSession & ES,MemoryBufferRef ObjBuffer)2750eae32dcSDimitry Andric getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
2760eae32dcSDimitry Andric auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
2770eae32dcSDimitry Andric
2780eae32dcSDimitry Andric if (!Obj)
2790eae32dcSDimitry Andric return Obj.takeError();
2800eae32dcSDimitry Andric
2810eae32dcSDimitry Andric if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))
2820eae32dcSDimitry Andric return getMachOObjectFileSymbolInfo(ES, *MachOObj);
2830eae32dcSDimitry Andric else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
2840eae32dcSDimitry Andric return getELFObjectFileSymbolInfo(ES, *ELFObj);
285753f127fSDimitry Andric else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
286753f127fSDimitry Andric return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
2870eae32dcSDimitry Andric
2880eae32dcSDimitry Andric return getGenericObjectFileSymbolInfo(ES, **Obj);
2890eae32dcSDimitry Andric }
2900eae32dcSDimitry Andric
2910eae32dcSDimitry Andric } // End namespace orc.
2920eae32dcSDimitry Andric } // End namespace llvm.
293