1 //===-- BreakpointSite.cpp ------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
11 #include "lldb/Breakpoint/BreakpointSite.h"
13 #include "lldb/Breakpoint/Breakpoint.h"
14 #include "lldb/Breakpoint/BreakpointLocation.h"
15 #include "lldb/Utility/Stream.h"
18 using namespace lldb_private
;
20 BreakpointSite::BreakpointSite(const BreakpointLocationSP
&constituent
,
21 lldb::addr_t addr
, bool use_hardware
)
22 : StoppointSite(GetNextID(), addr
, 0, use_hardware
),
23 m_type(eSoftware
), // Process subclasses need to set this correctly using
25 m_saved_opcode(), m_trap_opcode(),
26 m_enabled(false) // Need to create it disabled, so the first enable turns
29 m_constituents
.Add(constituent
);
32 BreakpointSite::~BreakpointSite() {
33 BreakpointLocationSP bp_loc_sp
;
34 const size_t constituent_count
= m_constituents
.GetSize();
35 for (size_t i
= 0; i
< constituent_count
; i
++) {
36 m_constituents
.GetByIndex(i
)->ClearBreakpointSite();
40 break_id_t
BreakpointSite::GetNextID() {
41 static break_id_t g_next_id
= 0;
45 // RETURNS - true if we should stop at this breakpoint, false if we
48 bool BreakpointSite::ShouldStop(StoppointCallbackContext
*context
) {
49 m_hit_counter
.Increment();
50 // ShouldStop can do a lot of work, and might even come back and hit
51 // this breakpoint site again. So don't hold the m_constituents_mutex the
52 // whole while. Instead make a local copy of the collection and call
53 // ShouldStop on the copy.
54 BreakpointLocationCollection constituents_copy
;
56 std::lock_guard
<std::recursive_mutex
> guard(m_constituents_mutex
);
57 constituents_copy
= m_constituents
;
59 return constituents_copy
.ShouldStop(context
);
62 bool BreakpointSite::IsBreakpointAtThisSite(lldb::break_id_t bp_id
) {
63 std::lock_guard
<std::recursive_mutex
> guard(m_constituents_mutex
);
64 const size_t constituent_count
= m_constituents
.GetSize();
65 for (size_t i
= 0; i
< constituent_count
; i
++) {
66 if (m_constituents
.GetByIndex(i
)->GetBreakpoint().GetID() == bp_id
)
72 void BreakpointSite::Dump(Stream
*s
) const {
76 s
->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx64
77 " type = %s breakpoint hit_count = %-4u",
78 GetID(), (uint64_t)m_addr
, IsHardware() ? "hardware" : "software",
82 void BreakpointSite::GetDescription(Stream
*s
, lldb::DescriptionLevel level
) {
83 std::lock_guard
<std::recursive_mutex
> guard(m_constituents_mutex
);
84 if (level
!= lldb::eDescriptionLevelBrief
)
85 s
->Printf("breakpoint site: %d at 0x%8.8" PRIx64
, GetID(),
87 m_constituents
.GetDescription(s
, level
);
90 std::optional
<uint32_t> BreakpointSite::GetSuggestedStackFrameIndex() {
92 std::optional
<uint32_t> result
;
93 std::lock_guard
<std::recursive_mutex
> guard(m_constituents_mutex
);
94 for (BreakpointLocationSP loc_sp
: m_constituents
.BreakpointLocations()) {
95 std::optional
<uint32_t> loc_frame_index
=
96 loc_sp
->GetSuggestedStackFrameIndex();
97 if (loc_frame_index
) {
99 result
= std::max(*loc_frame_index
, *result
);
101 result
= loc_frame_index
;
107 bool BreakpointSite::IsInternal() const { return m_constituents
.IsInternal(); }
109 uint8_t *BreakpointSite::GetTrapOpcodeBytes() { return &m_trap_opcode
[0]; }
111 const uint8_t *BreakpointSite::GetTrapOpcodeBytes() const {
112 return &m_trap_opcode
[0];
115 size_t BreakpointSite::GetTrapOpcodeMaxByteSize() const {
116 return sizeof(m_trap_opcode
);
119 bool BreakpointSite::SetTrapOpcode(const uint8_t *trap_opcode
,
120 uint32_t trap_opcode_size
) {
121 if (trap_opcode_size
> 0 && trap_opcode_size
<= sizeof(m_trap_opcode
)) {
122 m_byte_size
= trap_opcode_size
;
123 ::memcpy(m_trap_opcode
, trap_opcode
, trap_opcode_size
);
130 uint8_t *BreakpointSite::GetSavedOpcodeBytes() { return &m_saved_opcode
[0]; }
132 const uint8_t *BreakpointSite::GetSavedOpcodeBytes() const {
133 return &m_saved_opcode
[0];
136 bool BreakpointSite::IsEnabled() const { return m_enabled
; }
138 void BreakpointSite::SetEnabled(bool enabled
) { m_enabled
= enabled
; }
140 void BreakpointSite::AddConstituent(const BreakpointLocationSP
&constituent
) {
141 std::lock_guard
<std::recursive_mutex
> guard(m_constituents_mutex
);
142 m_constituents
.Add(constituent
);
145 size_t BreakpointSite::RemoveConstituent(lldb::break_id_t break_id
,
146 lldb::break_id_t break_loc_id
) {
147 std::lock_guard
<std::recursive_mutex
> guard(m_constituents_mutex
);
148 m_constituents
.Remove(break_id
, break_loc_id
);
149 return m_constituents
.GetSize();
152 size_t BreakpointSite::GetNumberOfConstituents() {
153 std::lock_guard
<std::recursive_mutex
> guard(m_constituents_mutex
);
154 return m_constituents
.GetSize();
157 BreakpointLocationSP
BreakpointSite::GetConstituentAtIndex(size_t index
) {
158 std::lock_guard
<std::recursive_mutex
> guard(m_constituents_mutex
);
159 return m_constituents
.GetByIndex(index
);
162 bool BreakpointSite::ValidForThisThread(Thread
&thread
) {
163 std::lock_guard
<std::recursive_mutex
> guard(m_constituents_mutex
);
164 return m_constituents
.ValidForThisThread(thread
);
167 void BreakpointSite::BumpHitCounts() {
168 std::lock_guard
<std::recursive_mutex
> guard(m_constituents_mutex
);
169 for (BreakpointLocationSP loc_sp
: m_constituents
.BreakpointLocations()) {
170 loc_sp
->BumpHitCount();
174 bool BreakpointSite::IntersectsRange(lldb::addr_t addr
, size_t size
,
175 lldb::addr_t
*intersect_addr
,
176 size_t *intersect_size
,
177 size_t *opcode_offset
) const {
178 // The function should be called only for software breakpoints.
179 lldbassert(GetType() == Type::eSoftware
);
181 if (m_byte_size
== 0)
184 const lldb::addr_t bp_end_addr
= m_addr
+ m_byte_size
;
185 const lldb::addr_t end_addr
= addr
+ size
;
186 // Is the breakpoint end address before the passed in start address?
187 if (bp_end_addr
<= addr
)
190 // Is the breakpoint start address after passed in end address?
191 if (end_addr
<= m_addr
)
194 if (intersect_addr
|| intersect_size
|| opcode_offset
) {
197 *intersect_addr
= addr
;
200 std::min
<lldb::addr_t
>(bp_end_addr
, end_addr
) - addr
;
202 *opcode_offset
= addr
- m_addr
;
205 *intersect_addr
= m_addr
;
208 std::min
<lldb::addr_t
>(bp_end_addr
, end_addr
) - m_addr
;
216 size_t BreakpointSite::CopyConstituentsList(
217 BreakpointLocationCollection
&out_collection
) {
218 std::lock_guard
<std::recursive_mutex
> guard(m_constituents_mutex
);
219 for (BreakpointLocationSP loc_sp
: m_constituents
.BreakpointLocations()) {
220 out_collection
.Add(loc_sp
);
222 return out_collection
.GetSize();