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