1*0eae32dcSDimitry Andric //===------ ObjectFileInterface.cpp - MU interface utils for objects ------===// 2*0eae32dcSDimitry Andric // 3*0eae32dcSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0eae32dcSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0eae32dcSDimitry Andric // 7*0eae32dcSDimitry Andric //===----------------------------------------------------------------------===// 8*0eae32dcSDimitry Andric 9*0eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" 10*0eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h" 11*0eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/MachOPlatform.h" 12*0eae32dcSDimitry Andric #include "llvm/Object/ELFObjectFile.h" 13*0eae32dcSDimitry Andric #include "llvm/Object/MachO.h" 14*0eae32dcSDimitry Andric #include "llvm/Object/ObjectFile.h" 15*0eae32dcSDimitry Andric #include "llvm/Support/Debug.h" 16*0eae32dcSDimitry Andric 17*0eae32dcSDimitry Andric #define DEBUG_TYPE "orc" 18*0eae32dcSDimitry Andric 19*0eae32dcSDimitry Andric namespace llvm { 20*0eae32dcSDimitry Andric namespace orc { 21*0eae32dcSDimitry Andric 22*0eae32dcSDimitry Andric void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES, 23*0eae32dcSDimitry Andric StringRef ObjFileName) { 24*0eae32dcSDimitry Andric assert(!I.InitSymbol && "I already has an init symbol"); 25*0eae32dcSDimitry Andric size_t Counter = 0; 26*0eae32dcSDimitry Andric 27*0eae32dcSDimitry Andric do { 28*0eae32dcSDimitry Andric std::string InitSymString; 29*0eae32dcSDimitry Andric raw_string_ostream(InitSymString) 30*0eae32dcSDimitry Andric << "$." << ObjFileName << ".__inits." << Counter++; 31*0eae32dcSDimitry Andric I.InitSymbol = ES.intern(InitSymString); 32*0eae32dcSDimitry Andric } while (I.SymbolFlags.count(I.InitSymbol)); 33*0eae32dcSDimitry Andric 34*0eae32dcSDimitry Andric I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly; 35*0eae32dcSDimitry Andric } 36*0eae32dcSDimitry Andric 37*0eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface> 38*0eae32dcSDimitry Andric getMachOObjectFileSymbolInfo(ExecutionSession &ES, 39*0eae32dcSDimitry Andric const object::MachOObjectFile &Obj) { 40*0eae32dcSDimitry Andric MaterializationUnit::Interface I; 41*0eae32dcSDimitry Andric 42*0eae32dcSDimitry Andric for (auto &Sym : Obj.symbols()) { 43*0eae32dcSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 44*0eae32dcSDimitry Andric if (!SymFlagsOrErr) 45*0eae32dcSDimitry Andric // TODO: Test this error. 46*0eae32dcSDimitry Andric return SymFlagsOrErr.takeError(); 47*0eae32dcSDimitry Andric 48*0eae32dcSDimitry Andric // Skip symbols not defined in this object file. 49*0eae32dcSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 50*0eae32dcSDimitry Andric continue; 51*0eae32dcSDimitry Andric 52*0eae32dcSDimitry Andric // Skip symbols that are not global. 53*0eae32dcSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 54*0eae32dcSDimitry Andric continue; 55*0eae32dcSDimitry Andric 56*0eae32dcSDimitry Andric // Skip symbols that have type SF_File. 57*0eae32dcSDimitry Andric if (auto SymType = Sym.getType()) { 58*0eae32dcSDimitry Andric if (*SymType == object::SymbolRef::ST_File) 59*0eae32dcSDimitry Andric continue; 60*0eae32dcSDimitry Andric } else 61*0eae32dcSDimitry Andric return SymType.takeError(); 62*0eae32dcSDimitry Andric 63*0eae32dcSDimitry Andric auto Name = Sym.getName(); 64*0eae32dcSDimitry Andric if (!Name) 65*0eae32dcSDimitry Andric return Name.takeError(); 66*0eae32dcSDimitry Andric auto InternedName = ES.intern(*Name); 67*0eae32dcSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 68*0eae32dcSDimitry Andric if (!SymFlags) 69*0eae32dcSDimitry Andric return SymFlags.takeError(); 70*0eae32dcSDimitry Andric 71*0eae32dcSDimitry Andric // Strip the 'exported' flag from MachO linker-private symbols. 72*0eae32dcSDimitry Andric if (Name->startswith("l")) 73*0eae32dcSDimitry Andric *SymFlags &= ~JITSymbolFlags::Exported; 74*0eae32dcSDimitry Andric 75*0eae32dcSDimitry Andric I.SymbolFlags[InternedName] = std::move(*SymFlags); 76*0eae32dcSDimitry Andric } 77*0eae32dcSDimitry Andric 78*0eae32dcSDimitry Andric for (auto &Sec : Obj.sections()) { 79*0eae32dcSDimitry Andric auto SecType = Obj.getSectionType(Sec); 80*0eae32dcSDimitry Andric if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) { 81*0eae32dcSDimitry Andric addInitSymbol(I, ES, Obj.getFileName()); 82*0eae32dcSDimitry Andric break; 83*0eae32dcSDimitry Andric } 84*0eae32dcSDimitry Andric auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl()); 85*0eae32dcSDimitry Andric auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl())); 86*0eae32dcSDimitry Andric if (MachOPlatform::isInitializerSection(SegName, SecName)) { 87*0eae32dcSDimitry Andric addInitSymbol(I, ES, Obj.getFileName()); 88*0eae32dcSDimitry Andric break; 89*0eae32dcSDimitry Andric } 90*0eae32dcSDimitry Andric } 91*0eae32dcSDimitry Andric 92*0eae32dcSDimitry Andric return I; 93*0eae32dcSDimitry Andric } 94*0eae32dcSDimitry Andric 95*0eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface> 96*0eae32dcSDimitry Andric getELFObjectFileSymbolInfo(ExecutionSession &ES, 97*0eae32dcSDimitry Andric const object::ELFObjectFileBase &Obj) { 98*0eae32dcSDimitry Andric MaterializationUnit::Interface I; 99*0eae32dcSDimitry Andric 100*0eae32dcSDimitry Andric for (auto &Sym : Obj.symbols()) { 101*0eae32dcSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 102*0eae32dcSDimitry Andric if (!SymFlagsOrErr) 103*0eae32dcSDimitry Andric // TODO: Test this error. 104*0eae32dcSDimitry Andric return SymFlagsOrErr.takeError(); 105*0eae32dcSDimitry Andric 106*0eae32dcSDimitry Andric // Skip symbols not defined in this object file. 107*0eae32dcSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 108*0eae32dcSDimitry Andric continue; 109*0eae32dcSDimitry Andric 110*0eae32dcSDimitry Andric // Skip symbols that are not global. 111*0eae32dcSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 112*0eae32dcSDimitry Andric continue; 113*0eae32dcSDimitry Andric 114*0eae32dcSDimitry Andric // Skip symbols that have type SF_File. 115*0eae32dcSDimitry Andric if (auto SymType = Sym.getType()) { 116*0eae32dcSDimitry Andric if (*SymType == object::SymbolRef::ST_File) 117*0eae32dcSDimitry Andric continue; 118*0eae32dcSDimitry Andric } else 119*0eae32dcSDimitry Andric return SymType.takeError(); 120*0eae32dcSDimitry Andric 121*0eae32dcSDimitry Andric auto Name = Sym.getName(); 122*0eae32dcSDimitry Andric if (!Name) 123*0eae32dcSDimitry Andric return Name.takeError(); 124*0eae32dcSDimitry Andric auto InternedName = ES.intern(*Name); 125*0eae32dcSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 126*0eae32dcSDimitry Andric if (!SymFlags) 127*0eae32dcSDimitry Andric return SymFlags.takeError(); 128*0eae32dcSDimitry Andric 129*0eae32dcSDimitry Andric // ELF STB_GNU_UNIQUE should map to Weak for ORC. 130*0eae32dcSDimitry Andric if (Sym.getBinding() == ELF::STB_GNU_UNIQUE) 131*0eae32dcSDimitry Andric *SymFlags |= JITSymbolFlags::Weak; 132*0eae32dcSDimitry Andric 133*0eae32dcSDimitry Andric I.SymbolFlags[InternedName] = std::move(*SymFlags); 134*0eae32dcSDimitry Andric } 135*0eae32dcSDimitry Andric 136*0eae32dcSDimitry Andric SymbolStringPtr InitSymbol; 137*0eae32dcSDimitry Andric for (auto &Sec : Obj.sections()) { 138*0eae32dcSDimitry Andric if (auto SecName = Sec.getName()) { 139*0eae32dcSDimitry Andric if (ELFNixPlatform::isInitializerSection(*SecName)) { 140*0eae32dcSDimitry Andric addInitSymbol(I, ES, Obj.getFileName()); 141*0eae32dcSDimitry Andric break; 142*0eae32dcSDimitry Andric } 143*0eae32dcSDimitry Andric } 144*0eae32dcSDimitry Andric } 145*0eae32dcSDimitry Andric 146*0eae32dcSDimitry Andric return I; 147*0eae32dcSDimitry Andric } 148*0eae32dcSDimitry Andric 149*0eae32dcSDimitry Andric Expected<MaterializationUnit::Interface> 150*0eae32dcSDimitry Andric getGenericObjectFileSymbolInfo(ExecutionSession &ES, 151*0eae32dcSDimitry Andric const object::ObjectFile &Obj) { 152*0eae32dcSDimitry Andric MaterializationUnit::Interface I; 153*0eae32dcSDimitry Andric 154*0eae32dcSDimitry Andric for (auto &Sym : Obj.symbols()) { 155*0eae32dcSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 156*0eae32dcSDimitry Andric if (!SymFlagsOrErr) 157*0eae32dcSDimitry Andric // TODO: Test this error. 158*0eae32dcSDimitry Andric return SymFlagsOrErr.takeError(); 159*0eae32dcSDimitry Andric 160*0eae32dcSDimitry Andric // Skip symbols not defined in this object file. 161*0eae32dcSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 162*0eae32dcSDimitry Andric continue; 163*0eae32dcSDimitry Andric 164*0eae32dcSDimitry Andric // Skip symbols that are not global. 165*0eae32dcSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 166*0eae32dcSDimitry Andric continue; 167*0eae32dcSDimitry Andric 168*0eae32dcSDimitry Andric // Skip symbols that have type SF_File. 169*0eae32dcSDimitry Andric if (auto SymType = Sym.getType()) { 170*0eae32dcSDimitry Andric if (*SymType == object::SymbolRef::ST_File) 171*0eae32dcSDimitry Andric continue; 172*0eae32dcSDimitry Andric } else 173*0eae32dcSDimitry Andric return SymType.takeError(); 174*0eae32dcSDimitry Andric 175*0eae32dcSDimitry Andric auto Name = Sym.getName(); 176*0eae32dcSDimitry Andric if (!Name) 177*0eae32dcSDimitry Andric return Name.takeError(); 178*0eae32dcSDimitry Andric auto InternedName = ES.intern(*Name); 179*0eae32dcSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 180*0eae32dcSDimitry Andric if (!SymFlags) 181*0eae32dcSDimitry Andric return SymFlags.takeError(); 182*0eae32dcSDimitry Andric 183*0eae32dcSDimitry Andric I.SymbolFlags[InternedName] = std::move(*SymFlags); 184*0eae32dcSDimitry Andric } 185*0eae32dcSDimitry Andric 186*0eae32dcSDimitry Andric return I; 187*0eae32dcSDimitry Andric } 188*0eae32dcSDimitry Andric 189*0eae32dcSDimitry Andric Expected<MaterializationUnit::Interface> 190*0eae32dcSDimitry Andric getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) { 191*0eae32dcSDimitry Andric auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); 192*0eae32dcSDimitry Andric 193*0eae32dcSDimitry Andric if (!Obj) 194*0eae32dcSDimitry Andric return Obj.takeError(); 195*0eae32dcSDimitry Andric 196*0eae32dcSDimitry Andric if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get())) 197*0eae32dcSDimitry Andric return getMachOObjectFileSymbolInfo(ES, *MachOObj); 198*0eae32dcSDimitry Andric else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get())) 199*0eae32dcSDimitry Andric return getELFObjectFileSymbolInfo(ES, *ELFObj); 200*0eae32dcSDimitry Andric 201*0eae32dcSDimitry Andric return getGenericObjectFileSymbolInfo(ES, **Obj); 202*0eae32dcSDimitry Andric } 203*0eae32dcSDimitry Andric 204*0eae32dcSDimitry Andric } // End namespace orc. 205*0eae32dcSDimitry Andric } // End namespace llvm. 206