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" 100eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h" 110eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/MachOPlatform.h" 12753f127fSDimitry Andric #include "llvm/Object/COFF.h" 130eae32dcSDimitry Andric #include "llvm/Object/ELFObjectFile.h" 140eae32dcSDimitry Andric #include "llvm/Object/MachO.h" 150eae32dcSDimitry Andric #include "llvm/Object/ObjectFile.h" 160eae32dcSDimitry Andric #include "llvm/Support/Debug.h" 170eae32dcSDimitry Andric 180eae32dcSDimitry Andric #define DEBUG_TYPE "orc" 190eae32dcSDimitry Andric 200eae32dcSDimitry Andric namespace llvm { 210eae32dcSDimitry Andric namespace orc { 220eae32dcSDimitry Andric 230eae32dcSDimitry Andric void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES, 240eae32dcSDimitry Andric StringRef ObjFileName) { 250eae32dcSDimitry Andric assert(!I.InitSymbol && "I already has an init symbol"); 260eae32dcSDimitry Andric size_t Counter = 0; 270eae32dcSDimitry Andric 280eae32dcSDimitry Andric do { 290eae32dcSDimitry Andric std::string InitSymString; 300eae32dcSDimitry Andric raw_string_ostream(InitSymString) 310eae32dcSDimitry Andric << "$." << ObjFileName << ".__inits." << Counter++; 320eae32dcSDimitry Andric I.InitSymbol = ES.intern(InitSymString); 330eae32dcSDimitry Andric } while (I.SymbolFlags.count(I.InitSymbol)); 340eae32dcSDimitry Andric 350eae32dcSDimitry Andric I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly; 360eae32dcSDimitry Andric } 370eae32dcSDimitry Andric 380eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface> 390eae32dcSDimitry Andric getMachOObjectFileSymbolInfo(ExecutionSession &ES, 400eae32dcSDimitry Andric const object::MachOObjectFile &Obj) { 410eae32dcSDimitry Andric MaterializationUnit::Interface I; 420eae32dcSDimitry Andric 430eae32dcSDimitry Andric for (auto &Sym : Obj.symbols()) { 440eae32dcSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 450eae32dcSDimitry Andric if (!SymFlagsOrErr) 460eae32dcSDimitry Andric // TODO: Test this error. 470eae32dcSDimitry Andric return SymFlagsOrErr.takeError(); 480eae32dcSDimitry Andric 490eae32dcSDimitry Andric // Skip symbols not defined in this object file. 500eae32dcSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 510eae32dcSDimitry Andric continue; 520eae32dcSDimitry Andric 530eae32dcSDimitry Andric // Skip symbols that are not global. 540eae32dcSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 550eae32dcSDimitry Andric continue; 560eae32dcSDimitry Andric 570eae32dcSDimitry Andric // Skip symbols that have type SF_File. 580eae32dcSDimitry Andric if (auto SymType = Sym.getType()) { 590eae32dcSDimitry Andric if (*SymType == object::SymbolRef::ST_File) 600eae32dcSDimitry Andric continue; 610eae32dcSDimitry Andric } else 620eae32dcSDimitry Andric return SymType.takeError(); 630eae32dcSDimitry Andric 640eae32dcSDimitry Andric auto Name = Sym.getName(); 650eae32dcSDimitry Andric if (!Name) 660eae32dcSDimitry Andric return Name.takeError(); 670eae32dcSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 680eae32dcSDimitry Andric if (!SymFlags) 690eae32dcSDimitry Andric return SymFlags.takeError(); 700eae32dcSDimitry Andric 710eae32dcSDimitry Andric // Strip the 'exported' flag from MachO linker-private symbols. 720eae32dcSDimitry Andric if (Name->startswith("l")) 730eae32dcSDimitry Andric *SymFlags &= ~JITSymbolFlags::Exported; 740eae32dcSDimitry Andric 7581ad6265SDimitry Andric I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 760eae32dcSDimitry Andric } 770eae32dcSDimitry Andric 780eae32dcSDimitry Andric for (auto &Sec : Obj.sections()) { 790eae32dcSDimitry Andric auto SecType = Obj.getSectionType(Sec); 800eae32dcSDimitry Andric if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) { 810eae32dcSDimitry Andric addInitSymbol(I, ES, Obj.getFileName()); 820eae32dcSDimitry Andric break; 830eae32dcSDimitry Andric } 840eae32dcSDimitry Andric auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl()); 850eae32dcSDimitry Andric auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl())); 860eae32dcSDimitry Andric if (MachOPlatform::isInitializerSection(SegName, SecName)) { 870eae32dcSDimitry Andric addInitSymbol(I, ES, Obj.getFileName()); 880eae32dcSDimitry Andric break; 890eae32dcSDimitry Andric } 900eae32dcSDimitry Andric } 910eae32dcSDimitry Andric 920eae32dcSDimitry Andric return I; 930eae32dcSDimitry Andric } 940eae32dcSDimitry Andric 950eae32dcSDimitry Andric static Expected<MaterializationUnit::Interface> 960eae32dcSDimitry Andric getELFObjectFileSymbolInfo(ExecutionSession &ES, 970eae32dcSDimitry Andric const object::ELFObjectFileBase &Obj) { 980eae32dcSDimitry Andric MaterializationUnit::Interface I; 990eae32dcSDimitry Andric 1000eae32dcSDimitry Andric for (auto &Sym : Obj.symbols()) { 1010eae32dcSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 1020eae32dcSDimitry Andric if (!SymFlagsOrErr) 1030eae32dcSDimitry Andric // TODO: Test this error. 1040eae32dcSDimitry Andric return SymFlagsOrErr.takeError(); 1050eae32dcSDimitry Andric 1060eae32dcSDimitry Andric // Skip symbols not defined in this object file. 1070eae32dcSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 1080eae32dcSDimitry Andric continue; 1090eae32dcSDimitry Andric 1100eae32dcSDimitry Andric // Skip symbols that are not global. 1110eae32dcSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 1120eae32dcSDimitry Andric continue; 1130eae32dcSDimitry Andric 1140eae32dcSDimitry Andric // Skip symbols that have type SF_File. 1150eae32dcSDimitry Andric if (auto SymType = Sym.getType()) { 1160eae32dcSDimitry Andric if (*SymType == object::SymbolRef::ST_File) 1170eae32dcSDimitry Andric continue; 1180eae32dcSDimitry Andric } else 1190eae32dcSDimitry Andric return SymType.takeError(); 1200eae32dcSDimitry Andric 1210eae32dcSDimitry Andric auto Name = Sym.getName(); 1220eae32dcSDimitry Andric if (!Name) 1230eae32dcSDimitry Andric return Name.takeError(); 12481ad6265SDimitry Andric 1250eae32dcSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 1260eae32dcSDimitry Andric if (!SymFlags) 1270eae32dcSDimitry Andric return SymFlags.takeError(); 1280eae32dcSDimitry Andric 1290eae32dcSDimitry Andric // ELF STB_GNU_UNIQUE should map to Weak for ORC. 1300eae32dcSDimitry Andric if (Sym.getBinding() == ELF::STB_GNU_UNIQUE) 1310eae32dcSDimitry Andric *SymFlags |= JITSymbolFlags::Weak; 1320eae32dcSDimitry Andric 13381ad6265SDimitry Andric I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 1340eae32dcSDimitry Andric } 1350eae32dcSDimitry Andric 1360eae32dcSDimitry Andric SymbolStringPtr InitSymbol; 1370eae32dcSDimitry Andric for (auto &Sec : Obj.sections()) { 1380eae32dcSDimitry Andric if (auto SecName = Sec.getName()) { 1390eae32dcSDimitry Andric if (ELFNixPlatform::isInitializerSection(*SecName)) { 1400eae32dcSDimitry Andric addInitSymbol(I, ES, Obj.getFileName()); 1410eae32dcSDimitry Andric break; 1420eae32dcSDimitry Andric } 1430eae32dcSDimitry Andric } 1440eae32dcSDimitry Andric } 1450eae32dcSDimitry Andric 1460eae32dcSDimitry Andric return I; 1470eae32dcSDimitry Andric } 1480eae32dcSDimitry Andric 149753f127fSDimitry Andric static Expected<MaterializationUnit::Interface> 150753f127fSDimitry Andric getCOFFObjectFileSymbolInfo(ExecutionSession &ES, 151753f127fSDimitry Andric const object::COFFObjectFile &Obj) { 152753f127fSDimitry Andric MaterializationUnit::Interface I; 153*972a253aSDimitry Andric std::vector<Optional<object::coff_aux_section_definition>> ComdatDefs( 154*972a253aSDimitry Andric Obj.getNumberOfSections() + 1); 155753f127fSDimitry Andric for (auto &Sym : Obj.symbols()) { 156753f127fSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 157753f127fSDimitry Andric if (!SymFlagsOrErr) 158753f127fSDimitry Andric // TODO: Test this error. 159753f127fSDimitry Andric return SymFlagsOrErr.takeError(); 160753f127fSDimitry Andric 161*972a253aSDimitry Andric // Handle comdat symbols 162*972a253aSDimitry Andric auto COFFSym = Obj.getCOFFSymbol(Sym); 163*972a253aSDimitry Andric bool IsWeak = false; 164*972a253aSDimitry Andric if (auto *Def = COFFSym.getSectionDefinition()) { 165*972a253aSDimitry Andric auto Sec = Obj.getSection(COFFSym.getSectionNumber()); 166*972a253aSDimitry Andric if (!Sec) 167*972a253aSDimitry Andric return Sec.takeError(); 168*972a253aSDimitry Andric if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) && 169*972a253aSDimitry Andric Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { 170*972a253aSDimitry Andric ComdatDefs[COFFSym.getSectionNumber()] = *Def; 171*972a253aSDimitry Andric continue; 172*972a253aSDimitry Andric } 173*972a253aSDimitry Andric } 174*972a253aSDimitry Andric if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) && 175*972a253aSDimitry Andric ComdatDefs[COFFSym.getSectionNumber()]) { 176*972a253aSDimitry Andric auto Def = ComdatDefs[COFFSym.getSectionNumber()]; 177*972a253aSDimitry Andric if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) { 178*972a253aSDimitry Andric IsWeak = true; 179*972a253aSDimitry Andric } 180*972a253aSDimitry Andric ComdatDefs[COFFSym.getSectionNumber()] = None; 181*972a253aSDimitry Andric } else { 182753f127fSDimitry Andric // Skip symbols not defined in this object file. 183753f127fSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 184753f127fSDimitry Andric continue; 185*972a253aSDimitry Andric } 186753f127fSDimitry Andric 187753f127fSDimitry Andric // Skip symbols that are not global. 188753f127fSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 189753f127fSDimitry Andric continue; 190753f127fSDimitry Andric 191753f127fSDimitry Andric // Skip symbols that have type SF_File. 192753f127fSDimitry Andric if (auto SymType = Sym.getType()) { 193753f127fSDimitry Andric if (*SymType == object::SymbolRef::ST_File) 194753f127fSDimitry Andric continue; 195753f127fSDimitry Andric } else 196753f127fSDimitry Andric return SymType.takeError(); 197753f127fSDimitry Andric 198753f127fSDimitry Andric auto Name = Sym.getName(); 199753f127fSDimitry Andric if (!Name) 200753f127fSDimitry Andric return Name.takeError(); 201753f127fSDimitry Andric 202753f127fSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 203753f127fSDimitry Andric if (!SymFlags) 204753f127fSDimitry Andric return SymFlags.takeError(); 205753f127fSDimitry Andric *SymFlags |= JITSymbolFlags::Exported; 206753f127fSDimitry Andric 207753f127fSDimitry Andric // Weak external is always a function 208*972a253aSDimitry Andric if (COFFSym.isWeakExternal()) 209753f127fSDimitry Andric *SymFlags |= JITSymbolFlags::Callable; 210*972a253aSDimitry Andric 211*972a253aSDimitry Andric if (IsWeak) 212*972a253aSDimitry Andric *SymFlags |= JITSymbolFlags::Weak; 213753f127fSDimitry Andric 214753f127fSDimitry Andric I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 215753f127fSDimitry Andric } 216753f127fSDimitry Andric 217753f127fSDimitry Andric // FIXME: handle init symbols 218753f127fSDimitry Andric 219753f127fSDimitry Andric return I; 220753f127fSDimitry Andric } 221753f127fSDimitry Andric 2220eae32dcSDimitry Andric Expected<MaterializationUnit::Interface> 2230eae32dcSDimitry Andric getGenericObjectFileSymbolInfo(ExecutionSession &ES, 2240eae32dcSDimitry Andric const object::ObjectFile &Obj) { 2250eae32dcSDimitry Andric MaterializationUnit::Interface I; 2260eae32dcSDimitry Andric 2270eae32dcSDimitry Andric for (auto &Sym : Obj.symbols()) { 2280eae32dcSDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 2290eae32dcSDimitry Andric if (!SymFlagsOrErr) 2300eae32dcSDimitry Andric // TODO: Test this error. 2310eae32dcSDimitry Andric return SymFlagsOrErr.takeError(); 2320eae32dcSDimitry Andric 2330eae32dcSDimitry Andric // Skip symbols not defined in this object file. 2340eae32dcSDimitry Andric if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) 2350eae32dcSDimitry Andric continue; 2360eae32dcSDimitry Andric 2370eae32dcSDimitry Andric // Skip symbols that are not global. 2380eae32dcSDimitry Andric if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) 2390eae32dcSDimitry Andric continue; 2400eae32dcSDimitry Andric 2410eae32dcSDimitry Andric // Skip symbols that have type SF_File. 2420eae32dcSDimitry Andric if (auto SymType = Sym.getType()) { 2430eae32dcSDimitry Andric if (*SymType == object::SymbolRef::ST_File) 2440eae32dcSDimitry Andric continue; 2450eae32dcSDimitry Andric } else 2460eae32dcSDimitry Andric return SymType.takeError(); 2470eae32dcSDimitry Andric 2480eae32dcSDimitry Andric auto Name = Sym.getName(); 2490eae32dcSDimitry Andric if (!Name) 2500eae32dcSDimitry Andric return Name.takeError(); 25181ad6265SDimitry Andric 2520eae32dcSDimitry Andric auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 2530eae32dcSDimitry Andric if (!SymFlags) 2540eae32dcSDimitry Andric return SymFlags.takeError(); 2550eae32dcSDimitry Andric 25681ad6265SDimitry Andric I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); 2570eae32dcSDimitry Andric } 2580eae32dcSDimitry Andric 2590eae32dcSDimitry Andric return I; 2600eae32dcSDimitry Andric } 2610eae32dcSDimitry Andric 2620eae32dcSDimitry Andric Expected<MaterializationUnit::Interface> 2630eae32dcSDimitry Andric getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) { 2640eae32dcSDimitry Andric auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); 2650eae32dcSDimitry Andric 2660eae32dcSDimitry Andric if (!Obj) 2670eae32dcSDimitry Andric return Obj.takeError(); 2680eae32dcSDimitry Andric 2690eae32dcSDimitry Andric if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get())) 2700eae32dcSDimitry Andric return getMachOObjectFileSymbolInfo(ES, *MachOObj); 2710eae32dcSDimitry Andric else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get())) 2720eae32dcSDimitry Andric return getELFObjectFileSymbolInfo(ES, *ELFObj); 273753f127fSDimitry Andric else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get())) 274753f127fSDimitry Andric return getCOFFObjectFileSymbolInfo(ES, *COFFObj); 2750eae32dcSDimitry Andric 2760eae32dcSDimitry Andric return getGenericObjectFileSymbolInfo(ES, **Obj); 2770eae32dcSDimitry Andric } 2780eae32dcSDimitry Andric 2790eae32dcSDimitry Andric } // End namespace orc. 2800eae32dcSDimitry Andric } // End namespace llvm. 281