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