Home | History | Annotate | Line # | Download | only in Orc
      1 //===--- TargetProcessControl.h - Target process control APIs ---*- 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 interacting with target processes.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESSCONTROL_H
     14 #define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESSCONTROL_H
     15 
     16 #include "llvm/ADT/Optional.h"
     17 #include "llvm/ADT/StringRef.h"
     18 #include "llvm/ADT/Triple.h"
     19 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
     20 #include "llvm/ExecutionEngine/Orc/Core.h"
     21 #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
     22 #include "llvm/Support/DynamicLibrary.h"
     23 #include "llvm/Support/MSVCErrorWorkarounds.h"
     24 
     25 #include <future>
     26 #include <vector>
     27 
     28 namespace llvm {
     29 namespace orc {
     30 
     31 /// TargetProcessControl supports interaction with a JIT target process.
     32 class TargetProcessControl {
     33 public:
     34   /// APIs for manipulating memory in the target process.
     35   class MemoryAccess {
     36   public:
     37     /// Callback function for asynchronous writes.
     38     using WriteResultFn = unique_function<void(Error)>;
     39 
     40     virtual ~MemoryAccess();
     41 
     42     virtual void writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,
     43                              WriteResultFn OnWriteComplete) = 0;
     44 
     45     virtual void writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws,
     46                               WriteResultFn OnWriteComplete) = 0;
     47 
     48     virtual void writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws,
     49                               WriteResultFn OnWriteComplete) = 0;
     50 
     51     virtual void writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws,
     52                               WriteResultFn OnWriteComplete) = 0;
     53 
     54     virtual void writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws,
     55                               WriteResultFn OnWriteComplete) = 0;
     56 
     57     Error writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws) {
     58       std::promise<MSVCPError> ResultP;
     59       auto ResultF = ResultP.get_future();
     60       writeUInt8s(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); });
     61       return ResultF.get();
     62     }
     63 
     64     Error writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws) {
     65       std::promise<MSVCPError> ResultP;
     66       auto ResultF = ResultP.get_future();
     67       writeUInt16s(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); });
     68       return ResultF.get();
     69     }
     70 
     71     Error writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws) {
     72       std::promise<MSVCPError> ResultP;
     73       auto ResultF = ResultP.get_future();
     74       writeUInt32s(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); });
     75       return ResultF.get();
     76     }
     77 
     78     Error writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws) {
     79       std::promise<MSVCPError> ResultP;
     80       auto ResultF = ResultP.get_future();
     81       writeUInt64s(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); });
     82       return ResultF.get();
     83     }
     84 
     85     Error writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws) {
     86       std::promise<MSVCPError> ResultP;
     87       auto ResultF = ResultP.get_future();
     88       writeBuffers(Ws, [&](Error Err) { ResultP.set_value(std::move(Err)); });
     89       return ResultF.get();
     90     }
     91   };
     92 
     93   /// A pair of a dylib and a set of symbols to be looked up.
     94   struct LookupRequest {
     95     LookupRequest(tpctypes::DylibHandle Handle, const SymbolLookupSet &Symbols)
     96         : Handle(Handle), Symbols(Symbols) {}
     97     tpctypes::DylibHandle Handle;
     98     const SymbolLookupSet &Symbols;
     99   };
    100 
    101   virtual ~TargetProcessControl();
    102 
    103   /// Intern a symbol name in the SymbolStringPool.
    104   SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
    105 
    106   /// Return a shared pointer to the SymbolStringPool for this instance.
    107   std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; }
    108 
    109   /// Return the Triple for the target process.
    110   const Triple &getTargetTriple() const { return TargetTriple; }
    111 
    112   /// Get the page size for the target process.
    113   unsigned getPageSize() const { return PageSize; }
    114 
    115   /// Return a MemoryAccess object for the target process.
    116   MemoryAccess &getMemoryAccess() const { return *MemAccess; }
    117 
    118   /// Return a JITLinkMemoryManager for the target process.
    119   jitlink::JITLinkMemoryManager &getMemMgr() const { return *MemMgr; }
    120 
    121   /// Load the dynamic library at the given path and return a handle to it.
    122   /// If LibraryPath is null this function will return the global handle for
    123   /// the target process.
    124   virtual Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) = 0;
    125 
    126   /// Search for symbols in the target process.
    127   ///
    128   /// The result of the lookup is a 2-dimentional array of target addresses
    129   /// that correspond to the lookup order. If a required symbol is not
    130   /// found then this method will return an error. If a weakly referenced
    131   /// symbol is not found then it be assigned a '0' value in the result.
    132   /// that correspond to the lookup order.
    133   virtual Expected<std::vector<tpctypes::LookupResult>>
    134   lookupSymbols(ArrayRef<LookupRequest> Request) = 0;
    135 
    136   /// Run function with a main-like signature.
    137   virtual Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr,
    138                                       ArrayRef<std::string> Args) = 0;
    139 
    140   /// Run a wrapper function with signature:
    141   ///
    142   /// \code{.cpp}
    143   ///   CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size);
    144   /// \endcode{.cpp}
    145   ///
    146   virtual Expected<tpctypes::WrapperFunctionResult>
    147   runWrapper(JITTargetAddress WrapperFnAddr, ArrayRef<uint8_t> ArgBuffer) = 0;
    148 
    149   /// Disconnect from the target process.
    150   ///
    151   /// This should be called after the JIT session is shut down.
    152   virtual Error disconnect() = 0;
    153 
    154 protected:
    155   TargetProcessControl(std::shared_ptr<SymbolStringPool> SSP)
    156       : SSP(std::move(SSP)) {}
    157 
    158   std::shared_ptr<SymbolStringPool> SSP;
    159   Triple TargetTriple;
    160   unsigned PageSize = 0;
    161   MemoryAccess *MemAccess = nullptr;
    162   jitlink::JITLinkMemoryManager *MemMgr = nullptr;
    163 };
    164 
    165 /// A TargetProcessControl implementation targeting the current process.
    166 class SelfTargetProcessControl : public TargetProcessControl,
    167                                  private TargetProcessControl::MemoryAccess {
    168 public:
    169   SelfTargetProcessControl(
    170       std::shared_ptr<SymbolStringPool> SSP, Triple TargetTriple,
    171       unsigned PageSize, std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr);
    172 
    173   /// Create a SelfTargetProcessControl with the given memory manager.
    174   /// If no memory manager is given a jitlink::InProcessMemoryManager will
    175   /// be used by default.
    176   static Expected<std::unique_ptr<SelfTargetProcessControl>>
    177   Create(std::shared_ptr<SymbolStringPool> SSP,
    178          std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr = nullptr);
    179 
    180   Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override;
    181 
    182   Expected<std::vector<tpctypes::LookupResult>>
    183   lookupSymbols(ArrayRef<LookupRequest> Request) override;
    184 
    185   Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr,
    186                               ArrayRef<std::string> Args) override;
    187 
    188   Expected<tpctypes::WrapperFunctionResult>
    189   runWrapper(JITTargetAddress WrapperFnAddr,
    190              ArrayRef<uint8_t> ArgBuffer) override;
    191 
    192   Error disconnect() override;
    193 
    194 private:
    195   void writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,
    196                    WriteResultFn OnWriteComplete) override;
    197 
    198   void writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws,
    199                     WriteResultFn OnWriteComplete) override;
    200 
    201   void writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws,
    202                     WriteResultFn OnWriteComplete) override;
    203 
    204   void writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws,
    205                     WriteResultFn OnWriteComplete) override;
    206 
    207   void writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws,
    208                     WriteResultFn OnWriteComplete) override;
    209 
    210   std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
    211   char GlobalManglingPrefix = 0;
    212   std::vector<std::unique_ptr<sys::DynamicLibrary>> DynamicLibraries;
    213 };
    214 
    215 } // end namespace orc
    216 } // end namespace llvm
    217 
    218 #endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESSCONTROL_H
    219