Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 14 | pmbaty | 1 | //===- RuntimeDyld.h - Run-time dynamic linker for MC-JIT -------*- 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 | // Interface for the runtime dynamic linker facilities of the MC-JIT. | ||
| 10 | // | ||
| 11 | //===----------------------------------------------------------------------===// | ||
| 12 | |||
| 13 | #ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H | ||
| 14 | #define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H | ||
| 15 | |||
| 16 | #include "llvm/ADT/FunctionExtras.h" | ||
| 17 | #include "llvm/ADT/STLExtras.h" | ||
| 18 | #include "llvm/ADT/StringRef.h" | ||
| 19 | #include "llvm/DebugInfo/DIContext.h" | ||
| 20 | #include "llvm/ExecutionEngine/JITSymbol.h" | ||
| 21 | #include "llvm/Object/ObjectFile.h" | ||
| 22 | #include "llvm/Support/Error.h" | ||
| 23 | #include <algorithm> | ||
| 24 | #include <cassert> | ||
| 25 | #include <cstddef> | ||
| 26 | #include <cstdint> | ||
| 27 | #include <map> | ||
| 28 | #include <memory> | ||
| 29 | #include <string> | ||
| 30 | #include <system_error> | ||
| 31 | |||
| 32 | namespace llvm { | ||
| 33 | |||
| 34 | namespace object { | ||
| 35 | |||
| 36 | template <typename T> class OwningBinary; | ||
| 37 | |||
| 38 | } // end namespace object | ||
| 39 | |||
| 40 | /// Base class for errors originating in RuntimeDyld, e.g. missing relocation | ||
| 41 | /// support. | ||
| 42 | class RuntimeDyldError : public ErrorInfo<RuntimeDyldError> { | ||
| 43 | public: | ||
| 44 | static char ID; | ||
| 45 | |||
| 46 | RuntimeDyldError(std::string ErrMsg) : ErrMsg(std::move(ErrMsg)) {} | ||
| 47 | |||
| 48 | void log(raw_ostream &OS) const override; | ||
| 49 | const std::string &getErrorMessage() const { return ErrMsg; } | ||
| 50 | std::error_code convertToErrorCode() const override; | ||
| 51 | |||
| 52 | private: | ||
| 53 | std::string ErrMsg; | ||
| 54 | }; | ||
| 55 | |||
| 56 | class RuntimeDyldImpl; | ||
| 57 | |||
| 58 | class RuntimeDyld { | ||
| 59 | public: | ||
| 60 |   // Change the address associated with a section when resolving relocations. | ||
| 61 |   // Any relocations already associated with the symbol will be re-resolved. | ||
| 62 | void reassignSectionAddress(unsigned SectionID, uint64_t Addr); | ||
| 63 | |||
| 64 | using NotifyStubEmittedFunction = std::function<void( | ||
| 65 | StringRef FileName, StringRef SectionName, StringRef SymbolName, | ||
| 66 | unsigned SectionID, uint32_t StubOffset)>; | ||
| 67 | |||
| 68 |   /// Information about the loaded object. | ||
| 69 | class LoadedObjectInfo : public llvm::LoadedObjectInfo { | ||
| 70 | friend class RuntimeDyldImpl; | ||
| 71 | |||
| 72 | public: | ||
| 73 | using ObjSectionToIDMap = std::map<object::SectionRef, unsigned>; | ||
| 74 | |||
| 75 | LoadedObjectInfo(RuntimeDyldImpl &RTDyld, ObjSectionToIDMap ObjSecToIDMap) | ||
| 76 | : RTDyld(RTDyld), ObjSecToIDMap(std::move(ObjSecToIDMap)) {} | ||
| 77 | |||
| 78 | virtual object::OwningBinary<object::ObjectFile> | ||
| 79 | getObjectForDebug(const object::ObjectFile &Obj) const = 0; | ||
| 80 | |||
| 81 |     uint64_t | ||
| 82 | getSectionLoadAddress(const object::SectionRef &Sec) const override; | ||
| 83 | |||
| 84 | protected: | ||
| 85 | virtual void anchor(); | ||
| 86 | |||
| 87 | RuntimeDyldImpl &RTDyld; | ||
| 88 |     ObjSectionToIDMap ObjSecToIDMap; | ||
| 89 | }; | ||
| 90 | |||
| 91 |   /// Memory Management. | ||
| 92 | class MemoryManager { | ||
| 93 | friend class RuntimeDyld; | ||
| 94 | |||
| 95 | public: | ||
| 96 | MemoryManager() = default; | ||
| 97 | virtual ~MemoryManager() = default; | ||
| 98 | |||
| 99 |     /// Allocate a memory block of (at least) the given size suitable for | ||
| 100 |     /// executable code. The SectionID is a unique identifier assigned by the | ||
| 101 |     /// RuntimeDyld instance, and optionally recorded by the memory manager to | ||
| 102 |     /// access a loaded section. | ||
| 103 | virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, | ||
| 104 |                                          unsigned SectionID, | ||
| 105 | StringRef SectionName) = 0; | ||
| 106 | |||
| 107 |     /// Allocate a memory block of (at least) the given size suitable for data. | ||
| 108 |     /// The SectionID is a unique identifier assigned by the JIT engine, and | ||
| 109 |     /// optionally recorded by the memory manager to access a loaded section. | ||
| 110 | virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, | ||
| 111 |                                          unsigned SectionID, | ||
| 112 | StringRef SectionName, | ||
| 113 | bool IsReadOnly) = 0; | ||
| 114 | |||
| 115 |     /// An allocated TLS section | ||
| 116 | struct TLSSection { | ||
| 117 |       /// The pointer to the initialization image | ||
| 118 | uint8_t *InitializationImage; | ||
| 119 |       /// The TLS offset | ||
| 120 | intptr_t Offset; | ||
| 121 | }; | ||
| 122 | |||
| 123 |     /// Allocate a memory block of (at least) the given size to be used for | ||
| 124 |     /// thread-local storage (TLS). | ||
| 125 | virtual TLSSection allocateTLSSection(uintptr_t Size, unsigned Alignment, | ||
| 126 |                                           unsigned SectionID, | ||
| 127 | StringRef SectionName); | ||
| 128 | |||
| 129 |     /// Inform the memory manager about the total amount of memory required to | ||
| 130 |     /// allocate all sections to be loaded: | ||
| 131 |     /// \p CodeSize - the total size of all code sections | ||
| 132 |     /// \p DataSizeRO - the total size of all read-only data sections | ||
| 133 |     /// \p DataSizeRW - the total size of all read-write data sections | ||
| 134 |     /// | ||
| 135 |     /// Note that by default the callback is disabled. To enable it | ||
| 136 |     /// redefine the method needsToReserveAllocationSpace to return true. | ||
| 137 | virtual void reserveAllocationSpace(uintptr_t CodeSize, Align CodeAlign, | ||
| 138 |                                         uintptr_t RODataSize, Align RODataAlign, | ||
| 139 |                                         uintptr_t RWDataSize, | ||
| 140 | Align RWDataAlign) {} | ||
| 141 | |||
| 142 |     /// Override to return true to enable the reserveAllocationSpace callback. | ||
| 143 | virtual bool needsToReserveAllocationSpace() { return false; } | ||
| 144 | |||
| 145 |     /// Override to return false to tell LLVM no stub space will be needed. | ||
| 146 |     /// This requires some guarantees depending on architecuture, but when | ||
| 147 |     /// you know what you are doing it saves allocated space. | ||
| 148 | virtual bool allowStubAllocation() const { return true; } | ||
| 149 | |||
| 150 |     /// Register the EH frames with the runtime so that c++ exceptions work. | ||
| 151 |     /// | ||
| 152 |     /// \p Addr parameter provides the local address of the EH frame section | ||
| 153 |     /// data, while \p LoadAddr provides the address of the data in the target | ||
| 154 |     /// address space.  If the section has not been remapped (which will usually | ||
| 155 |     /// be the case for local execution) these two values will be the same. | ||
| 156 | virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, | ||
| 157 | size_t Size) = 0; | ||
| 158 | virtual void deregisterEHFrames() = 0; | ||
| 159 | |||
| 160 |     /// This method is called when object loading is complete and section page | ||
| 161 |     /// permissions can be applied.  It is up to the memory manager implementation | ||
| 162 |     /// to decide whether or not to act on this method.  The memory manager will | ||
| 163 |     /// typically allocate all sections as read-write and then apply specific | ||
| 164 |     /// permissions when this method is called.  Code sections cannot be executed | ||
| 165 |     /// until this function has been called.  In addition, any cache coherency | ||
| 166 |     /// operations needed to reliably use the memory are also performed. | ||
| 167 |     /// | ||
| 168 |     /// Returns true if an error occurred, false otherwise. | ||
| 169 | virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0; | ||
| 170 | |||
| 171 |     /// This method is called after an object has been loaded into memory but | ||
| 172 |     /// before relocations are applied to the loaded sections. | ||
| 173 |     /// | ||
| 174 |     /// Memory managers which are preparing code for execution in an external | ||
| 175 |     /// address space can use this call to remap the section addresses for the | ||
| 176 |     /// newly loaded object. | ||
| 177 |     /// | ||
| 178 |     /// For clients that do not need access to an ExecutionEngine instance this | ||
| 179 |     /// method should be preferred to its cousin | ||
| 180 |     /// MCJITMemoryManager::notifyObjectLoaded as this method is compatible with | ||
| 181 |     /// ORC JIT stacks. | ||
| 182 | virtual void notifyObjectLoaded(RuntimeDyld &RTDyld, | ||
| 183 | const object::ObjectFile &Obj) {} | ||
| 184 | |||
| 185 | private: | ||
| 186 | virtual void anchor(); | ||
| 187 | |||
| 188 | bool FinalizationLocked = false; | ||
| 189 | }; | ||
| 190 | |||
| 191 |   /// Construct a RuntimeDyld instance. | ||
| 192 | RuntimeDyld(MemoryManager &MemMgr, JITSymbolResolver &Resolver); | ||
| 193 | RuntimeDyld(const RuntimeDyld &) = delete; | ||
| 194 | RuntimeDyld &operator=(const RuntimeDyld &) = delete; | ||
| 195 | ~RuntimeDyld(); | ||
| 196 | |||
| 197 |   /// Add the referenced object file to the list of objects to be loaded and | ||
| 198 |   /// relocated. | ||
| 199 | std::unique_ptr<LoadedObjectInfo> loadObject(const object::ObjectFile &O); | ||
| 200 | |||
| 201 |   /// Get the address of our local copy of the symbol. This may or may not | ||
| 202 |   /// be the address used for relocation (clients can copy the data around | ||
| 203 |   /// and resolve relocatons based on where they put it). | ||
| 204 | void *getSymbolLocalAddress(StringRef Name) const; | ||
| 205 | |||
| 206 |   /// Get the section ID for the section containing the given symbol. | ||
| 207 | unsigned getSymbolSectionID(StringRef Name) const; | ||
| 208 | |||
| 209 |   /// Get the target address and flags for the named symbol. | ||
| 210 |   /// This address is the one used for relocation. | ||
| 211 | JITEvaluatedSymbol getSymbol(StringRef Name) const; | ||
| 212 | |||
| 213 |   /// Returns a copy of the symbol table. This can be used by on-finalized | ||
| 214 |   /// callbacks to extract the symbol table before throwing away the | ||
| 215 |   /// RuntimeDyld instance. Because the map keys (StringRefs) are backed by | ||
| 216 |   /// strings inside the RuntimeDyld instance, the map should be processed | ||
| 217 |   /// before the RuntimeDyld instance is discarded. | ||
| 218 | std::map<StringRef, JITEvaluatedSymbol> getSymbolTable() const; | ||
| 219 | |||
| 220 |   /// Resolve the relocations for all symbols we currently know about. | ||
| 221 | void resolveRelocations(); | ||
| 222 | |||
| 223 |   /// Map a section to its target address space value. | ||
| 224 |   /// Map the address of a JIT section as returned from the memory manager | ||
| 225 |   /// to the address in the target process as the running code will see it. | ||
| 226 |   /// This is the address which will be used for relocation resolution. | ||
| 227 | void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress); | ||
| 228 | |||
| 229 |   /// Returns the section's working memory. | ||
| 230 | StringRef getSectionContent(unsigned SectionID) const; | ||
| 231 | |||
| 232 |   /// If the section was loaded, return the section's load address, | ||
| 233 |   /// otherwise return std::nullopt. | ||
| 234 | uint64_t getSectionLoadAddress(unsigned SectionID) const; | ||
| 235 | |||
| 236 |   /// Set the NotifyStubEmitted callback. This is used for debugging | ||
| 237 |   /// purposes. A callback is made for each stub that is generated. | ||
| 238 | void setNotifyStubEmitted(NotifyStubEmittedFunction NotifyStubEmitted) { | ||
| 239 | this->NotifyStubEmitted = std::move(NotifyStubEmitted); | ||
| 240 |   } | ||
| 241 | |||
| 242 |   /// Register any EH frame sections that have been loaded but not previously | ||
| 243 |   /// registered with the memory manager.  Note, RuntimeDyld is responsible | ||
| 244 |   /// for identifying the EH frame and calling the memory manager with the | ||
| 245 |   /// EH frame section data.  However, the memory manager itself will handle | ||
| 246 |   /// the actual target-specific EH frame registration. | ||
| 247 | void registerEHFrames(); | ||
| 248 | |||
| 249 | void deregisterEHFrames(); | ||
| 250 | |||
| 251 | bool hasError(); | ||
| 252 | StringRef getErrorString(); | ||
| 253 | |||
| 254 |   /// By default, only sections that are "required for execution" are passed to | ||
| 255 |   /// the RTDyldMemoryManager, and other sections are discarded. Passing 'true' | ||
| 256 |   /// to this method will cause RuntimeDyld to pass all sections to its | ||
| 257 |   /// memory manager regardless of whether they are "required to execute" in the | ||
| 258 |   /// usual sense. This is useful for inspecting metadata sections that may not | ||
| 259 |   /// contain relocations, E.g. Debug info, stackmaps. | ||
| 260 |   /// | ||
| 261 |   /// Must be called before the first object file is loaded. | ||
| 262 | void setProcessAllSections(bool ProcessAllSections) { | ||
| 263 | assert(!Dyld && "setProcessAllSections must be called before loadObject."); | ||
| 264 | this->ProcessAllSections = ProcessAllSections; | ||
| 265 |   } | ||
| 266 | |||
| 267 |   /// Perform all actions needed to make the code owned by this RuntimeDyld | ||
| 268 |   /// instance executable: | ||
| 269 |   /// | ||
| 270 |   /// 1) Apply relocations. | ||
| 271 |   /// 2) Register EH frames. | ||
| 272 |   /// 3) Update memory permissions*. | ||
| 273 |   /// | ||
| 274 |   /// * Finalization is potentially recursive**, and the 3rd step will only be | ||
| 275 |   ///   applied by the outermost call to finalize. This allows different | ||
| 276 |   ///   RuntimeDyld instances to share a memory manager without the innermost | ||
| 277 |   ///   finalization locking the memory and causing relocation fixup errors in | ||
| 278 |   ///   outer instances. | ||
| 279 |   /// | ||
| 280 |   /// ** Recursive finalization occurs when one RuntimeDyld instances needs the | ||
| 281 |   ///   address of a symbol owned by some other instance in order to apply | ||
| 282 |   ///   relocations. | ||
| 283 |   /// | ||
| 284 | void finalizeWithMemoryManagerLocking(); | ||
| 285 | |||
| 286 | private: | ||
| 287 | friend void jitLinkForORC( | ||
| 288 | object::OwningBinary<object::ObjectFile> O, | ||
| 289 | RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver, | ||
| 290 |       bool ProcessAllSections, | ||
| 291 | unique_function<Error(const object::ObjectFile &Obj, LoadedObjectInfo &, | ||
| 292 | std::map<StringRef, JITEvaluatedSymbol>)> | ||
| 293 | OnLoaded, | ||
| 294 | unique_function<void(object::OwningBinary<object::ObjectFile> O, | ||
| 295 | std::unique_ptr<LoadedObjectInfo>, Error)> | ||
| 296 | OnEmitted); | ||
| 297 | |||
| 298 |   // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public | ||
| 299 |   // interface. | ||
| 300 | std::unique_ptr<RuntimeDyldImpl> Dyld; | ||
| 301 | MemoryManager &MemMgr; | ||
| 302 | JITSymbolResolver &Resolver; | ||
| 303 | bool ProcessAllSections; | ||
| 304 |   NotifyStubEmittedFunction NotifyStubEmitted; | ||
| 305 | }; | ||
| 306 | |||
| 307 | // Asynchronous JIT link for ORC. | ||
| 308 | // | ||
| 309 | // Warning: This API is experimental and probably should not be used by anyone | ||
| 310 | // but ORC's RTDyldObjectLinkingLayer2. Internally it constructs a RuntimeDyld | ||
| 311 | // instance and uses continuation passing to perform the fix-up and finalize | ||
| 312 | // steps asynchronously. | ||
| 313 | void jitLinkForORC( | ||
| 314 | object::OwningBinary<object::ObjectFile> O, | ||
| 315 | RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver, | ||
| 316 |     bool ProcessAllSections, | ||
| 317 | unique_function<Error(const object::ObjectFile &Obj, | ||
| 318 | RuntimeDyld::LoadedObjectInfo &, | ||
| 319 | std::map<StringRef, JITEvaluatedSymbol>)> | ||
| 320 | OnLoaded, | ||
| 321 | unique_function<void(object::OwningBinary<object::ObjectFile>, | ||
| 322 | std::unique_ptr<RuntimeDyld::LoadedObjectInfo>, Error)> | ||
| 323 | OnEmitted); | ||
| 324 | |||
| 325 | } // end namespace llvm | ||
| 326 | |||
| 327 | #endif // LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H |