]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Breakpoint/BreakpointSite.cpp
Vendor import of lldb trunk r256945:
[FreeBSD/FreeBSD.git] / 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/Core/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,
29                                bool use_hardware) :
30     StoppointLocation(GetNextID(), addr, 0, use_hardware),
31     m_type (eSoftware), // Process subclasses need to set this correctly using SetType()
32     m_saved_opcode(),
33     m_trap_opcode(),
34     m_enabled(false), // Need to create it disabled, so the first enable turns it on.
35     m_owners(),
36     m_owners_mutex(Mutex::eMutexTypeRecursive)
37 {
38     m_owners.Add(owner);
39 }
40
41 BreakpointSite::~BreakpointSite()
42 {
43     BreakpointLocationSP bp_loc_sp;
44     const size_t owner_count = m_owners.GetSize();
45     for (size_t i = 0; i < owner_count; i++)
46     {
47         m_owners.GetByIndex(i)->ClearBreakpointSite();
48     }
49 }
50
51 break_id_t
52 BreakpointSite::GetNextID()
53 {
54     static break_id_t g_next_id = 0;
55     return ++g_next_id;
56 }
57
58 // RETURNS - true if we should stop at this breakpoint, false if we
59 // should continue.
60
61 bool
62 BreakpointSite::ShouldStop (StoppointCallbackContext *context)
63 {
64     Mutex::Locker locker(m_owners_mutex);
65     IncrementHitCount();
66     return m_owners.ShouldStop (context);
67 }
68
69 bool
70 BreakpointSite::IsBreakpointAtThisSite (lldb::break_id_t bp_id)
71 {
72     Mutex::Locker locker(m_owners_mutex);
73     const size_t owner_count = m_owners.GetSize();
74     for (size_t i = 0; i < owner_count; i++)
75     {
76         if (m_owners.GetByIndex(i)->GetBreakpoint().GetID() == bp_id)
77             return true;
78     }
79     return false;
80 }
81
82 void
83 BreakpointSite::Dump(Stream *s) const
84 {
85     if (s == nullptr)
86         return;
87
88     s->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx64 "  type = %s breakpoint  hw_index = %i  hit_count = %-4u",
89             GetID(),
90             (uint64_t)m_addr,
91             IsHardware() ? "hardware" : "software",
92             GetHardwareIndex(),
93             GetHitCount());
94 }
95
96 void
97 BreakpointSite::GetDescription (Stream *s, lldb::DescriptionLevel level)
98 {
99     Mutex::Locker locker(m_owners_mutex);
100     if (level != lldb::eDescriptionLevelBrief)
101         s->Printf ("breakpoint site: %d at 0x%8.8" PRIx64, GetID(), GetLoadAddress());
102     m_owners.GetDescription (s, level);
103 }
104
105 bool
106 BreakpointSite::IsInternal() const
107 {
108     return m_owners.IsInternal();
109 }
110
111 uint8_t *
112 BreakpointSite::GetTrapOpcodeBytes()
113 {
114     return &m_trap_opcode[0];
115 }
116
117 const uint8_t *
118 BreakpointSite::GetTrapOpcodeBytes() const
119 {
120     return &m_trap_opcode[0];
121 }
122
123 size_t
124 BreakpointSite::GetTrapOpcodeMaxByteSize() const
125 {
126     return sizeof(m_trap_opcode);
127 }
128
129 bool
130 BreakpointSite::SetTrapOpcode (const uint8_t *trap_opcode, uint32_t trap_opcode_size)
131 {
132     if (trap_opcode_size > 0 && trap_opcode_size <= sizeof(m_trap_opcode))
133     {
134         m_byte_size = trap_opcode_size;
135         ::memcpy (m_trap_opcode, trap_opcode, trap_opcode_size);
136         return true;
137     }
138     m_byte_size = 0;
139     return false;
140 }
141
142 uint8_t *
143 BreakpointSite::GetSavedOpcodeBytes()
144 {
145     return &m_saved_opcode[0];
146 }
147
148 const uint8_t *
149 BreakpointSite::GetSavedOpcodeBytes() const
150 {
151     return &m_saved_opcode[0];
152 }
153
154 bool
155 BreakpointSite::IsEnabled () const
156 {
157     return m_enabled;
158 }
159
160 void
161 BreakpointSite::SetEnabled (bool enabled)
162 {
163     m_enabled = enabled;
164 }
165
166 void
167 BreakpointSite::AddOwner (const BreakpointLocationSP &owner)
168 {
169     Mutex::Locker locker(m_owners_mutex);
170     m_owners.Add(owner);
171 }
172
173 size_t
174 BreakpointSite::RemoveOwner (lldb::break_id_t break_id, lldb::break_id_t break_loc_id)
175 {
176     Mutex::Locker locker(m_owners_mutex);
177     m_owners.Remove(break_id, break_loc_id);
178     return m_owners.GetSize();
179 }
180
181 size_t
182 BreakpointSite::GetNumberOfOwners ()
183 {
184     Mutex::Locker locker(m_owners_mutex);
185     return m_owners.GetSize();
186 }
187
188 BreakpointLocationSP
189 BreakpointSite::GetOwnerAtIndex (size_t index)
190 {
191     Mutex::Locker locker(m_owners_mutex);
192     return m_owners.GetByIndex (index);
193 }
194
195 bool
196 BreakpointSite::ValidForThisThread (Thread *thread)
197 {
198     Mutex::Locker locker(m_owners_mutex);
199     return m_owners.ValidForThisThread(thread);
200 }
201
202 void
203 BreakpointSite::BumpHitCounts()
204 {
205     Mutex::Locker locker(m_owners_mutex);
206     for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations())
207     {
208         loc_sp->BumpHitCount();
209     }
210 }
211
212 bool
213 BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const
214 {
215     // We only use software traps for software breakpoints
216     if (!IsHardware())
217     {
218         if (m_byte_size > 0)
219         {
220             const lldb::addr_t bp_end_addr = m_addr + m_byte_size;
221             const lldb::addr_t end_addr = addr + size;
222             // Is the breakpoint end address before the passed in start address?
223             if (bp_end_addr <= addr)
224                 return false;
225             // Is the breakpoint start address after passed in end address?
226             if (end_addr <= m_addr)
227                 return false;
228             if (intersect_addr || intersect_size || opcode_offset)
229             {
230                 if (m_addr < addr)
231                 {
232                     if (intersect_addr)
233                         *intersect_addr = addr;
234                     if (intersect_size)
235                         *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr;
236                     if (opcode_offset)
237                         *opcode_offset = addr - m_addr;
238                 }
239                 else
240                 {
241                     if (intersect_addr)
242                         *intersect_addr = m_addr;
243                     if (intersect_size)
244                         *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr;
245                     if (opcode_offset)
246                         *opcode_offset = 0;
247                 }
248             }
249             return true;
250         }
251     }
252     return false;
253 }
254
255 size_t
256 BreakpointSite::CopyOwnersList (BreakpointLocationCollection &out_collection)
257 {
258     Mutex::Locker locker(m_owners_mutex);
259     for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations())
260     {
261         out_collection.Add(loc_sp);
262     }
263     return out_collection.GetSize();
264 }