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