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