reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
//===---------------------SharingPtr.cpp ------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Utility/SharingPtr.h"

#if defined(ENABLE_SP_LOGGING)

// If ENABLE_SP_LOGGING is defined, then log all shared pointer assignments and
// allow them to be queried using a pointer by a call to:
#include <assert.h>
#include <execinfo.h>

#include "llvm/ADT/STLExtras.h"

#include <map>
#include <mutex>
#include <vector>

class Backtrace {
public:
  Backtrace();

  ~Backtrace();

  void GetFrames();

  void Dump() const;

private:
  void *m_sp_this;
  std::vector<void *> m_frames;
};

Backtrace::Backtrace() : m_frames() {}

Backtrace::~Backtrace() {}

void Backtrace::GetFrames() {
  void *frames[1024];
  const int count = ::backtrace(frames, llvm::array_lengthof(frames));
  if (count > 2)
    m_frames.assign(frames + 2, frames + (count - 2));
}

void Backtrace::Dump() const {
  if (!m_frames.empty())
    ::backtrace_symbols_fd(m_frames.data(), m_frames.size(), STDOUT_FILENO);
  write(STDOUT_FILENO, "\n\n", 2);
}

extern "C" void track_sp(void *sp_this, void *ptr, long use_count) {
  typedef std::pair<void *, Backtrace> PtrBacktracePair;
  typedef std::map<void *, PtrBacktracePair> PtrToBacktraceMap;
  static std::mutex g_mutex;
  std::lock_guard<std::mutex> guard(g_mutex);
  static PtrToBacktraceMap g_map;

  if (sp_this) {
    printf("sp(%p) -> %p %lu\n", sp_this, ptr, use_count);

    if (ptr) {
      Backtrace bt;
      bt.GetFrames();
      g_map[sp_this] = std::make_pair(ptr, bt);
    } else {
      g_map.erase(sp_this);
    }
  } else {
    if (ptr)
      printf("Searching for shared pointers that are tracking %p: ", ptr);
    else
      printf("Dump all live shared pointres: ");

    uint32_t matches = 0;
    PtrToBacktraceMap::iterator pos, end = g_map.end();
    for (pos = g_map.begin(); pos != end; ++pos) {
      if (ptr == NULL || pos->second.first == ptr) {
        ++matches;
        printf("\nsp(%p): %p\n", pos->first, pos->second.first);
        pos->second.second.Dump();
      }
    }
    if (matches == 0) {
      printf("none.\n");
    }
  }
}
// Put dump_sp_refs in the lldb namespace to it gets through our exports lists
// filter in the LLDB.framework or lldb.so
namespace lldb {

void dump_sp_refs(void *ptr) {
  // Use a specially crafted call to "track_sp" which will dump info on all
  // live shared pointers that reference "ptr"
  track_sp(NULL, ptr, 0);
}
}

#endif

namespace lldb_private {

namespace imp {

shared_count::~shared_count() {}

void shared_count::add_shared() {
#ifdef _MSC_VER
  _InterlockedIncrement(&shared_owners_);
#else
  ++shared_owners_;
#endif
}

void shared_count::release_shared() {
#ifdef _MSC_VER
  if (_InterlockedDecrement(&shared_owners_) == -1)
#else
  if (--shared_owners_ == -1)
#endif
  {
    on_zero_shared();
    delete this;
  }
}

} // imp

} // namespace lldb