1 //===--- SimpleRemoteEPCUtils.h - Utils for Simple Remote EPC ---*- 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 // Message definitions and other utilities for SimpleRemoteEPC and 10 // SimpleRemoteEPCServer. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H 15 #define LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H 16 17 #include "llvm/ADT/ArrayRef.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ADT/StringMap.h" 20 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" 21 #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h" 22 #include "llvm/Support/Error.h" 23 24 #include <atomic> 25 #include <mutex> 26 #include <string> 27 #include <thread> 28 29 namespace llvm { 30 namespace orc { 31 32 namespace SimpleRemoteEPCDefaultBootstrapSymbolNames { 33 extern const char *ExecutorSessionObjectName; 34 extern const char *DispatchFnName; 35 } // end namespace SimpleRemoteEPCDefaultBootstrapSymbolNames 36 37 enum class SimpleRemoteEPCOpcode : uint8_t { 38 Setup, 39 Hangup, 40 Result, 41 CallWrapper, 42 LastOpC = CallWrapper 43 }; 44 45 struct SimpleRemoteEPCExecutorInfo { 46 std::string TargetTriple; 47 uint64_t PageSize; 48 StringMap<std::vector<char>> BootstrapMap; 49 StringMap<ExecutorAddr> BootstrapSymbols; 50 }; 51 52 using SimpleRemoteEPCArgBytesVector = SmallVector<char, 128>; 53 54 class SimpleRemoteEPCTransportClient { 55 public: 56 enum HandleMessageAction { ContinueSession, EndSession }; 57 58 virtual ~SimpleRemoteEPCTransportClient(); 59 60 /// Handle receipt of a message. 61 /// 62 /// Returns an Error if the message cannot be handled, 'EndSession' if the 63 /// client will not accept any further messages, and 'ContinueSession' 64 /// otherwise. 65 virtual Expected<HandleMessageAction> 66 handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr, 67 SimpleRemoteEPCArgBytesVector ArgBytes) = 0; 68 69 /// Handle a disconnection from the underlying transport. No further messages 70 /// should be sent to handleMessage after this is called. 71 /// Err may contain an Error value indicating unexpected disconnection. This 72 /// allows clients to log such errors, but no attempt should be made at 73 /// recovery (which should be handled inside the transport class, if it is 74 /// supported at all). 75 virtual void handleDisconnect(Error Err) = 0; 76 }; 77 78 class SimpleRemoteEPCTransport { 79 public: 80 virtual ~SimpleRemoteEPCTransport(); 81 82 /// Called during setup of the client to indicate that the client is ready 83 /// to receive messages. 84 /// 85 /// Transport objects should not access the client until this method is 86 /// called. 87 virtual Error start() = 0; 88 89 /// Send a SimpleRemoteEPC message. 90 /// 91 /// This function may be called concurrently. Subclasses should implement 92 /// locking if required for the underlying transport. 93 virtual Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, 94 ExecutorAddr TagAddr, ArrayRef<char> ArgBytes) = 0; 95 96 /// Trigger disconnection from the transport. The implementation should 97 /// respond by calling handleDisconnect on the client once disconnection 98 /// is complete. May be called more than once and from different threads. 99 virtual void disconnect() = 0; 100 }; 101 102 /// Uses read/write on FileDescriptors for transport. 103 class FDSimpleRemoteEPCTransport : public SimpleRemoteEPCTransport { 104 public: 105 /// Create a FDSimpleRemoteEPCTransport using the given FDs for 106 /// reading (InFD) and writing (OutFD). 107 static Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>> 108 Create(SimpleRemoteEPCTransportClient &C, int InFD, int OutFD); 109 110 /// Create a FDSimpleRemoteEPCTransport using the given FD for both 111 /// reading and writing. 112 static Expected<std::unique_ptr<FDSimpleRemoteEPCTransport>> Create(SimpleRemoteEPCTransportClient & C,int FD)113 Create(SimpleRemoteEPCTransportClient &C, int FD) { 114 return Create(C, FD, FD); 115 } 116 117 ~FDSimpleRemoteEPCTransport() override; 118 119 Error start() override; 120 121 Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, 122 ExecutorAddr TagAddr, ArrayRef<char> ArgBytes) override; 123 124 void disconnect() override; 125 126 private: FDSimpleRemoteEPCTransport(SimpleRemoteEPCTransportClient & C,int InFD,int OutFD)127 FDSimpleRemoteEPCTransport(SimpleRemoteEPCTransportClient &C, int InFD, 128 int OutFD) 129 : C(C), InFD(InFD), OutFD(OutFD) {} 130 131 Error readBytes(char *Dst, size_t Size, bool *IsEOF = nullptr); 132 int writeBytes(const char *Src, size_t Size); 133 void listenLoop(); 134 135 std::mutex M; 136 SimpleRemoteEPCTransportClient &C; 137 std::thread ListenerThread; 138 int InFD, OutFD; 139 std::atomic<bool> Disconnected{false}; 140 }; 141 142 struct RemoteSymbolLookupSetElement { 143 std::string Name; 144 bool Required; 145 }; 146 147 using RemoteSymbolLookupSet = std::vector<RemoteSymbolLookupSetElement>; 148 149 struct RemoteSymbolLookup { 150 uint64_t H; 151 RemoteSymbolLookupSet Symbols; 152 }; 153 154 namespace shared { 155 156 using SPSRemoteSymbolLookupSetElement = SPSTuple<SPSString, bool>; 157 158 using SPSRemoteSymbolLookupSet = SPSSequence<SPSRemoteSymbolLookupSetElement>; 159 160 using SPSRemoteSymbolLookup = SPSTuple<uint64_t, SPSRemoteSymbolLookupSet>; 161 162 /// Tuple containing target triple, page size, and bootstrap symbols. 163 using SPSSimpleRemoteEPCExecutorInfo = 164 SPSTuple<SPSString, uint64_t, 165 SPSSequence<SPSTuple<SPSString, SPSSequence<char>>>, 166 SPSSequence<SPSTuple<SPSString, SPSExecutorAddr>>>; 167 168 template <> 169 class SPSSerializationTraits<SPSRemoteSymbolLookupSetElement, 170 RemoteSymbolLookupSetElement> { 171 public: size(const RemoteSymbolLookupSetElement & V)172 static size_t size(const RemoteSymbolLookupSetElement &V) { 173 return SPSArgList<SPSString, bool>::size(V.Name, V.Required); 174 } 175 serialize(SPSOutputBuffer & OB,const RemoteSymbolLookupSetElement & V)176 static size_t serialize(SPSOutputBuffer &OB, 177 const RemoteSymbolLookupSetElement &V) { 178 return SPSArgList<SPSString, bool>::serialize(OB, V.Name, V.Required); 179 } 180 deserialize(SPSInputBuffer & IB,RemoteSymbolLookupSetElement & V)181 static size_t deserialize(SPSInputBuffer &IB, 182 RemoteSymbolLookupSetElement &V) { 183 return SPSArgList<SPSString, bool>::deserialize(IB, V.Name, V.Required); 184 } 185 }; 186 187 template <> 188 class SPSSerializationTraits<SPSRemoteSymbolLookup, RemoteSymbolLookup> { 189 public: size(const RemoteSymbolLookup & V)190 static size_t size(const RemoteSymbolLookup &V) { 191 return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::size(V.H, V.Symbols); 192 } 193 serialize(SPSOutputBuffer & OB,const RemoteSymbolLookup & V)194 static size_t serialize(SPSOutputBuffer &OB, const RemoteSymbolLookup &V) { 195 return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::serialize(OB, V.H, 196 V.Symbols); 197 } 198 deserialize(SPSInputBuffer & IB,RemoteSymbolLookup & V)199 static size_t deserialize(SPSInputBuffer &IB, RemoteSymbolLookup &V) { 200 return SPSArgList<uint64_t, SPSRemoteSymbolLookupSet>::deserialize( 201 IB, V.H, V.Symbols); 202 } 203 }; 204 205 template <> 206 class SPSSerializationTraits<SPSSimpleRemoteEPCExecutorInfo, 207 SimpleRemoteEPCExecutorInfo> { 208 public: size(const SimpleRemoteEPCExecutorInfo & SI)209 static size_t size(const SimpleRemoteEPCExecutorInfo &SI) { 210 return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::size( 211 SI.TargetTriple, SI.PageSize, SI.BootstrapMap, SI.BootstrapSymbols); 212 } 213 serialize(SPSOutputBuffer & OB,const SimpleRemoteEPCExecutorInfo & SI)214 static bool serialize(SPSOutputBuffer &OB, 215 const SimpleRemoteEPCExecutorInfo &SI) { 216 return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::serialize( 217 OB, SI.TargetTriple, SI.PageSize, SI.BootstrapMap, SI.BootstrapSymbols); 218 } 219 deserialize(SPSInputBuffer & IB,SimpleRemoteEPCExecutorInfo & SI)220 static bool deserialize(SPSInputBuffer &IB, SimpleRemoteEPCExecutorInfo &SI) { 221 return SPSSimpleRemoteEPCExecutorInfo::AsArgList ::deserialize( 222 IB, SI.TargetTriple, SI.PageSize, SI.BootstrapMap, SI.BootstrapSymbols); 223 } 224 }; 225 226 using SPSLoadDylibSignature = SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, 227 SPSString, uint64_t); 228 229 using SPSLookupSymbolsSignature = 230 SPSExpected<SPSSequence<SPSSequence<SPSExecutorAddr>>>( 231 SPSExecutorAddr, SPSSequence<SPSRemoteSymbolLookup>); 232 233 } // end namespace shared 234 } // end namespace orc 235 } // end namespace llvm 236 237 #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_SIMPLEREMOTEEPCUTILS_H 238