Branch data Line data Source code
1 : : #include <llvm/ADT/StringMap.h> 2 : : #include <llvm/DebugInfo/DIContext.h> 3 : : #include <llvm/IR/DataLayout.h> 4 : : 5 : : #include "julia_internal.h" 6 : : #include "processor.h" 7 : : 8 : : #include <map> 9 : : #include <mutex> 10 : : #include <type_traits> 11 : : 12 : : typedef struct { 13 : : const llvm::object::ObjectFile *obj; 14 : : llvm::DIContext *ctx; 15 : : int64_t slide; 16 : : } objfileentry_t; 17 : : 18 : : // Central registry for resolving function addresses to `jl_method_instance_t`s and 19 : : // originating `ObjectFile`s (for the DWARF debug info). 20 : : // 21 : : // A global singleton instance is notified by the JIT whenever a new object is emitted, 22 : : // and later queried by the various function info APIs. We also use the chance to handle 23 : : // some platform-specific unwind info registration (which is unrelated to the query 24 : : // functionality). 25 : : class JITDebugInfoRegistry 26 : : { 27 : : public: 28 : : template<typename ResourceT> 29 : : struct Locked { 30 : : 31 : : template<typename CResourceT> 32 : : struct Lock { 33 : : std::unique_lock<std::mutex> lock; 34 : : CResourceT &resource; 35 : : 36 : 1405806 : Lock(std::mutex &mutex, CResourceT &resource) JL_NOTSAFEPOINT : lock(mutex), resource(resource) {} 37 : : Lock(Lock &&) JL_NOTSAFEPOINT = default; 38 : : Lock &operator=(Lock &&) JL_NOTSAFEPOINT = default; 39 : : 40 : 137312695 : CResourceT &operator*() JL_NOTSAFEPOINT { 41 : 137312695 : return resource; 42 : : } 43 : : 44 : : const CResourceT &operator*() const JL_NOTSAFEPOINT { 45 : : return resource; 46 : : } 47 : : 48 : 135997505 : CResourceT *operator->() JL_NOTSAFEPOINT { 49 : 135997505 : return &**this; 50 : : } 51 : : 52 : : const CResourceT *operator->() const JL_NOTSAFEPOINT { 53 : : return &**this; 54 : : } 55 : : 56 : : operator const CResourceT &() const JL_NOTSAFEPOINT { 57 : : return resource; 58 : : } 59 : : 60 : 1405809 : ~Lock() JL_NOTSAFEPOINT = default; 61 : : }; 62 : : private: 63 : : 64 : : mutable std::mutex mutex; 65 : : ResourceT resource; 66 : : public: 67 : : typedef Lock<ResourceT> LockT; 68 : : typedef Lock<const ResourceT> ConstLockT; 69 : : 70 : 1701 : Locked(ResourceT resource = ResourceT()) JL_NOTSAFEPOINT : mutex(), resource(std::move(resource)) {} 71 : : 72 : 1343696 : LockT operator*() JL_NOTSAFEPOINT { 73 : 1343696 : return LockT(mutex, resource); 74 : : } 75 : : 76 : 62112 : ConstLockT operator*() const JL_NOTSAFEPOINT { 77 : 62112 : return ConstLockT(mutex, resource); 78 : : } 79 : : 80 : : ~Locked() JL_NOTSAFEPOINT = default; 81 : : }; 82 : : 83 : : struct sysimg_info_t { 84 : : uint64_t jl_sysimage_base; 85 : : jl_sysimg_fptrs_t sysimg_fptrs; 86 : : jl_method_instance_t **sysimg_fvars_linfo; 87 : : size_t sysimg_fvars_n; 88 : : }; 89 : : 90 : : struct libc_frames_t { 91 : : #if defined(_OS_DARWIN_) && defined(LLVM_SHLIB) 92 : : std::atomic<void(*)(void*)> libc_register_frame_{nullptr}; 93 : : std::atomic<void(*)(void*)> libc_deregister_frame_{nullptr}; 94 : : 95 : : void libc_register_frame(const char *Entry) JL_NOTSAFEPOINT; 96 : : 97 : : void libc_deregister_frame(const char *Entry) JL_NOTSAFEPOINT; 98 : : #endif 99 : : }; 100 : : private: 101 : : 102 : : struct ObjectInfo { 103 : : const llvm::object::ObjectFile *object = nullptr; 104 : : size_t SectionSize = 0; 105 : : ptrdiff_t slide = 0; 106 : : llvm::object::SectionRef Section{}; 107 : : llvm::DIContext *context = nullptr; 108 : : }; 109 : : 110 : : template<typename KeyT, typename ValT> 111 : : using rev_map = std::map<KeyT, ValT, std::greater<KeyT>>; 112 : : 113 : : typedef rev_map<size_t, ObjectInfo> objectmap_t; 114 : : typedef rev_map<uint64_t, objfileentry_t> objfilemap_t; 115 : : 116 : : objectmap_t objectmap{}; 117 : : rev_map<size_t, std::pair<size_t, jl_method_instance_t *>> linfomap{}; 118 : : 119 : : // Maintain a mapping of unrealized function names -> linfo objects 120 : : // so that when we see it get emitted, we can add a link back to the linfo 121 : : // that it came from (providing name, type signature, file info, etc.) 122 : : Locked<llvm::StringMap<jl_code_instance_t*>> codeinst_in_flight{}; 123 : : 124 : : Locked<sysimg_info_t> sysimg_info{}; 125 : : 126 : : Locked<objfilemap_t> objfilemap{}; 127 : : 128 : : static std::string mangle(llvm::StringRef Name, const llvm::DataLayout &DL) JL_NOTSAFEPOINT; 129 : : 130 : : public: 131 : : 132 : : JITDebugInfoRegistry() JL_NOTSAFEPOINT; 133 : : ~JITDebugInfoRegistry() JL_NOTSAFEPOINT = default; 134 : : 135 : : libc_frames_t libc_frames{}; 136 : : 137 : : void add_code_in_flight(llvm::StringRef name, jl_code_instance_t *codeinst, const llvm::DataLayout &DL) JL_NOTSAFEPOINT; 138 : : jl_method_instance_t *lookupLinfo(size_t pointer) JL_NOTSAFEPOINT; 139 : : void registerJITObject(const llvm::object::ObjectFile &Object, 140 : : std::function<uint64_t(const llvm::StringRef &)> getLoadAddress, 141 : : std::function<void*(void*)> lookupWriteAddress) JL_NOTSAFEPOINT; 142 : : objectmap_t& getObjectMap() JL_NOTSAFEPOINT; 143 : : void set_sysimg_info(sysimg_info_t info) JL_NOTSAFEPOINT; 144 : : Locked<sysimg_info_t>::ConstLockT get_sysimg_info() const JL_NOTSAFEPOINT; 145 : : Locked<objfilemap_t>::LockT get_objfile_map() JL_NOTSAFEPOINT; 146 : : };