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