Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/GetDylibInterface.cpp
213799 views
//===-------- GetDylibInterface.cpp - Get interface for real dylib --------===//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/GetDylibInterface.h"910#include "llvm/BinaryFormat/Magic.h"11#include "llvm/Object/MachO.h"12#include "llvm/Object/MachOUniversal.h"13#include "llvm/Object/TapiUniversal.h"1415#define DEBUG_TYPE "orc"1617namespace llvm::orc {1819Expected<SymbolNameSet> getDylibInterfaceFromDylib(ExecutionSession &ES,20Twine Path) {21auto CPUType = MachO::getCPUType(ES.getTargetTriple());22if (!CPUType)23return CPUType.takeError();2425auto CPUSubType = MachO::getCPUSubType(ES.getTargetTriple());26if (!CPUSubType)27return CPUSubType.takeError();2829auto Buf = MemoryBuffer::getFile(Path);30if (!Buf)31return createFileError(Path, Buf.getError());3233auto BinFile = object::createBinary((*Buf)->getMemBufferRef());34if (!BinFile)35return BinFile.takeError();3637std::unique_ptr<object::MachOObjectFile> MachOFile;38if (isa<object::MachOObjectFile>(**BinFile))39MachOFile.reset(dyn_cast<object::MachOObjectFile>(BinFile->release()));40else if (auto *MachOUni =41dyn_cast<object::MachOUniversalBinary>(BinFile->get())) {42for (auto &O : MachOUni->objects()) {43if (O.getCPUType() == *CPUType &&44(O.getCPUSubType() & ~MachO::CPU_SUBTYPE_MASK) == *CPUSubType) {45if (auto Obj = O.getAsObjectFile())46MachOFile = std::move(*Obj);47else48return Obj.takeError();49break;50}51}52if (!MachOFile)53return make_error<StringError>("MachO universal binary at " + Path +54" does not contain a slice for " +55ES.getTargetTriple().str(),56inconvertibleErrorCode());57} else58return make_error<StringError>("File at " + Path + " is not a MachO",59inconvertibleErrorCode());6061if (MachOFile->getHeader().filetype != MachO::MH_DYLIB)62return make_error<StringError>("MachO at " + Path + " is not a dylib",63inconvertibleErrorCode());6465SymbolNameSet Symbols;66for (auto &Sym : MachOFile->symbols()) {67if (auto Name = Sym.getName())68Symbols.insert(ES.intern(*Name));69else70return Name.takeError();71}7273return std::move(Symbols);74}7576Expected<SymbolNameSet> getDylibInterfaceFromTapiFile(ExecutionSession &ES,77Twine Path) {78SymbolNameSet Symbols;7980auto TapiFileBuffer = MemoryBuffer::getFile(Path);81if (!TapiFileBuffer)82return createFileError(Path, TapiFileBuffer.getError());8384auto Tapi =85object::TapiUniversal::create((*TapiFileBuffer)->getMemBufferRef());86if (!Tapi)87return Tapi.takeError();8889auto CPUType = MachO::getCPUType(ES.getTargetTriple());90if (!CPUType)91return CPUType.takeError();9293auto CPUSubType = MachO::getCPUSubType(ES.getTargetTriple());94if (!CPUSubType)95return CPUSubType.takeError();9697auto &IF = (*Tapi)->getInterfaceFile();98auto Interface =99IF.extract(MachO::getArchitectureFromCpuType(*CPUType, *CPUSubType));100if (!Interface)101return Interface.takeError();102103for (auto *Sym : (*Interface)->exports())104Symbols.insert(ES.intern(Sym->getName()));105106return Symbols;107}108109Expected<SymbolNameSet> getDylibInterface(ExecutionSession &ES, Twine Path) {110file_magic Magic;111if (auto EC = identify_magic(Path, Magic))112return createFileError(Path, EC);113114switch (Magic) {115case file_magic::macho_universal_binary:116case file_magic::macho_dynamically_linked_shared_lib:117return getDylibInterfaceFromDylib(ES, Path);118case file_magic::tapi_file:119return getDylibInterfaceFromTapiFile(ES, Path);120default:121return make_error<StringError>("Cannot get interface for " + Path +122" unrecognized file type",123inconvertibleErrorCode());124}125}126127} // namespace llvm::orc128129130