1 //===---------------------SharingPtr.cpp ------------------------*- 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 #include "lldb/Utility/SharingPtr.h" 11 12 #if defined (ENABLE_SP_LOGGING) 13 14 // If ENABLE_SP_LOGGING is defined, then log all shared pointer assignements 15 // and allow them to be queried using a pointer by a call to: 16 #include <execinfo.h> 17 #include <map> 18 #include <assert.h> 19 #include "lldb/Host/Mutex.h" 20 21 #include "llvm/ADT/STLExtras.h" 22 23 #include <vector> 24 25 class Backtrace 26 { 27 public: 28 Backtrace (); 29 30 ~Backtrace (); 31 32 void 33 GetFrames (); 34 35 void 36 Dump () const; 37 38 private: 39 void *m_sp_this; 40 std::vector<void *> m_frames; 41 }; 42 43 44 Backtrace::Backtrace () : m_frames() 45 { 46 } 47 48 Backtrace::~Backtrace () 49 { 50 } 51 52 void 53 Backtrace::GetFrames () 54 { 55 void *frames[1024]; 56 const int count = ::backtrace (frames, llvm::array_lengthof(frames)); 57 if (count > 2) 58 m_frames.assign (frames + 2, frames + (count - 2)); 59 } 60 61 void 62 Backtrace::Dump () const 63 { 64 if (!m_frames.empty()) 65 ::backtrace_symbols_fd (m_frames.data(), m_frames.size(), STDOUT_FILENO); 66 write (STDOUT_FILENO, "\n\n", 2); 67 } 68 69 extern "C" void track_sp (void *sp_this, void *ptr, long use_count) 70 { 71 typedef std::pair<void *, Backtrace> PtrBacktracePair; 72 typedef std::map<void *, PtrBacktracePair> PtrToBacktraceMap; 73 static lldb_private::Mutex g_mutex(lldb_private::Mutex::eMutexTypeNormal); 74 lldb_private::Mutex::Locker locker (g_mutex); 75 static PtrToBacktraceMap g_map; 76 77 if (sp_this) 78 { 79 printf ("sp(%p) -> %p %lu\n", sp_this, ptr, use_count); 80 81 if (ptr) 82 { 83 Backtrace bt; 84 bt.GetFrames(); 85 g_map[sp_this] = std::make_pair(ptr, bt); 86 } 87 else 88 { 89 g_map.erase (sp_this); 90 } 91 } 92 else 93 { 94 if (ptr) 95 printf ("Searching for shared pointers that are tracking %p: ", ptr); 96 else 97 printf ("Dump all live shared pointres: "); 98 99 uint32_t matches = 0; 100 PtrToBacktraceMap::iterator pos, end = g_map.end(); 101 for (pos = g_map.begin(); pos != end; ++pos) 102 { 103 if (ptr == NULL || pos->second.first == ptr) 104 { 105 ++matches; 106 printf ("\nsp(%p): %p\n", pos->first, pos->second.first); 107 pos->second.second.Dump(); 108 } 109 } 110 if (matches == 0) 111 { 112 printf ("none.\n"); 113 } 114 } 115 } 116 // Put dump_sp_refs in the lldb namespace to it gets through our exports lists filter in the LLDB.framework or lldb.so 117 namespace lldb { 118 119 void dump_sp_refs (void *ptr) 120 { 121 // Use a specially crafted call to "track_sp" which will 122 // dump info on all live shared pointers that reference "ptr" 123 track_sp (NULL, ptr, 0); 124 } 125 126 } 127 128 #endif 129 130 namespace lldb_private { 131 132 namespace imp 133 { 134 135 136 shared_count::~shared_count() 137 { 138 } 139 140 void 141 shared_count::add_shared() 142 { 143 #ifdef _MSC_VER 144 _InterlockedIncrement(&shared_owners_); 145 #else 146 ++shared_owners_; 147 #endif 148 } 149 150 void 151 shared_count::release_shared() 152 { 153 #ifdef _MSC_VER 154 if (_InterlockedDecrement(&shared_owners_) == -1) 155 #else 156 if (--shared_owners_ == -1) 157 #endif 158 { 159 on_zero_shared(); 160 delete this; 161 } 162 } 163 164 } // imp 165 166 167 } // namespace lldb 168 169