1 //===-- DNBBreakpoint.h -----------------------------------------*- 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 // Created by Greg Clayton on 6/29/07. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef __DNBBreakpoint_h__ 15 #define __DNBBreakpoint_h__ 16 17 #include <mach/mach.h> 18 19 #include <map> 20 #include <vector> 21 22 #include "DNBDefs.h" 23 24 class MachProcess; 25 26 class DNBBreakpoint 27 { 28 public: 29 DNBBreakpoint(nub_addr_t m_addr, nub_size_t byte_size, bool hardware); 30 ~DNBBreakpoint(); 31 ByteSize()32 nub_size_t ByteSize() const { return m_byte_size; } SavedOpcodeBytes()33 uint8_t * SavedOpcodeBytes() { return &m_opcode[0]; } 34 const uint8_t * SavedOpcodeBytes()35 SavedOpcodeBytes() const { return &m_opcode[0]; } Address()36 nub_addr_t Address() const { return m_addr; } 37 // nub_thread_t ThreadID() const { return m_tid; } IsEnabled()38 bool IsEnabled() const { return m_enabled; } IntersectsRange(nub_addr_t addr,nub_size_t size,nub_addr_t * intersect_addr,nub_size_t * intersect_size,nub_size_t * opcode_offset)39 bool IntersectsRange(nub_addr_t addr, 40 nub_size_t size, 41 nub_addr_t *intersect_addr, 42 nub_size_t *intersect_size, 43 nub_size_t *opcode_offset) const 44 { 45 // We only use software traps for software breakpoints 46 if (IsBreakpoint() && IsEnabled() && !IsHardware()) 47 { 48 if (m_byte_size > 0) 49 { 50 const nub_addr_t bp_end_addr = m_addr + m_byte_size; 51 const nub_addr_t end_addr = addr + size; 52 // Is the breakpoint end address before the passed in start address? 53 if (bp_end_addr <= addr) 54 return false; 55 // Is the breakpoint start address after passed in end address? 56 if (end_addr <= m_addr) 57 return false; 58 if (intersect_addr || intersect_size || opcode_offset) 59 { 60 if (m_addr < addr) 61 { 62 if (intersect_addr) 63 *intersect_addr = addr; 64 if (intersect_size) 65 *intersect_size = std::min<nub_addr_t>(bp_end_addr, end_addr) - addr; 66 if (opcode_offset) 67 *opcode_offset = addr - m_addr; 68 } 69 else 70 { 71 if (intersect_addr) 72 *intersect_addr = m_addr; 73 if (intersect_size) 74 *intersect_size = std::min<nub_addr_t>(bp_end_addr, end_addr) - m_addr; 75 if (opcode_offset) 76 *opcode_offset = 0; 77 } 78 } 79 return true; 80 } 81 } 82 return false; 83 } SetEnabled(bool enabled)84 void SetEnabled(bool enabled) 85 { 86 if (!enabled) 87 SetHardwareIndex(INVALID_NUB_HW_INDEX); 88 m_enabled = enabled; 89 } SetIsWatchpoint(uint32_t type)90 void SetIsWatchpoint (uint32_t type) 91 { 92 m_is_watchpoint = 1; 93 m_watch_read = (type & WATCH_TYPE_READ) != 0; 94 m_watch_write = (type & WATCH_TYPE_WRITE) != 0; 95 } IsBreakpoint()96 bool IsBreakpoint() const { return m_is_watchpoint == 0; } IsWatchpoint()97 bool IsWatchpoint() const { return m_is_watchpoint == 1; } WatchpointRead()98 bool WatchpointRead() const { return m_watch_read != 0; } WatchpointWrite()99 bool WatchpointWrite() const { return m_watch_write != 0; } HardwarePreferred()100 bool HardwarePreferred() const { return m_hw_preferred; } IsHardware()101 bool IsHardware() const { return m_hw_index != INVALID_NUB_HW_INDEX; } GetHardwareIndex()102 uint32_t GetHardwareIndex() const { return m_hw_index; } SetHardwareIndex(uint32_t hw_index)103 void SetHardwareIndex(uint32_t hw_index) { m_hw_index = hw_index; } 104 void Dump() const; Retain()105 uint32_t Retain () 106 { 107 return ++m_retain_count; 108 } Release()109 uint32_t Release () 110 { 111 if (m_retain_count == 0) 112 return 0; 113 return --m_retain_count; 114 } 115 116 private: 117 uint32_t m_retain_count; // Each breakpoint is maintained by address and is ref counted in case multiple people set a breakpoint at the same address 118 uint32_t m_byte_size; // Length in bytes of the breakpoint if set in memory 119 uint8_t m_opcode[8]; // Saved opcode bytes 120 nub_addr_t m_addr; // Address of this breakpoint 121 uint32_t m_enabled:1, // Flags for this breakpoint 122 m_hw_preferred:1, // 1 if this point has been requested to be set using hardware (which may fail due to lack of resources) 123 m_is_watchpoint:1, // 1 if this is a watchpoint 124 m_watch_read:1, // 1 if we stop when the watched data is read from 125 m_watch_write:1; // 1 if we stop when the watched data is written to 126 uint32_t m_hw_index; // The hardware resource index for this breakpoint/watchpoint 127 }; 128 129 130 class DNBBreakpointList 131 { 132 public: 133 DNBBreakpointList(); 134 ~DNBBreakpointList(); 135 136 DNBBreakpoint * Add (nub_addr_t addr, nub_size_t length, bool hardware); 137 bool Remove (nub_addr_t addr); 138 DNBBreakpoint * FindByAddress (nub_addr_t addr); 139 const DNBBreakpoint * FindByAddress (nub_addr_t addr) const; 140 141 size_t FindBreakpointsThatOverlapRange (nub_addr_t addr, 142 nub_addr_t size, 143 std::vector<DNBBreakpoint *> &bps); 144 145 void Dump () const; 146 Size()147 size_t Size() const { return m_breakpoints.size(); } 148 void DisableAll (); 149 150 void RemoveTrapsFromBuffer (nub_addr_t addr, 151 nub_size_t size, 152 void *buf) const; 153 154 void DisableAllBreakpoints (MachProcess *process); 155 void DisableAllWatchpoints(MachProcess *process); 156 void RemoveDisabled (); 157 protected: 158 typedef std::map<nub_addr_t, DNBBreakpoint> collection; 159 typedef collection::iterator iterator; 160 typedef collection::const_iterator const_iterator; 161 collection m_breakpoints; 162 }; 163 164 #endif 165 166