1 //===- RTDyldObjectLinkingLayer.h - RTDyld-based jit linking ---*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Contains the definition for an RTDyld-based, in-process object linking layer. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H 15 #define LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H 16 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/StringMap.h" 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/ExecutionEngine/JITSymbol.h" 21 #include "llvm/ExecutionEngine/RuntimeDyld.h" 22 #include "llvm/Object/ObjectFile.h" 23 #include "llvm/Support/Error.h" 24 #include <algorithm> 25 #include <cassert> 26 #include <functional> 27 #include <list> 28 #include <memory> 29 #include <string> 30 #include <utility> 31 #include <vector> 32 33 namespace llvm { 34 namespace orc { 35 36 class RTDyldObjectLinkingLayerBase { 37 public: 38 39 using ObjectPtr = 40 std::shared_ptr<object::OwningBinary<object::ObjectFile>>; 41 42 protected: 43 44 /// @brief Holds an object to be allocated/linked as a unit in the JIT. 45 /// 46 /// An instance of this class will be created for each object added 47 /// via JITObjectLayer::addObject. Deleting the instance (via 48 /// removeObject) frees its memory, removing all symbol definitions that 49 /// had been provided by this instance. Higher level layers are responsible 50 /// for taking any action required to handle the missing symbols. 51 class LinkedObject { 52 public: 53 LinkedObject() = default; 54 LinkedObject(const LinkedObject&) = delete; 55 void operator=(const LinkedObject&) = delete; 56 virtual ~LinkedObject() = default; 57 58 virtual void finalize() = 0; 59 60 virtual JITSymbol::GetAddressFtor 61 getSymbolMaterializer(std::string Name) = 0; 62 63 virtual void mapSectionAddress(const void *LocalAddress, 64 JITTargetAddress TargetAddr) const = 0; 65 66 JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) { 67 auto SymEntry = SymbolTable.find(Name); 68 if (SymEntry == SymbolTable.end()) 69 return nullptr; 70 if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly) 71 return nullptr; 72 if (!Finalized) 73 return JITSymbol(getSymbolMaterializer(Name), 74 SymEntry->second.getFlags()); 75 return JITSymbol(SymEntry->second); 76 } 77 78 protected: 79 StringMap<JITEvaluatedSymbol> SymbolTable; 80 bool Finalized = false; 81 }; 82 83 using LinkedObjectListT = std::list<std::unique_ptr<LinkedObject>>; 84 85 public: 86 /// @brief Handle to a loaded object. 87 using ObjHandleT = LinkedObjectListT::iterator; 88 }; 89 90 /// @brief Bare bones object linking layer. 91 /// 92 /// This class is intended to be used as the base layer for a JIT. It allows 93 /// object files to be loaded into memory, linked, and the addresses of their 94 /// symbols queried. All objects added to this layer can see each other's 95 /// symbols. 96 class RTDyldObjectLinkingLayer : public RTDyldObjectLinkingLayerBase { 97 public: 98 99 using RTDyldObjectLinkingLayerBase::ObjectPtr; 100 101 /// @brief Functor for receiving object-loaded notifications. 102 using NotifyLoadedFtor = 103 std::function<void(ObjHandleT, const ObjectPtr &Obj, 104 const RuntimeDyld::LoadedObjectInfo &)>; 105 106 /// @brief Functor for receiving finalization notifications. 107 using NotifyFinalizedFtor = std::function<void(ObjHandleT)>; 108 109 private: 110 111 112 template <typename MemoryManagerPtrT, typename SymbolResolverPtrT, 113 typename FinalizerFtor> 114 class ConcreteLinkedObject : public LinkedObject { 115 public: 116 ConcreteLinkedObject(ObjectPtr Obj, MemoryManagerPtrT MemMgr, 117 SymbolResolverPtrT Resolver, 118 FinalizerFtor Finalizer, 119 bool ProcessAllSections) 120 : MemMgr(std::move(MemMgr)), 121 PFC(llvm::make_unique<PreFinalizeContents>(std::move(Obj), 122 std::move(Resolver), 123 std::move(Finalizer), 124 ProcessAllSections)) { 125 buildInitialSymbolTable(PFC->Obj); 126 } 127 128 ~ConcreteLinkedObject() override { 129 MemMgr->deregisterEHFrames(); 130 } 131 132 void setHandle(ObjHandleT H) { 133 PFC->Handle = H; 134 } 135 136 void finalize() override { 137 assert(PFC && "mapSectionAddress called on finalized LinkedObject"); 138 139 RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver); 140 RTDyld.setProcessAllSections(PFC->ProcessAllSections); 141 PFC->RTDyld = &RTDyld; 142 143 this->Finalized = true; 144 PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Obj), 145 [&]() { 146 this->updateSymbolTable(RTDyld); 147 }); 148 149 // Release resources. 150 PFC = nullptr; 151 } 152 153 JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override { 154 return 155 [this, Name]() { 156 // The symbol may be materialized between the creation of this lambda 157 // and its execution, so we need to double check. 158 if (!this->Finalized) 159 this->finalize(); 160 return this->getSymbol(Name, false).getAddress(); 161 }; 162 } 163 164 void mapSectionAddress(const void *LocalAddress, 165 JITTargetAddress TargetAddr) const override { 166 assert(PFC && "mapSectionAddress called on finalized LinkedObject"); 167 assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObject"); 168 PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr); 169 } 170 171 private: 172 173 void buildInitialSymbolTable(const ObjectPtr &Obj) { 174 for (auto &Symbol : Obj->getBinary()->symbols()) { 175 if (Symbol.getFlags() & object::SymbolRef::SF_Undefined) 176 continue; 177 Expected<StringRef> SymbolName = Symbol.getName(); 178 // FIXME: Raise an error for bad symbols. 179 if (!SymbolName) { 180 consumeError(SymbolName.takeError()); 181 continue; 182 } 183 auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol); 184 SymbolTable.insert( 185 std::make_pair(*SymbolName, JITEvaluatedSymbol(0, Flags))); 186 } 187 } 188 189 void updateSymbolTable(const RuntimeDyld &RTDyld) { 190 for (auto &SymEntry : SymbolTable) 191 SymEntry.second = RTDyld.getSymbol(SymEntry.first()); 192 } 193 194 // Contains the information needed prior to finalization: the object files, 195 // memory manager, resolver, and flags needed for RuntimeDyld. 196 struct PreFinalizeContents { 197 PreFinalizeContents(ObjectPtr Obj, SymbolResolverPtrT Resolver, 198 FinalizerFtor Finalizer, bool ProcessAllSections) 199 : Obj(std::move(Obj)), Resolver(std::move(Resolver)), 200 Finalizer(std::move(Finalizer)), 201 ProcessAllSections(ProcessAllSections) {} 202 203 ObjectPtr Obj; 204 SymbolResolverPtrT Resolver; 205 FinalizerFtor Finalizer; 206 bool ProcessAllSections; 207 ObjHandleT Handle; 208 RuntimeDyld *RTDyld; 209 }; 210 211 MemoryManagerPtrT MemMgr; 212 std::unique_ptr<PreFinalizeContents> PFC; 213 }; 214 215 template <typename MemoryManagerPtrT, typename SymbolResolverPtrT, 216 typename FinalizerFtor> 217 std::unique_ptr< 218 ConcreteLinkedObject<MemoryManagerPtrT, SymbolResolverPtrT, FinalizerFtor>> 219 createLinkedObject(ObjectPtr Obj, MemoryManagerPtrT MemMgr, 220 SymbolResolverPtrT Resolver, 221 FinalizerFtor Finalizer, 222 bool ProcessAllSections) { 223 using LOS = ConcreteLinkedObject<MemoryManagerPtrT, SymbolResolverPtrT, 224 FinalizerFtor>; 225 return llvm::make_unique<LOS>(std::move(Obj), std::move(MemMgr), 226 std::move(Resolver), std::move(Finalizer), 227 ProcessAllSections); 228 } 229 230 public: 231 232 /// @brief Functor for creating memory managers. 233 using MemoryManagerGetter = 234 std::function<std::shared_ptr<RuntimeDyld::MemoryManager>()>; 235 236 /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded, 237 /// and NotifyFinalized functors. 238 RTDyldObjectLinkingLayer( 239 MemoryManagerGetter GetMemMgr, 240 NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), 241 NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()) 242 : GetMemMgr(GetMemMgr), 243 NotifyLoaded(std::move(NotifyLoaded)), 244 NotifyFinalized(std::move(NotifyFinalized)), 245 ProcessAllSections(false) {} 246 247 /// @brief Set the 'ProcessAllSections' flag. 248 /// 249 /// If set to true, all sections in each object file will be allocated using 250 /// the memory manager, rather than just the sections required for execution. 251 /// 252 /// This is kludgy, and may be removed in the future. 253 void setProcessAllSections(bool ProcessAllSections) { 254 this->ProcessAllSections = ProcessAllSections; 255 } 256 257 /// @brief Add an object to the JIT. 258 /// 259 /// @return A handle that can be used to refer to the loaded object (for 260 /// symbol searching, finalization, freeing memory, etc.). 261 Expected<ObjHandleT> addObject(ObjectPtr Obj, 262 std::shared_ptr<JITSymbolResolver> Resolver) { 263 auto Finalizer = [&](ObjHandleT H, RuntimeDyld &RTDyld, 264 const ObjectPtr &ObjToLoad, 265 std::function<void()> LOSHandleLoad) { 266 std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info = 267 RTDyld.loadObject(*ObjToLoad->getBinary()); 268 269 LOSHandleLoad(); 270 271 if (this->NotifyLoaded) 272 this->NotifyLoaded(H, ObjToLoad, *Info); 273 274 RTDyld.finalizeWithMemoryManagerLocking(); 275 276 if (this->NotifyFinalized) 277 this->NotifyFinalized(H); 278 }; 279 280 auto LO = 281 createLinkedObject(std::move(Obj), GetMemMgr(), 282 std::move(Resolver), std::move(Finalizer), 283 ProcessAllSections); 284 // LOS is an owning-ptr. Keep a non-owning one so that we can set the handle 285 // below. 286 auto *LOPtr = LO.get(); 287 288 ObjHandleT Handle = LinkedObjList.insert(LinkedObjList.end(), std::move(LO)); 289 LOPtr->setHandle(Handle); 290 291 return Handle; 292 } 293 294 /// @brief Remove the object associated with handle H. 295 /// 296 /// All memory allocated for the object will be freed, and the sections and 297 /// symbols it provided will no longer be available. No attempt is made to 298 /// re-emit the missing symbols, and any use of these symbols (directly or 299 /// indirectly) will result in undefined behavior. If dependence tracking is 300 /// required to detect or resolve such issues it should be added at a higher 301 /// layer. 302 Error removeObject(ObjHandleT H) { 303 // How do we invalidate the symbols in H? 304 LinkedObjList.erase(H); 305 return Error::success(); 306 } 307 308 /// @brief Search for the given named symbol. 309 /// @param Name The name of the symbol to search for. 310 /// @param ExportedSymbolsOnly If true, search only for exported symbols. 311 /// @return A handle for the given named symbol, if it exists. 312 JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { 313 for (auto I = LinkedObjList.begin(), E = LinkedObjList.end(); I != E; 314 ++I) 315 if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly)) 316 return Symbol; 317 318 return nullptr; 319 } 320 321 /// @brief Search for the given named symbol in the context of the loaded 322 /// object represented by the handle H. 323 /// @param H The handle for the object to search in. 324 /// @param Name The name of the symbol to search for. 325 /// @param ExportedSymbolsOnly If true, search only for exported symbols. 326 /// @return A handle for the given named symbol, if it is found in the 327 /// given object. 328 JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, 329 bool ExportedSymbolsOnly) { 330 return (*H)->getSymbol(Name, ExportedSymbolsOnly); 331 } 332 333 /// @brief Map section addresses for the object associated with the handle H. 334 void mapSectionAddress(ObjHandleT H, const void *LocalAddress, 335 JITTargetAddress TargetAddr) { 336 (*H)->mapSectionAddress(LocalAddress, TargetAddr); 337 } 338 339 /// @brief Immediately emit and finalize the object represented by the given 340 /// handle. 341 /// @param H Handle for object to emit/finalize. 342 Error emitAndFinalize(ObjHandleT H) { 343 (*H)->finalize(); 344 return Error::success(); 345 } 346 347 private: 348 349 LinkedObjectListT LinkedObjList; 350 MemoryManagerGetter GetMemMgr; 351 NotifyLoadedFtor NotifyLoaded; 352 NotifyFinalizedFtor NotifyFinalized; 353 bool ProcessAllSections = false; 354 }; 355 356 } // end namespace orc 357 } // end namespace llvm 358 359 #endif // LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H 360