Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
35266 views
//===------ ObjectFileInterface.cpp - MU interface utils for objects ------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"9#include "llvm/ExecutionEngine/Orc/COFFPlatform.h"10#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"11#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"12#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"13#include "llvm/Object/COFF.h"14#include "llvm/Object/ELFObjectFile.h"15#include "llvm/Object/MachO.h"16#include "llvm/Object/ObjectFile.h"17#include "llvm/Support/Debug.h"18#include <optional>1920#define DEBUG_TYPE "orc"2122namespace llvm {23namespace orc {2425void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES,26StringRef ObjFileName) {27assert(!I.InitSymbol && "I already has an init symbol");28size_t Counter = 0;2930do {31std::string InitSymString;32raw_string_ostream(InitSymString)33<< "$." << ObjFileName << ".__inits." << Counter++;34I.InitSymbol = ES.intern(InitSymString);35} while (I.SymbolFlags.count(I.InitSymbol));3637I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;38}3940static Expected<MaterializationUnit::Interface>41getMachOObjectFileSymbolInfo(ExecutionSession &ES,42const object::MachOObjectFile &Obj) {43MaterializationUnit::Interface I;4445for (auto &Sym : Obj.symbols()) {46Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();47if (!SymFlagsOrErr)48// TODO: Test this error.49return SymFlagsOrErr.takeError();5051// Skip symbols not defined in this object file.52if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)53continue;5455// Skip symbols that are not global.56if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))57continue;5859// Skip symbols that have type SF_File.60if (auto SymType = Sym.getType()) {61if (*SymType == object::SymbolRef::ST_File)62continue;63} else64return SymType.takeError();6566auto Name = Sym.getName();67if (!Name)68return Name.takeError();69auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);70if (!SymFlags)71return SymFlags.takeError();7273// Strip the 'exported' flag from MachO linker-private symbols.74if (Name->starts_with("l"))75*SymFlags &= ~JITSymbolFlags::Exported;7677I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);78}7980for (auto &Sec : Obj.sections()) {81auto SecType = Obj.getSectionType(Sec);82if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {83addInitSymbol(I, ES, Obj.getFileName());84break;85}86auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());87auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));88if (isMachOInitializerSection(SegName, SecName)) {89addInitSymbol(I, ES, Obj.getFileName());90break;91}92}9394return I;95}9697static Expected<MaterializationUnit::Interface>98getELFObjectFileSymbolInfo(ExecutionSession &ES,99const object::ELFObjectFileBase &Obj) {100MaterializationUnit::Interface I;101102for (auto &Sym : Obj.symbols()) {103Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();104if (!SymFlagsOrErr)105// TODO: Test this error.106return SymFlagsOrErr.takeError();107108// Skip symbols not defined in this object file.109if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)110continue;111112// Skip symbols that are not global.113if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))114continue;115116// Skip symbols that have type SF_File.117if (auto SymType = Sym.getType()) {118if (*SymType == object::SymbolRef::ST_File)119continue;120} else121return SymType.takeError();122123auto Name = Sym.getName();124if (!Name)125return Name.takeError();126127auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);128if (!SymFlags)129return SymFlags.takeError();130131// ELF STB_GNU_UNIQUE should map to Weak for ORC.132if (Sym.getBinding() == ELF::STB_GNU_UNIQUE)133*SymFlags |= JITSymbolFlags::Weak;134135I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);136}137138SymbolStringPtr InitSymbol;139for (auto &Sec : Obj.sections()) {140if (auto SecName = Sec.getName()) {141if (isELFInitializerSection(*SecName)) {142addInitSymbol(I, ES, Obj.getFileName());143break;144}145}146}147148return I;149}150151static Expected<MaterializationUnit::Interface>152getCOFFObjectFileSymbolInfo(ExecutionSession &ES,153const object::COFFObjectFile &Obj) {154MaterializationUnit::Interface I;155std::vector<std::optional<object::coff_aux_section_definition>> ComdatDefs(156Obj.getNumberOfSections() + 1);157for (auto &Sym : Obj.symbols()) {158Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();159if (!SymFlagsOrErr)160// TODO: Test this error.161return SymFlagsOrErr.takeError();162163// Handle comdat symbols164auto COFFSym = Obj.getCOFFSymbol(Sym);165bool IsWeak = false;166if (auto *Def = COFFSym.getSectionDefinition()) {167auto Sec = Obj.getSection(COFFSym.getSectionNumber());168if (!Sec)169return Sec.takeError();170if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&171Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {172ComdatDefs[COFFSym.getSectionNumber()] = *Def;173continue;174}175}176if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&177ComdatDefs[COFFSym.getSectionNumber()]) {178auto Def = ComdatDefs[COFFSym.getSectionNumber()];179if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {180IsWeak = true;181}182ComdatDefs[COFFSym.getSectionNumber()] = std::nullopt;183} else {184// Skip symbols not defined in this object file.185if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)186continue;187}188189// Skip symbols that are not global.190if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))191continue;192193// Skip symbols that have type SF_File.194if (auto SymType = Sym.getType()) {195if (*SymType == object::SymbolRef::ST_File)196continue;197} else198return SymType.takeError();199200auto Name = Sym.getName();201if (!Name)202return Name.takeError();203204auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);205if (!SymFlags)206return SymFlags.takeError();207*SymFlags |= JITSymbolFlags::Exported;208209// Weak external is always a function210if (COFFSym.isWeakExternal())211*SymFlags |= JITSymbolFlags::Callable;212213if (IsWeak)214*SymFlags |= JITSymbolFlags::Weak;215216I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);217}218219SymbolStringPtr InitSymbol;220for (auto &Sec : Obj.sections()) {221if (auto SecName = Sec.getName()) {222if (isCOFFInitializerSection(*SecName)) {223addInitSymbol(I, ES, Obj.getFileName());224break;225}226} else227return SecName.takeError();228}229230return I;231}232233Expected<MaterializationUnit::Interface>234getGenericObjectFileSymbolInfo(ExecutionSession &ES,235const object::ObjectFile &Obj) {236MaterializationUnit::Interface I;237238for (auto &Sym : Obj.symbols()) {239Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();240if (!SymFlagsOrErr)241// TODO: Test this error.242return SymFlagsOrErr.takeError();243244// Skip symbols not defined in this object file.245if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)246continue;247248// Skip symbols that are not global.249if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))250continue;251252// Skip symbols that have type SF_File.253if (auto SymType = Sym.getType()) {254if (*SymType == object::SymbolRef::ST_File)255continue;256} else257return SymType.takeError();258259auto Name = Sym.getName();260if (!Name)261return Name.takeError();262263auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);264if (!SymFlags)265return SymFlags.takeError();266267I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);268}269270return I;271}272273Expected<MaterializationUnit::Interface>274getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {275auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);276277if (!Obj)278return Obj.takeError();279280if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj->get()))281return getMachOObjectFileSymbolInfo(ES, *MachOObj);282else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))283return getELFObjectFileSymbolInfo(ES, *ELFObj);284else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))285return getCOFFObjectFileSymbolInfo(ES, *COFFObj);286287return getGenericObjectFileSymbolInfo(ES, **Obj);288}289290} // End namespace orc.291} // End namespace llvm.292293294