1 | //===-- WatchpointResource.cpp --------------------------------------------===// |
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 <assert.h> |
10 | |
11 | #include "lldb/Breakpoint/WatchpointResource.h" |
12 | #include "lldb/Utility/Stream.h" |
13 | |
14 | #include <algorithm> |
15 | |
16 | using namespace lldb; |
17 | using namespace lldb_private; |
18 | |
19 | WatchpointResource::WatchpointResource(lldb::addr_t addr, size_t size, |
20 | bool read, bool write) |
21 | : m_id(GetNextID()), m_addr(addr), m_size(size), |
22 | m_watch_read(read), m_watch_write(write) {} |
23 | |
24 | WatchpointResource::~WatchpointResource() { |
25 | std::lock_guard<std::mutex> guard(m_constituents_mutex); |
26 | m_constituents.clear(); |
27 | } |
28 | |
29 | addr_t WatchpointResource::GetLoadAddress() const { return m_addr; } |
30 | |
31 | size_t WatchpointResource::GetByteSize() const { return m_size; } |
32 | |
33 | bool WatchpointResource::WatchpointResourceRead() const { return m_watch_read; } |
34 | |
35 | bool WatchpointResource::WatchpointResourceWrite() const { |
36 | return m_watch_write; |
37 | } |
38 | |
39 | void WatchpointResource::SetType(bool read, bool write) { |
40 | m_watch_read = read; |
41 | m_watch_write = write; |
42 | } |
43 | |
44 | wp_resource_id_t WatchpointResource::GetID() const { return m_id; } |
45 | |
46 | bool WatchpointResource::Contains(addr_t addr) { |
47 | if (addr >= m_addr && addr < m_addr + m_size) |
48 | return true; |
49 | return false; |
50 | } |
51 | |
52 | void WatchpointResource::AddConstituent(const WatchpointSP &wp_sp) { |
53 | std::lock_guard<std::mutex> guard(m_constituents_mutex); |
54 | m_constituents.push_back(x: wp_sp); |
55 | } |
56 | |
57 | void WatchpointResource::RemoveConstituent(WatchpointSP &wp_sp) { |
58 | std::lock_guard<std::mutex> guard(m_constituents_mutex); |
59 | const auto &it = |
60 | std::find(first: m_constituents.begin(), last: m_constituents.end(), val: wp_sp); |
61 | if (it != m_constituents.end()) |
62 | m_constituents.erase(position: it); |
63 | } |
64 | |
65 | size_t WatchpointResource::GetNumberOfConstituents() { |
66 | std::lock_guard<std::mutex> guard(m_constituents_mutex); |
67 | return m_constituents.size(); |
68 | } |
69 | |
70 | bool WatchpointResource::ConstituentsContains(const WatchpointSP &wp_sp) { |
71 | return ConstituentsContains(wp: wp_sp.get()); |
72 | } |
73 | |
74 | bool WatchpointResource::ConstituentsContains(const Watchpoint *wp) { |
75 | std::lock_guard<std::mutex> guard(m_constituents_mutex); |
76 | WatchpointCollection::const_iterator match = |
77 | std::find_if(first: m_constituents.begin(), last: m_constituents.end(), |
78 | pred: [&wp](const WatchpointSP &x) { return x.get() == wp; }); |
79 | return match != m_constituents.end(); |
80 | } |
81 | |
82 | WatchpointSP WatchpointResource::GetConstituentAtIndex(size_t idx) { |
83 | std::lock_guard<std::mutex> guard(m_constituents_mutex); |
84 | assert(idx < m_constituents.size()); |
85 | if (idx >= m_constituents.size()) |
86 | return {}; |
87 | |
88 | return m_constituents[idx]; |
89 | } |
90 | |
91 | WatchpointResource::WatchpointCollection |
92 | WatchpointResource::CopyConstituentsList() { |
93 | std::lock_guard<std::mutex> guard(m_constituents_mutex); |
94 | return m_constituents; |
95 | } |
96 | |
97 | bool WatchpointResource::ShouldStop(StoppointCallbackContext *context) { |
98 | // LWP_TODO: Need to poll all Watchpoint constituents and see if |
99 | // we should stop, like BreakpointSites do. |
100 | #if 0 |
101 | m_hit_counter.Increment(); |
102 | // ShouldStop can do a lot of work, and might even come back and hit |
103 | // this breakpoint site again. So don't hold the m_constituents_mutex the |
104 | // whole while. Instead make a local copy of the collection and call |
105 | // ShouldStop on the copy. |
106 | WatchpointResourceCollection constituents_copy; |
107 | { |
108 | std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); |
109 | constituents_copy = m_constituents; |
110 | } |
111 | return constituents_copy.ShouldStop(context); |
112 | #endif |
113 | return true; |
114 | } |
115 | |
116 | void WatchpointResource::Dump(Stream *s) const { |
117 | s->Printf(format: "addr = 0x%8.8" PRIx64 " size = %zu" , m_addr, m_size); |
118 | } |
119 | |
120 | wp_resource_id_t WatchpointResource::GetNextID() { |
121 | static wp_resource_id_t g_next_id = 0; |
122 | return ++g_next_id; |
123 | } |
124 | |