//===------ ObjectFileInterface.cpp - MU interface utils for objects ------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h" #include "llvm/ExecutionEngine/Orc/MachOPlatform.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" #define DEBUG_TYPE "orc" namespace llvm { namespace orc { void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES, StringRef ObjFileName) { assert(!I.InitSymbol && "I already has an init symbol"); size_t Counter = 0; do { std::string InitSymString; raw_string_ostream(InitSymString) << "$." << ObjFileName << ".__inits." << Counter++; I.InitSymbol = ES.intern(InitSymString); } while (I.SymbolFlags.count(I.InitSymbol)); I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly; } static Expected getMachOObjectFileSymbolInfo(ExecutionSession &ES, const object::MachOObjectFile &Obj) { MaterializationUnit::Interface I; for (auto &Sym : Obj.symbols()) { Expected SymFlagsOrErr = Sym.getFlags(); if (!SymFlagsOrErr) // TODO: Test this error. return SymFlagsOrErr.takeError(); // Skip symbols not defined in this object file. if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) continue; // Skip symbols that are not global. if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) continue; // Skip symbols that have type SF_File. if (auto SymType = Sym.getType()) { if (*SymType == object::SymbolRef::ST_File) continue; } else return SymType.takeError(); auto Name = Sym.getName(); if (!Name) return Name.takeError(); auto InternedName = ES.intern(*Name); auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); if (!SymFlags) return SymFlags.takeError(); // Strip the 'exported' flag from MachO linker-private symbols. if (Name->startswith("l")) *SymFlags &= ~JITSymbolFlags::Exported; I.SymbolFlags[InternedName] = std::move(*SymFlags); } for (auto &Sec : Obj.sections()) { auto SecType = Obj.getSectionType(Sec); if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) { addInitSymbol(I, ES, Obj.getFileName()); break; } auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl()); auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl())); if (MachOPlatform::isInitializerSection(SegName, SecName)) { addInitSymbol(I, ES, Obj.getFileName()); break; } } return I; } static Expected getELFObjectFileSymbolInfo(ExecutionSession &ES, const object::ELFObjectFileBase &Obj) { MaterializationUnit::Interface I; for (auto &Sym : Obj.symbols()) { Expected SymFlagsOrErr = Sym.getFlags(); if (!SymFlagsOrErr) // TODO: Test this error. return SymFlagsOrErr.takeError(); // Skip symbols not defined in this object file. if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) continue; // Skip symbols that are not global. if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) continue; // Skip symbols that have type SF_File. if (auto SymType = Sym.getType()) { if (*SymType == object::SymbolRef::ST_File) continue; } else return SymType.takeError(); auto Name = Sym.getName(); if (!Name) return Name.takeError(); auto InternedName = ES.intern(*Name); auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); if (!SymFlags) return SymFlags.takeError(); // ELF STB_GNU_UNIQUE should map to Weak for ORC. if (Sym.getBinding() == ELF::STB_GNU_UNIQUE) *SymFlags |= JITSymbolFlags::Weak; I.SymbolFlags[InternedName] = std::move(*SymFlags); } SymbolStringPtr InitSymbol; for (auto &Sec : Obj.sections()) { if (auto SecName = Sec.getName()) { if (ELFNixPlatform::isInitializerSection(*SecName)) { addInitSymbol(I, ES, Obj.getFileName()); break; } } } return I; } Expected getGenericObjectFileSymbolInfo(ExecutionSession &ES, const object::ObjectFile &Obj) { MaterializationUnit::Interface I; for (auto &Sym : Obj.symbols()) { Expected SymFlagsOrErr = Sym.getFlags(); if (!SymFlagsOrErr) // TODO: Test this error. return SymFlagsOrErr.takeError(); // Skip symbols not defined in this object file. if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) continue; // Skip symbols that are not global. if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) continue; // Skip symbols that have type SF_File. if (auto SymType = Sym.getType()) { if (*SymType == object::SymbolRef::ST_File) continue; } else return SymType.takeError(); auto Name = Sym.getName(); if (!Name) return Name.takeError(); auto InternedName = ES.intern(*Name); auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); if (!SymFlags) return SymFlags.takeError(); I.SymbolFlags[InternedName] = std::move(*SymFlags); } return I; } Expected getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) { auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); if (!Obj) return Obj.takeError(); if (auto *MachOObj = dyn_cast(Obj->get())) return getMachOObjectFileSymbolInfo(ES, *MachOObj); else if (auto *ELFObj = dyn_cast(Obj->get())) return getELFObjectFileSymbolInfo(ES, *ELFObj); return getGenericObjectFileSymbolInfo(ES, **Obj); } } // End namespace orc. } // End namespace llvm.