1 //===-- DNBBreakpoint.cpp ---------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Created by Greg Clayton on 6/29/07.
12 //===----------------------------------------------------------------------===//
14 #include "DNBBreakpoint.h"
15 #include "MachProcess.h"
22 #pragma mark -- DNBBreakpoint
23 DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size, bool hardware) :
25 m_byte_size (static_cast<uint32_t>(byte_size)),
29 m_hw_preferred(hardware),
33 m_hw_index(INVALID_NUB_HW_INDEX)
37 DNBBreakpoint::~DNBBreakpoint()
42 DNBBreakpoint::Dump() const
46 DNBLog ("DNBBreakpoint addr = 0x%llx state = %s type = %s breakpoint hw_index = %i",
48 m_enabled ? "enabled " : "disabled",
49 IsHardware() ? "hardware" : "software",
54 DNBLog ("DNBBreakpoint addr = 0x%llx size = %llu state = %s type = %s watchpoint (%s%s) hw_index = %i",
56 (uint64_t)m_byte_size,
57 m_enabled ? "enabled " : "disabled",
58 IsHardware() ? "hardware" : "software",
59 m_watch_read ? "r" : "",
60 m_watch_write ? "w" : "",
65 #pragma mark -- DNBBreakpointList
67 DNBBreakpointList::DNBBreakpointList()
71 DNBBreakpointList::~DNBBreakpointList()
77 DNBBreakpointList::Add(nub_addr_t addr, nub_size_t length, bool hardware)
79 m_breakpoints.insert(std::make_pair(addr, DNBBreakpoint(addr, length, hardware)));
80 iterator pos = m_breakpoints.find (addr);
85 DNBBreakpointList::Remove (nub_addr_t addr)
87 iterator pos = m_breakpoints.find(addr);
88 if (pos != m_breakpoints.end())
90 m_breakpoints.erase(pos);
97 DNBBreakpointList::FindByAddress (nub_addr_t addr)
99 iterator pos = m_breakpoints.find(addr);
100 if (pos != m_breakpoints.end())
106 const DNBBreakpoint *
107 DNBBreakpointList::FindByAddress (nub_addr_t addr) const
109 const_iterator pos = m_breakpoints.find(addr);
110 if (pos != m_breakpoints.end())
116 // Finds the next breakpoint at an address greater than or equal to "addr"
118 DNBBreakpointList::FindBreakpointsThatOverlapRange (nub_addr_t addr,
120 std::vector<DNBBreakpoint *> &bps)
123 iterator end = m_breakpoints.end();
124 // Find the first breakpoint with an address >= to "addr"
125 iterator pos = m_breakpoints.lower_bound(addr);
128 if (pos != m_breakpoints.begin())
130 // Watch out for a breakpoint at an address less than "addr" that might still overlap
131 iterator prev_pos = pos;
133 if (prev_pos->second.IntersectsRange (addr, size, NULL, NULL, NULL))
134 bps.push_back (&pos->second);
140 // When we hit a breakpoint whose start address is greater than "addr + size" we are done.
141 // Do the math in a way that doesn't risk unsigned overflow with bad input.
142 if ((pos->second.Address() - addr) >= size)
145 // Check if this breakpoint overlaps, and if it does, add it to the list
146 if (pos->second.IntersectsRange (addr, size, NULL, NULL, NULL))
148 bps.push_back (&pos->second);
157 DNBBreakpointList::Dump() const
160 const_iterator end = m_breakpoints.end();
161 for (pos = m_breakpoints.begin(); pos != end; ++pos)
166 DNBBreakpointList::DisableAll ()
168 iterator pos, end = m_breakpoints.end();
169 for (pos = m_breakpoints.begin(); pos != end; ++pos)
170 pos->second.SetEnabled(false);
175 DNBBreakpointList::RemoveTrapsFromBuffer (nub_addr_t addr, nub_size_t size, void *p) const
177 uint8_t *buf = (uint8_t *)p;
178 const_iterator end = m_breakpoints.end();
179 const_iterator pos = m_breakpoints.lower_bound(addr);
180 while (pos != end && (pos->first < (addr + size)))
182 nub_addr_t intersect_addr;
183 nub_size_t intersect_size;
184 nub_size_t opcode_offset;
185 const DNBBreakpoint &bp = pos->second;
186 if (bp.IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset))
188 assert(addr <= intersect_addr && intersect_addr < addr + size);
189 assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size);
190 assert(opcode_offset + intersect_size <= bp.ByteSize());
191 nub_size_t buf_offset = intersect_addr - addr;
192 ::memcpy(buf + buf_offset, bp.SavedOpcodeBytes() + opcode_offset, intersect_size);
199 DNBBreakpointList::DisableAllBreakpoints(MachProcess *process)
201 iterator pos, end = m_breakpoints.end();
202 for (pos = m_breakpoints.begin(); pos != end; ++pos)
203 process->DisableBreakpoint(pos->second.Address(), false);
207 DNBBreakpointList::DisableAllWatchpoints(MachProcess *process)
209 iterator pos, end = m_breakpoints.end();
210 for (pos = m_breakpoints.begin(); pos != end; ++pos)
211 process->DisableWatchpoint(pos->second.Address(), false);
215 DNBBreakpointList::RemoveDisabled()
217 iterator pos = m_breakpoints.begin();
218 while (pos != m_breakpoints.end())
220 if (!pos->second.IsEnabled())
221 pos = m_breakpoints.erase(pos);