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