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