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" 10*bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/COFFPlatform.h" 110eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h" 120eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/MachOPlatform.h" 13753f127fSDimitry Andric #include "llvm/Object/COFF.h" 140eae32dcSDimitry Andric #include "llvm/Object/ELFObjectFile.h" 150eae32dcSDimitry Andric #include "llvm/Object/MachO.h" 160eae32dcSDimitry Andric #include "llvm/Object/ObjectFile.h" 170eae32dcSDimitry Andric #include "llvm/Support/Debug.h" 18*bdd1243dSDimitry Andric #include <optional> 190eae32dcSDimitry Andric 200eae32dcSDimitry Andric #define DEBUG_TYPE "orc" 210eae32dcSDimitry Andric 220eae32dcSDimitry Andric namespace llvm { 230eae32dcSDimitry Andric namespace orc { 240eae32dcSDimitry Andric 250eae32dcSDimitry Andric void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES, 260eae32dcSDimitry Andric StringRef ObjFileName) { 270eae32dcSDimitry Andric assert(!I.InitSymbol && "I already has an init symbol"); 280eae32dcSDimitry Andric size_t Counter = 0; 290eae32dcSDimitry Andric 300eae32dcSDimitry Andric do { 310eae32dcSDimitry Andric std::string InitSymString; 320eae32dcSDimitry Andric raw_string_ostream(InitSymString) 330eae32dcSDimitry Andric << "$." << ObjFileName << ".__inits." << Counter++; 340eae32dcSDimitry Andric I.InitSymbol = ES.intern(InitSymString); 350eae32dcSDimitry Andric } while (I.SymbolFlags.count(I.InitSymbol)); 360eae32dcSDimitry Andric 370eae32dcSDimitry Andric I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly; 380eae32dcSDimitry Andric } 390eae32dcSDimitry Andric 400eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface> 410eae32dcSDimitry Andric getMachOObjectFileSymbolInfo(ExecutionSession &ES, 420eae32dcSDimitry Andric const object::MachOObjectFile &Obj) { 430eae32dcSDimitry Andric MaterializationUnit::Interface I; 440eae32dcSDimitry Andric 450eae32dcSDimitry Andric for (auto &Sym : Obj.symbols()) { 460eae32dcSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 470eae32dcSDimitry Andric if (!SymFlagsOrErr) 480eae32dcSDimitry Andric // TODO: Test this error. 490eae32dcSDimitry Andric return SymFlagsOrErr.takeError(); 500eae32dcSDimitry Andric 510eae32dcSDimitry Andric // Skip symbols not defined in this object file. 520eae32dcSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 530eae32dcSDimitry Andric continue; 540eae32dcSDimitry Andric 550eae32dcSDimitry Andric // Skip symbols that are not global. 560eae32dcSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 570eae32dcSDimitry Andric continue; 580eae32dcSDimitry Andric 590eae32dcSDimitry Andric // Skip symbols that have type SF_File. 600eae32dcSDimitry Andric if (auto SymType = Sym.getType()) { 610eae32dcSDimitry Andric if (*SymType == object::SymbolRef::ST_File) 620eae32dcSDimitry Andric continue; 630eae32dcSDimitry Andric } else 640eae32dcSDimitry Andric return SymType.takeError(); 650eae32dcSDimitry Andric 660eae32dcSDimitry Andric auto Name = Sym.getName(); 670eae32dcSDimitry Andric if (!Name) 680eae32dcSDimitry Andric return Name.takeError(); 690eae32dcSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 700eae32dcSDimitry Andric if (!SymFlags) 710eae32dcSDimitry Andric return SymFlags.takeError(); 720eae32dcSDimitry Andric 730eae32dcSDimitry Andric // Strip the 'exported' flag from MachO linker-private symbols. 740eae32dcSDimitry Andric if (Name->startswith("l")) 750eae32dcSDimitry Andric *SymFlags &= ~JITSymbolFlags::Exported; 760eae32dcSDimitry Andric 7781ad6265SDimitry Andric I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 780eae32dcSDimitry Andric } 790eae32dcSDimitry Andric 800eae32dcSDimitry Andric for (auto &Sec : Obj.sections()) { 810eae32dcSDimitry Andric auto SecType = Obj.getSectionType(Sec); 820eae32dcSDimitry Andric if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) { 830eae32dcSDimitry Andric addInitSymbol(I, ES, Obj.getFileName()); 840eae32dcSDimitry Andric break; 850eae32dcSDimitry Andric } 860eae32dcSDimitry Andric auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl()); 870eae32dcSDimitry Andric auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl())); 880eae32dcSDimitry Andric if (MachOPlatform::isInitializerSection(SegName, SecName)) { 890eae32dcSDimitry Andric addInitSymbol(I, ES, Obj.getFileName()); 900eae32dcSDimitry Andric break; 910eae32dcSDimitry Andric } 920eae32dcSDimitry Andric } 930eae32dcSDimitry Andric 940eae32dcSDimitry Andric return I; 950eae32dcSDimitry Andric } 960eae32dcSDimitry Andric 970eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface> 980eae32dcSDimitry Andric getELFObjectFileSymbolInfo(ExecutionSession &ES, 990eae32dcSDimitry Andric const object::ELFObjectFileBase &Obj) { 1000eae32dcSDimitry Andric MaterializationUnit::Interface I; 1010eae32dcSDimitry Andric 1020eae32dcSDimitry Andric for (auto &Sym : Obj.symbols()) { 1030eae32dcSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 1040eae32dcSDimitry Andric if (!SymFlagsOrErr) 1050eae32dcSDimitry Andric // TODO: Test this error. 1060eae32dcSDimitry Andric return SymFlagsOrErr.takeError(); 1070eae32dcSDimitry Andric 1080eae32dcSDimitry Andric // Skip symbols not defined in this object file. 1090eae32dcSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 1100eae32dcSDimitry Andric continue; 1110eae32dcSDimitry Andric 1120eae32dcSDimitry Andric // Skip symbols that are not global. 1130eae32dcSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 1140eae32dcSDimitry Andric continue; 1150eae32dcSDimitry Andric 1160eae32dcSDimitry Andric // Skip symbols that have type SF_File. 1170eae32dcSDimitry Andric if (auto SymType = Sym.getType()) { 1180eae32dcSDimitry Andric if (*SymType == object::SymbolRef::ST_File) 1190eae32dcSDimitry Andric continue; 1200eae32dcSDimitry Andric } else 1210eae32dcSDimitry Andric return SymType.takeError(); 1220eae32dcSDimitry Andric 1230eae32dcSDimitry Andric auto Name = Sym.getName(); 1240eae32dcSDimitry Andric if (!Name) 1250eae32dcSDimitry Andric return Name.takeError(); 12681ad6265SDimitry Andric 1270eae32dcSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 1280eae32dcSDimitry Andric if (!SymFlags) 1290eae32dcSDimitry Andric return SymFlags.takeError(); 1300eae32dcSDimitry Andric 1310eae32dcSDimitry Andric // ELF STB_GNU_UNIQUE should map to Weak for ORC. 1320eae32dcSDimitry Andric if (Sym.getBinding() == ELF::STB_GNU_UNIQUE) 1330eae32dcSDimitry Andric *SymFlags |= JITSymbolFlags::Weak; 1340eae32dcSDimitry Andric 13581ad6265SDimitry Andric I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 1360eae32dcSDimitry Andric } 1370eae32dcSDimitry Andric 1380eae32dcSDimitry Andric SymbolStringPtr InitSymbol; 1390eae32dcSDimitry Andric for (auto &Sec : Obj.sections()) { 1400eae32dcSDimitry Andric if (auto SecName = Sec.getName()) { 1410eae32dcSDimitry Andric if (ELFNixPlatform::isInitializerSection(*SecName)) { 1420eae32dcSDimitry Andric addInitSymbol(I, ES, Obj.getFileName()); 1430eae32dcSDimitry Andric break; 1440eae32dcSDimitry Andric } 1450eae32dcSDimitry Andric } 1460eae32dcSDimitry Andric } 1470eae32dcSDimitry Andric 1480eae32dcSDimitry Andric return I; 1490eae32dcSDimitry Andric } 1500eae32dcSDimitry Andric 151753f127fSDimitry Andric static Expected<MaterializationUnit::Interface> 152753f127fSDimitry Andric getCOFFObjectFileSymbolInfo(ExecutionSession &ES, 153753f127fSDimitry Andric const object::COFFObjectFile &Obj) { 154753f127fSDimitry Andric MaterializationUnit::Interface I; 155*bdd1243dSDimitry Andric std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs( 156972a253aSDimitry Andric Obj.getNumberOfSections() + 1); 157753f127fSDimitry Andric for (auto &Sym : Obj.symbols()) { 158753f127fSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 159753f127fSDimitry Andric if (!SymFlagsOrErr) 160753f127fSDimitry Andric // TODO: Test this error. 161753f127fSDimitry Andric return SymFlagsOrErr.takeError(); 162753f127fSDimitry Andric 163972a253aSDimitry Andric // Handle comdat symbols 164972a253aSDimitry Andric auto COFFSym = Obj.getCOFFSymbol(Sym); 165972a253aSDimitry Andric bool IsWeak = false; 166972a253aSDimitry Andric if (auto *Def = COFFSym.getSectionDefinition()) { 167972a253aSDimitry Andric auto Sec = Obj.getSection(COFFSym.getSectionNumber()); 168972a253aSDimitry Andric if (!Sec) 169972a253aSDimitry Andric return Sec.takeError(); 170972a253aSDimitry Andric if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) && 171972a253aSDimitry Andric Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { 172972a253aSDimitry Andric ComdatDefs[COFFSym.getSectionNumber()] = *Def; 173972a253aSDimitry Andric continue; 174972a253aSDimitry Andric } 175972a253aSDimitry Andric } 176972a253aSDimitry Andric if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) && 177972a253aSDimitry Andric ComdatDefs[COFFSym.getSectionNumber()]) { 178972a253aSDimitry Andric auto Def = ComdatDefs[COFFSym.getSectionNumber()]; 179972a253aSDimitry Andric if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) { 180972a253aSDimitry Andric IsWeak = true; 181972a253aSDimitry Andric } 182*bdd1243dSDimitry Andric ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt; 183972a253aSDimitry Andric } else { 184753f127fSDimitry Andric // Skip symbols not defined in this object file. 185753f127fSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 186753f127fSDimitry Andric continue; 187972a253aSDimitry Andric } 188753f127fSDimitry Andric 189753f127fSDimitry Andric // Skip symbols that are not global. 190753f127fSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 191753f127fSDimitry Andric continue; 192753f127fSDimitry Andric 193753f127fSDimitry Andric // Skip symbols that have type SF_File. 194753f127fSDimitry Andric if (auto SymType = Sym.getType()) { 195753f127fSDimitry Andric if (*SymType == object::SymbolRef::ST_File) 196753f127fSDimitry Andric continue; 197753f127fSDimitry Andric } else 198753f127fSDimitry Andric return SymType.takeError(); 199753f127fSDimitry Andric 200753f127fSDimitry Andric auto Name = Sym.getName(); 201753f127fSDimitry Andric if (!Name) 202753f127fSDimitry Andric return Name.takeError(); 203753f127fSDimitry Andric 204753f127fSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 205753f127fSDimitry Andric if (!SymFlags) 206753f127fSDimitry Andric return SymFlags.takeError(); 207753f127fSDimitry Andric *SymFlags |= JITSymbolFlags::Exported; 208753f127fSDimitry Andric 209753f127fSDimitry Andric // Weak external is always a function 210972a253aSDimitry Andric if (COFFSym.isWeakExternal()) 211753f127fSDimitry Andric *SymFlags |= JITSymbolFlags::Callable; 212972a253aSDimitry Andric 213972a253aSDimitry Andric if (IsWeak) 214972a253aSDimitry Andric *SymFlags |= JITSymbolFlags::Weak; 215753f127fSDimitry Andric 216753f127fSDimitry Andric I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 217753f127fSDimitry Andric } 218753f127fSDimitry Andric 219*bdd1243dSDimitry Andric SymbolStringPtr InitSymbol; 220*bdd1243dSDimitry Andric for (auto &Sec : Obj.sections()) { 221*bdd1243dSDimitry Andric if (auto SecName = Sec.getName()) { 222*bdd1243dSDimitry Andric if (COFFPlatform::isInitializerSection(*SecName)) { 223*bdd1243dSDimitry Andric addInitSymbol(I, ES, Obj.getFileName()); 224*bdd1243dSDimitry Andric break; 225*bdd1243dSDimitry Andric } 226*bdd1243dSDimitry Andric } else 227*bdd1243dSDimitry Andric return SecName.takeError(); 228*bdd1243dSDimitry Andric } 229753f127fSDimitry Andric 230753f127fSDimitry Andric return I; 231753f127fSDimitry Andric } 232753f127fSDimitry Andric 2330eae32dcSDimitry Andric Expected<MaterializationUnit::Interface> 2340eae32dcSDimitry Andric getGenericObjectFileSymbolInfo(ExecutionSession &ES, 2350eae32dcSDimitry Andric const object::ObjectFile &Obj) { 2360eae32dcSDimitry Andric MaterializationUnit::Interface I; 2370eae32dcSDimitry Andric 2380eae32dcSDimitry Andric for (auto &Sym : Obj.symbols()) { 2390eae32dcSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 2400eae32dcSDimitry Andric if (!SymFlagsOrErr) 2410eae32dcSDimitry Andric // TODO: Test this error. 2420eae32dcSDimitry Andric return SymFlagsOrErr.takeError(); 2430eae32dcSDimitry Andric 2440eae32dcSDimitry Andric // Skip symbols not defined in this object file. 2450eae32dcSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 2460eae32dcSDimitry Andric continue; 2470eae32dcSDimitry Andric 2480eae32dcSDimitry Andric // Skip symbols that are not global. 2490eae32dcSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 2500eae32dcSDimitry Andric continue; 2510eae32dcSDimitry Andric 2520eae32dcSDimitry Andric // Skip symbols that have type SF_File. 2530eae32dcSDimitry Andric if (auto SymType = Sym.getType()) { 2540eae32dcSDimitry Andric if (*SymType == object::SymbolRef::ST_File) 2550eae32dcSDimitry Andric continue; 2560eae32dcSDimitry Andric } else 2570eae32dcSDimitry Andric return SymType.takeError(); 2580eae32dcSDimitry Andric 2590eae32dcSDimitry Andric auto Name = Sym.getName(); 2600eae32dcSDimitry Andric if (!Name) 2610eae32dcSDimitry Andric return Name.takeError(); 26281ad6265SDimitry Andric 2630eae32dcSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 2640eae32dcSDimitry Andric if (!SymFlags) 2650eae32dcSDimitry Andric return SymFlags.takeError(); 2660eae32dcSDimitry Andric 26781ad6265SDimitry Andric I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 2680eae32dcSDimitry Andric } 2690eae32dcSDimitry Andric 2700eae32dcSDimitry Andric return I; 2710eae32dcSDimitry Andric } 2720eae32dcSDimitry Andric 2730eae32dcSDimitry Andric Expected<MaterializationUnit::Interface> 2740eae32dcSDimitry Andric getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) { 2750eae32dcSDimitry Andric auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); 2760eae32dcSDimitry Andric 2770eae32dcSDimitry Andric if (!Obj) 2780eae32dcSDimitry Andric return Obj.takeError(); 2790eae32dcSDimitry Andric 2800eae32dcSDimitry Andric if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get())) 2810eae32dcSDimitry Andric return getMachOObjectFileSymbolInfo(ES, *MachOObj); 2820eae32dcSDimitry Andric else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get())) 2830eae32dcSDimitry Andric return getELFObjectFileSymbolInfo(ES, *ELFObj); 284753f127fSDimitry Andric else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get())) 285753f127fSDimitry Andric return getCOFFObjectFileSymbolInfo(ES, *COFFObj); 2860eae32dcSDimitry Andric 2870eae32dcSDimitry Andric return getGenericObjectFileSymbolInfo(ES, **Obj); 2880eae32dcSDimitry Andric } 2890eae32dcSDimitry Andric 290*bdd1243dSDimitry Andric bool hasInitializerSection(jitlink::LinkGraph &G) { 291*bdd1243dSDimitry Andric bool IsMachO = G.getTargetTriple().isOSBinFormatMachO(); 292*bdd1243dSDimitry Andric bool IsElf = G.getTargetTriple().isOSBinFormatELF(); 293*bdd1243dSDimitry Andric if (!IsMachO && !IsElf) 294*bdd1243dSDimitry Andric return false; 295*bdd1243dSDimitry Andric 296*bdd1243dSDimitry Andric for (auto &Sec : G.sections()) { 297*bdd1243dSDimitry Andric if (IsMachO && std::apply(MachOPlatform::isInitializerSection, 298*bdd1243dSDimitry Andric Sec.getName().split(","))) 299*bdd1243dSDimitry Andric return true; 300*bdd1243dSDimitry Andric if (IsElf && ELFNixPlatform::isInitializerSection(Sec.getName())) 301*bdd1243dSDimitry Andric return true; 302*bdd1243dSDimitry Andric } 303*bdd1243dSDimitry Andric 304*bdd1243dSDimitry Andric return false; 305*bdd1243dSDimitry Andric } 306*bdd1243dSDimitry Andric 3070eae32dcSDimitry Andric } // End namespace orc. 3080eae32dcSDimitry Andric } // End namespace llvm. 309