]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Breakpoint/BreakpointSite.cpp
MFV r336851:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Breakpoint / BreakpointSite.cpp
1 //===-- BreakpointSite.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 // C Includes
11 // C++ Includes
12 #include <inttypes.h>
13
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Breakpoint/BreakpointSite.h"
17
18 #include "lldb/Breakpoint/Breakpoint.h"
19 #include "lldb/Breakpoint/BreakpointLocation.h"
20 #include "lldb/Breakpoint/BreakpointSiteList.h"
21 #include "lldb/Utility/Stream.h"
22
23 using namespace lldb;
24 using namespace lldb_private;
25
26 BreakpointSite::BreakpointSite(BreakpointSiteList *list,
27                                const BreakpointLocationSP &owner,
28                                lldb::addr_t addr, bool use_hardware)
29     : StoppointLocation(GetNextID(), addr, 0, use_hardware),
30       m_type(eSoftware), // Process subclasses need to set this correctly using
31                          // SetType()
32       m_saved_opcode(), m_trap_opcode(),
33       m_enabled(false), // Need to create it disabled, so the first enable turns
34                         // it on.
35       m_owners(), m_owners_mutex() {
36   m_owners.Add(owner);
37 }
38
39 BreakpointSite::~BreakpointSite() {
40   BreakpointLocationSP bp_loc_sp;
41   const size_t owner_count = m_owners.GetSize();
42   for (size_t i = 0; i < owner_count; i++) {
43     m_owners.GetByIndex(i)->ClearBreakpointSite();
44   }
45 }
46
47 break_id_t BreakpointSite::GetNextID() {
48   static break_id_t g_next_id = 0;
49   return ++g_next_id;
50 }
51
52 // RETURNS - true if we should stop at this breakpoint, false if we
53 // should continue.
54
55 bool BreakpointSite::ShouldStop(StoppointCallbackContext *context) {
56   std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
57   IncrementHitCount();
58   return m_owners.ShouldStop(context);
59 }
60
61 bool BreakpointSite::IsBreakpointAtThisSite(lldb::break_id_t bp_id) {
62   std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
63   const size_t owner_count = m_owners.GetSize();
64   for (size_t i = 0; i < owner_count; i++) {
65     if (m_owners.GetByIndex(i)->GetBreakpoint().GetID() == bp_id)
66       return true;
67   }
68   return false;
69 }
70
71 void BreakpointSite::Dump(Stream *s) const {
72   if (s == nullptr)
73     return;
74
75   s->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx64
76             "  type = %s breakpoint  hw_index = %i  hit_count = %-4u",
77             GetID(), (uint64_t)m_addr, IsHardware() ? "hardware" : "software",
78             GetHardwareIndex(), GetHitCount());
79 }
80
81 void BreakpointSite::GetDescription(Stream *s, lldb::DescriptionLevel level) {
82   std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
83   if (level != lldb::eDescriptionLevelBrief)
84     s->Printf("breakpoint site: %d at 0x%8.8" PRIx64, GetID(),
85               GetLoadAddress());
86   m_owners.GetDescription(s, level);
87 }
88
89 bool BreakpointSite::IsInternal() const { return m_owners.IsInternal(); }
90
91 uint8_t *BreakpointSite::GetTrapOpcodeBytes() { return &m_trap_opcode[0]; }
92
93 const uint8_t *BreakpointSite::GetTrapOpcodeBytes() const {
94   return &m_trap_opcode[0];
95 }
96
97 size_t BreakpointSite::GetTrapOpcodeMaxByteSize() const {
98   return sizeof(m_trap_opcode);
99 }
100
101 bool BreakpointSite::SetTrapOpcode(const uint8_t *trap_opcode,
102                                    uint32_t trap_opcode_size) {
103   if (trap_opcode_size > 0 && trap_opcode_size <= sizeof(m_trap_opcode)) {
104     m_byte_size = trap_opcode_size;
105     ::memcpy(m_trap_opcode, trap_opcode, trap_opcode_size);
106     return true;
107   }
108   m_byte_size = 0;
109   return false;
110 }
111
112 uint8_t *BreakpointSite::GetSavedOpcodeBytes() { return &m_saved_opcode[0]; }
113
114 const uint8_t *BreakpointSite::GetSavedOpcodeBytes() const {
115   return &m_saved_opcode[0];
116 }
117
118 bool BreakpointSite::IsEnabled() const { return m_enabled; }
119
120 void BreakpointSite::SetEnabled(bool enabled) { m_enabled = enabled; }
121
122 void BreakpointSite::AddOwner(const BreakpointLocationSP &owner) {
123   std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
124   m_owners.Add(owner);
125 }
126
127 size_t BreakpointSite::RemoveOwner(lldb::break_id_t break_id,
128                                    lldb::break_id_t break_loc_id) {
129   std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
130   m_owners.Remove(break_id, break_loc_id);
131   return m_owners.GetSize();
132 }
133
134 size_t BreakpointSite::GetNumberOfOwners() {
135   std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
136   return m_owners.GetSize();
137 }
138
139 BreakpointLocationSP BreakpointSite::GetOwnerAtIndex(size_t index) {
140   std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
141   return m_owners.GetByIndex(index);
142 }
143
144 bool BreakpointSite::ValidForThisThread(Thread *thread) {
145   std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
146   return m_owners.ValidForThisThread(thread);
147 }
148
149 void BreakpointSite::BumpHitCounts() {
150   std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
151   for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations()) {
152     loc_sp->BumpHitCount();
153   }
154 }
155
156 bool BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size,
157                                      lldb::addr_t *intersect_addr,
158                                      size_t *intersect_size,
159                                      size_t *opcode_offset) const {
160   // We only use software traps for software breakpoints
161   if (!IsHardware()) {
162     if (m_byte_size > 0) {
163       const lldb::addr_t bp_end_addr = m_addr + m_byte_size;
164       const lldb::addr_t end_addr = addr + size;
165       // Is the breakpoint end address before the passed in start address?
166       if (bp_end_addr <= addr)
167         return false;
168       // Is the breakpoint start address after passed in end address?
169       if (end_addr <= m_addr)
170         return false;
171       if (intersect_addr || intersect_size || opcode_offset) {
172         if (m_addr < addr) {
173           if (intersect_addr)
174             *intersect_addr = addr;
175           if (intersect_size)
176             *intersect_size =
177                 std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr;
178           if (opcode_offset)
179             *opcode_offset = addr - m_addr;
180         } else {
181           if (intersect_addr)
182             *intersect_addr = m_addr;
183           if (intersect_size)
184             *intersect_size =
185                 std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr;
186           if (opcode_offset)
187             *opcode_offset = 0;
188         }
189       }
190       return true;
191     }
192   }
193   return false;
194 }
195
196 size_t
197 BreakpointSite::CopyOwnersList(BreakpointLocationCollection &out_collection) {
198   std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
199   for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations()) {
200     out_collection.Add(loc_sp);
201   }
202   return out_collection.GetSize();
203 }