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" 13*06c3fb27SDimitry 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 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> 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. 750eae32dcSDimitry Andric if (Name->startswith("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())); 89*06c3fb27SDimitry 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> 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()) { 142*06c3fb27SDimitry 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> 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()) { 223*06c3fb27SDimitry 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> 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> 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