1//===-- RemoteJITUtils.h - Utilities for remote-JITing with LLI -*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// Utilities for remote-JITing with LLI. 10// 11//===----------------------------------------------------------------------===// 12 13#ifndef LLVM_TOOLS_LLI_REMOTEJITUTILS_H 14#define LLVM_TOOLS_LLI_REMOTEJITUTILS_H 15 16#include "llvm/ExecutionEngine/Orc/RPC/RawByteChannel.h" 17#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" 18#include <mutex> 19 20#if !defined(_MSC_VER) && !defined(__MINGW32__) 21#include <unistd.h> 22#else 23#include <io.h> 24#endif 25 26/// RPC channel that reads from and writes from file descriptors. 27class FDRawChannel final : public llvm::orc::rpc::RawByteChannel { 28public: 29 FDRawChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {} 30 31 llvm::Error readBytes(char *Dst, unsigned Size) override { 32 assert(Dst && "Attempt to read into null."); 33 ssize_t Completed = 0; 34 while (Completed < static_cast<ssize_t>(Size)) { 35 ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed); 36 if (Read <= 0) { 37 auto ErrNo = errno; 38 if (ErrNo == EAGAIN || ErrNo == EINTR) 39 continue; 40 else 41 return llvm::errorCodeToError( 42 std::error_code(errno, std::generic_category())); 43 } 44 Completed += Read; 45 } 46 return llvm::Error::success(); 47 } 48 49 llvm::Error appendBytes(const char *Src, unsigned Size) override { 50 assert(Src && "Attempt to append from null."); 51 ssize_t Completed = 0; 52 while (Completed < static_cast<ssize_t>(Size)) { 53 ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed); 54 if (Written < 0) { 55 auto ErrNo = errno; 56 if (ErrNo == EAGAIN || ErrNo == EINTR) 57 continue; 58 else 59 return llvm::errorCodeToError( 60 std::error_code(errno, std::generic_category())); 61 } 62 Completed += Written; 63 } 64 return llvm::Error::success(); 65 } 66 67 llvm::Error send() override { return llvm::Error::success(); } 68 69private: 70 int InFD, OutFD; 71}; 72 73// launch the remote process (see lli.cpp) and return a channel to it. 74std::unique_ptr<FDRawChannel> launchRemote(); 75 76namespace llvm { 77 78// ForwardingMM - Adapter to connect MCJIT to Orc's Remote 79// memory manager. 80class ForwardingMemoryManager : public llvm::RTDyldMemoryManager { 81public: 82 void setMemMgr(std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr) { 83 this->MemMgr = std::move(MemMgr); 84 } 85 86 void setResolver(std::shared_ptr<LegacyJITSymbolResolver> Resolver) { 87 this->Resolver = std::move(Resolver); 88 } 89 90 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, 91 unsigned SectionID, 92 StringRef SectionName) override { 93 return MemMgr->allocateCodeSection(Size, Alignment, SectionID, SectionName); 94 } 95 96 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 97 unsigned SectionID, StringRef SectionName, 98 bool IsReadOnly) override { 99 return MemMgr->allocateDataSection(Size, Alignment, SectionID, SectionName, 100 IsReadOnly); 101 } 102 103 void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, 104 uintptr_t RODataSize, uint32_t RODataAlign, 105 uintptr_t RWDataSize, 106 uint32_t RWDataAlign) override { 107 MemMgr->reserveAllocationSpace(CodeSize, CodeAlign, RODataSize, RODataAlign, 108 RWDataSize, RWDataAlign); 109 } 110 111 bool needsToReserveAllocationSpace() override { 112 return MemMgr->needsToReserveAllocationSpace(); 113 } 114 115 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, 116 size_t Size) override { 117 MemMgr->registerEHFrames(Addr, LoadAddr, Size); 118 } 119 120 void deregisterEHFrames() override { 121 MemMgr->deregisterEHFrames(); 122 } 123 124 bool finalizeMemory(std::string *ErrMsg = nullptr) override { 125 return MemMgr->finalizeMemory(ErrMsg); 126 } 127 128 void notifyObjectLoaded(RuntimeDyld &RTDyld, 129 const object::ObjectFile &Obj) override { 130 MemMgr->notifyObjectLoaded(RTDyld, Obj); 131 } 132 133 // Don't hide the sibling notifyObjectLoaded from RTDyldMemoryManager. 134 using RTDyldMemoryManager::notifyObjectLoaded; 135 136 JITSymbol findSymbol(const std::string &Name) override { 137 return Resolver->findSymbol(Name); 138 } 139 140 JITSymbol 141 findSymbolInLogicalDylib(const std::string &Name) override { 142 return Resolver->findSymbolInLogicalDylib(Name); 143 } 144 145private: 146 std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr; 147 std::shared_ptr<LegacyJITSymbolResolver> Resolver; 148}; 149} 150 151#endif 152