124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- DNBBreakpoint.h -----------------------------------------*- C++ -*-===// 224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The LLVM Compiler Infrastructure 424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source 624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details. 724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===// 924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Created by Greg Clayton on 6/29/07. 1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===// 1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#ifndef __DNBBreakpoint_h__ 1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#define __DNBBreakpoint_h__ 1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 17ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton#include <mach/mach.h> 18ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton 19ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton#include <map> 20ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton#include <vector> 2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "DNBDefs.h" 2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 24ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Claytonclass MachProcess; 25ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton 2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerclass DNBBreakpoint 2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerpublic: 29ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton DNBBreakpoint(nub_addr_t m_addr, nub_size_t byte_size, bool hardware); 3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ~DNBBreakpoint(); 3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_size_t ByteSize() const { return m_byte_size; } 3324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner uint8_t * SavedOpcodeBytes() { return &m_opcode[0]; } 3424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const uint8_t * 3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner SavedOpcodeBytes() const { return &m_opcode[0]; } 3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_addr_t Address() const { return m_addr; } 37ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton// nub_thread_t ThreadID() const { return m_tid; } 3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner bool IsEnabled() const { return m_enabled; } 39ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton bool IntersectsRange(nub_addr_t addr, 40ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton nub_size_t size, 41ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton nub_addr_t *intersect_addr, 42ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton nub_size_t *intersect_size, 43ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton nub_size_t *opcode_offset) const 4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 4524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // We only use software traps for software breakpoints 4624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (IsBreakpoint() && IsEnabled() && !IsHardware()) 4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 4824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_byte_size > 0) 4924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 5024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const nub_addr_t bp_end_addr = m_addr + m_byte_size; 5124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const nub_addr_t end_addr = addr + size; 5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Is the breakpoint end address before the passed in start address? 5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (bp_end_addr <= addr) 5424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return false; 5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Is the breakpoint start address after passed in end address? 5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (end_addr <= m_addr) 5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return false; 5824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (intersect_addr || intersect_size || opcode_offset) 5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_addr < addr) 6124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (intersect_addr) 6324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner *intersect_addr = addr; 6424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (intersect_size) 6524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner *intersect_size = std::min<nub_addr_t>(bp_end_addr, end_addr) - addr; 6624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (opcode_offset) 6724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner *opcode_offset = addr - m_addr; 6824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 6924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 7024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 7124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (intersect_addr) 7224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner *intersect_addr = m_addr; 7324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (intersect_size) 7424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner *intersect_size = std::min<nub_addr_t>(bp_end_addr, end_addr) - m_addr; 7524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (opcode_offset) 7624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner *opcode_offset = 0; 7724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 7824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 7924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return true; 8024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 8124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 8224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return false; 8324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 8431d8918cb12fa1f715920db37a2290b3911e62eeJohnny Chen void SetEnabled(bool enabled) 8524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 8624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (!enabled) 8724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner SetHardwareIndex(INVALID_NUB_HW_INDEX); 8824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_enabled = enabled; 8924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 9024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner void SetIsWatchpoint (uint32_t type) 9124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 9224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_is_watchpoint = 1; 9324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_watch_read = (type & WATCH_TYPE_READ) != 0; 9424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_watch_write = (type & WATCH_TYPE_WRITE) != 0; 9524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 9624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner bool IsBreakpoint() const { return m_is_watchpoint == 0; } 9724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner bool IsWatchpoint() const { return m_is_watchpoint == 1; } 9824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner bool WatchpointRead() const { return m_watch_read != 0; } 9924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner bool WatchpointWrite() const { return m_watch_write != 0; } 10024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner bool HardwarePreferred() const { return m_hw_preferred; } 10124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner bool IsHardware() const { return m_hw_index != INVALID_NUB_HW_INDEX; } 10224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner uint32_t GetHardwareIndex() const { return m_hw_index; } 10324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner void SetHardwareIndex(uint32_t hw_index) { m_hw_index = hw_index; } 10424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner void Dump() const; 105ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton uint32_t Retain () 106ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton { 107ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton return ++m_retain_count; 108ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton } 109ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton uint32_t Release () 110ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton { 111ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton if (m_retain_count == 0) 112ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton return 0; 113ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton return --m_retain_count; 114ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton } 11524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 11624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerprivate: 117ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton 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 118ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton uint32_t m_byte_size; // Length in bytes of the breakpoint if set in memory 11924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner uint8_t m_opcode[8]; // Saved opcode bytes 12024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner nub_addr_t m_addr; // Address of this breakpoint 12124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner uint32_t m_enabled:1, // Flags for this breakpoint 12224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_hw_preferred:1, // 1 if this point has been requested to be set using hardware (which may fail due to lack of resources) 12324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_is_watchpoint:1, // 1 if this is a watchpoint 12424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_watch_read:1, // 1 if we stop when the watched data is read from 12524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_watch_write:1; // 1 if we stop when the watched data is written to 12624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner uint32_t m_hw_index; // The hardware resource index for this breakpoint/watchpoint 12724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}; 12824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 12924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 13024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerclass DNBBreakpointList 13124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 13224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerpublic: 13324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBBreakpointList(); 13424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ~DNBBreakpointList(); 13524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 136ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton DNBBreakpoint * Add (nub_addr_t addr, nub_size_t length, bool hardware); 137ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton bool Remove (nub_addr_t addr); 13824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner DNBBreakpoint * FindByAddress (nub_addr_t addr); 13924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const DNBBreakpoint * FindByAddress (nub_addr_t addr) const; 140ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton 141ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton size_t FindBreakpointsThatOverlapRange (nub_addr_t addr, 142ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton nub_addr_t size, 143ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton std::vector<DNBBreakpoint *> &bps); 144ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton 14524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner void Dump () const; 14624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 14724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner size_t Size() const { return m_breakpoints.size(); } 1484d4ff9e8f7746ba1b1d597512b7cb711350c0206Greg Clayton void DisableAll (); 14924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 150ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton void RemoveTrapsFromBuffer (nub_addr_t addr, 151ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton nub_size_t size, 152ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton void *buf) const; 153ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton 154ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton void DisableAllBreakpoints (MachProcess *process); 155ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton void DisableAllWatchpoints(MachProcess *process); 156ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton void RemoveDisabled (); 15724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerprotected: 158ac94caa68a4a5fa4bd939d7656a6a12d8fc06a33Greg Clayton typedef std::map<nub_addr_t, DNBBreakpoint> collection; 15924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner typedef collection::iterator iterator; 16024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner typedef collection::const_iterator const_iterator; 16124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner collection m_breakpoints; 16224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}; 16324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 16424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif 16524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 166