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" 12*db995d72SSunho 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 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> 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> 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 149*db995d72SSunho Kim static Expected<MaterializationUnit::Interface> 150*db995d72SSunho Kim getCOFFObjectFileSymbolInfo(ExecutionSession &ES, 151*db995d72SSunho Kim const object::COFFObjectFile &Obj) { 152*db995d72SSunho Kim MaterializationUnit::Interface I; 153*db995d72SSunho Kim 154*db995d72SSunho Kim for (auto &Sym : Obj.symbols()) { 155*db995d72SSunho Kim Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 156*db995d72SSunho Kim if (!SymFlagsOrErr) 157*db995d72SSunho Kim // TODO: Test this error. 158*db995d72SSunho Kim return SymFlagsOrErr.takeError(); 159*db995d72SSunho Kim 160*db995d72SSunho Kim // Skip symbols not defined in this object file. 161*db995d72SSunho Kim if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 162*db995d72SSunho Kim continue; 163*db995d72SSunho Kim 164*db995d72SSunho Kim // Skip symbols that are not global. 165*db995d72SSunho Kim if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 166*db995d72SSunho Kim continue; 167*db995d72SSunho Kim 168*db995d72SSunho Kim // Skip symbols that have type SF_File. 169*db995d72SSunho Kim if (auto SymType = Sym.getType()) { 170*db995d72SSunho Kim if (*SymType == object::SymbolRef::ST_File) 171*db995d72SSunho Kim continue; 172*db995d72SSunho Kim } else 173*db995d72SSunho Kim return SymType.takeError(); 174*db995d72SSunho Kim 175*db995d72SSunho Kim auto Name = Sym.getName(); 176*db995d72SSunho Kim if (!Name) 177*db995d72SSunho Kim return Name.takeError(); 178*db995d72SSunho Kim 179*db995d72SSunho Kim auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 180*db995d72SSunho Kim if (!SymFlags) 181*db995d72SSunho Kim return SymFlags.takeError(); 182*db995d72SSunho Kim *SymFlags |= JITSymbolFlags::Exported; 183*db995d72SSunho Kim auto COFFSym = Obj.getCOFFSymbol(Sym); 184*db995d72SSunho Kim 185*db995d72SSunho Kim // Weak external is always a function 186*db995d72SSunho Kim if (COFFSym.isWeakExternal()) { 187*db995d72SSunho Kim *SymFlags |= JITSymbolFlags::Callable; 188*db995d72SSunho Kim } 189*db995d72SSunho Kim 190*db995d72SSunho Kim I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 191*db995d72SSunho Kim } 192*db995d72SSunho Kim 193*db995d72SSunho Kim // FIXME: handle init symbols 194*db995d72SSunho Kim 195*db995d72SSunho Kim return I; 196*db995d72SSunho Kim } 197*db995d72SSunho Kim 1984299d8d0SLang Hames Expected<MaterializationUnit::Interface> 1994299d8d0SLang Hames getGenericObjectFileSymbolInfo(ExecutionSession &ES, 2004299d8d0SLang Hames const object::ObjectFile &Obj) { 2014299d8d0SLang Hames MaterializationUnit::Interface I; 2024299d8d0SLang Hames 2034299d8d0SLang Hames for (auto &Sym : Obj.symbols()) { 2044299d8d0SLang Hames Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 2054299d8d0SLang Hames if (!SymFlagsOrErr) 2064299d8d0SLang Hames // TODO: Test this error. 2074299d8d0SLang Hames return SymFlagsOrErr.takeError(); 2084299d8d0SLang Hames 2094299d8d0SLang Hames // Skip symbols not defined in this object file. 2104299d8d0SLang Hames if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 2114299d8d0SLang Hames continue; 2124299d8d0SLang Hames 2134299d8d0SLang Hames // Skip symbols that are not global. 2144299d8d0SLang Hames if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 2154299d8d0SLang Hames continue; 2164299d8d0SLang Hames 2174299d8d0SLang Hames // Skip symbols that have type SF_File. 2184299d8d0SLang Hames if (auto SymType = Sym.getType()) { 2194299d8d0SLang Hames if (*SymType == object::SymbolRef::ST_File) 2204299d8d0SLang Hames continue; 2214299d8d0SLang Hames } else 2224299d8d0SLang Hames return SymType.takeError(); 2234299d8d0SLang Hames 2244299d8d0SLang Hames auto Name = Sym.getName(); 2254299d8d0SLang Hames if (!Name) 2264299d8d0SLang Hames return Name.takeError(); 2272ca81cd9SLang Hames 2284299d8d0SLang Hames auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 2294299d8d0SLang Hames if (!SymFlags) 2304299d8d0SLang Hames return SymFlags.takeError(); 2314299d8d0SLang Hames 2322ca81cd9SLang Hames I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 2334299d8d0SLang Hames } 2344299d8d0SLang Hames 2354299d8d0SLang Hames return I; 2364299d8d0SLang Hames } 2374299d8d0SLang Hames 2384299d8d0SLang Hames Expected<MaterializationUnit::Interface> 2394299d8d0SLang Hames getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) { 2404299d8d0SLang Hames auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); 2414299d8d0SLang Hames 2424299d8d0SLang Hames if (!Obj) 2434299d8d0SLang Hames return Obj.takeError(); 2444299d8d0SLang Hames 2454299d8d0SLang Hames if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get())) 2464299d8d0SLang Hames return getMachOObjectFileSymbolInfo(ES, *MachOObj); 2474299d8d0SLang Hames else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get())) 2484299d8d0SLang Hames return getELFObjectFileSymbolInfo(ES, *ELFObj); 249*db995d72SSunho Kim else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get())) 250*db995d72SSunho Kim return getCOFFObjectFileSymbolInfo(ES, *COFFObj); 2514299d8d0SLang Hames 2524299d8d0SLang Hames return getGenericObjectFileSymbolInfo(ES, **Obj); 2534299d8d0SLang Hames } 2544299d8d0SLang Hames 2554299d8d0SLang Hames } // End namespace orc. 2564299d8d0SLang Hames } // End namespace llvm. 257