DNBBreakpoint.h revision 24943d2ee8bfaa7cf5893e4709143924157a5c1e
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
1724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <list>
1824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "DNBDefs.h"
2024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerclass DNBBreakpoint
2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerpublic:
2424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DNBBreakpoint(nub_addr_t m_addr, nub_size_t byte_size, nub_thread_t tid, bool hardware);
2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ~DNBBreakpoint();
2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_break_t GetID() const { return m_breakID; }
2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_size_t  ByteSize() const { return m_byte_size; }
2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint8_t *   SavedOpcodeBytes() { return &m_opcode[0]; }
3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint8_t *
3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                SavedOpcodeBytes() const { return &m_opcode[0]; }
3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_addr_t  Address() const { return m_addr; }
3324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_thread_t ThreadID() const { return m_tid; }
3424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool        IsEnabled() const { return m_enabled; }
3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool        IntersectsRange(nub_addr_t addr, nub_size_t size, nub_addr_t *intersect_addr, nub_size_t *intersect_size, nub_size_t *opcode_offset) const
3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    // We only use software traps for software breakpoints
3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (IsBreakpoint() && IsEnabled() && !IsHardware())
3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (m_byte_size > 0)
4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            const nub_addr_t bp_end_addr = m_addr + m_byte_size;
4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            const nub_addr_t end_addr = addr + size;
4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            // Is the breakpoint end address before the passed in start address?
4524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            if (bp_end_addr <= addr)
4624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                return false;
4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            // Is the breakpoint start address after passed in end address?
4824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            if (end_addr <= m_addr)
4924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                return false;
5024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            if (intersect_addr || intersect_size || opcode_offset)
5124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                if (m_addr < addr)
5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                {
5424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    if (intersect_addr)
5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                        *intersect_addr = addr;
5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    if (intersect_size)
5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                        *intersect_size = std::min<nub_addr_t>(bp_end_addr, end_addr) - addr;
5824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    if (opcode_offset)
5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                        *opcode_offset = addr - m_addr;
6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                }
6124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                else
6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                {
6324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    if (intersect_addr)
6424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                        *intersect_addr = m_addr;
6524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    if (intersect_size)
6624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                        *intersect_size = std::min<nub_addr_t>(bp_end_addr, end_addr) - m_addr;
6724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    if (opcode_offset)
6824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                        *opcode_offset = 0;
6924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                }
7024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
7124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            return true;
7224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
7324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
7424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    return false;
7524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
7624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    void        SetEnabled(uint32_t enabled)
7724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
7824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (!enabled)
7924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        SetHardwareIndex(INVALID_NUB_HW_INDEX);
8024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    m_enabled = enabled;
8124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
8224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    void        SetIsWatchpoint (uint32_t type)
8324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
8424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    m_is_watchpoint = 1;
8524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    m_watch_read = (type & WATCH_TYPE_READ) != 0;
8624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    m_watch_write = (type & WATCH_TYPE_WRITE) != 0;
8724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
8824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool        IsBreakpoint() const { return m_is_watchpoint == 0; }
8924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool        IsWatchpoint() const { return m_is_watchpoint == 1; }
9024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool        WatchpointRead() const { return m_watch_read != 0; }
9124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool        WatchpointWrite() const { return m_watch_write != 0; }
9224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool        HardwarePreferred() const { return m_hw_preferred; }
9324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool        IsHardware() const { return m_hw_index != INVALID_NUB_HW_INDEX; }
9424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint32_t    GetHardwareIndex() const { return m_hw_index; }
9524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    void        SetHardwareIndex(uint32_t hw_index) { m_hw_index = hw_index; }
9624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  StateType   GetState() const { return m_state; }
9724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//  void        SetState(StateType newState) { m_state = newState; }
9824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int32_t     GetHitCount() const { return m_hit_count; }
9924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int32_t     GetIgnoreCount() const { return m_ignore_count; }
10024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    void        SetIgnoreCount(int32_t n) { m_ignore_count = n; }
10124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool        BreakpointHit(nub_process_t pid, nub_thread_t tid);
10224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    void        SetCallback(DNBCallbackBreakpointHit callback, void *callback_baton);
10324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    void        Dump() const;
10424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
10524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerprivate:
10624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_break_t m_breakID;          // The unique identifier for this breakpoint
10724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_thread_t m_tid;             // Thread ID for the breakpoint (can be INVALID_NUB_THREAD for all threads)
10824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_size_t  m_byte_size;        // Length in bytes of the breakpoint if set in memory
10924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint8_t     m_opcode[8];        // Saved opcode bytes
11024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    nub_addr_t  m_addr;             // Address of this breakpoint
11124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint32_t    m_enabled:1,        // Flags for this breakpoint
11224943d2ee8bfaa7cf5893e4709143924157a5c1eChris 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)
11324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                m_is_watchpoint:1,  // 1 if this is a watchpoint
11424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                m_watch_read:1,     // 1 if we stop when the watched data is read from
11524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                m_watch_write:1;    // 1 if we stop when the watched data is written to
11624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint32_t    m_hw_index;         // The hardware resource index for this breakpoint/watchpoint
11724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int32_t     m_hit_count;        // Number of times this breakpoint has been hit
11824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int32_t     m_ignore_count;     // Number of times to ignore this breakpoint
11924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DNBCallbackBreakpointHit
12024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                m_callback;         // Callback to call when this breakpoint gets hit
12124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    void *      m_callback_baton;   // Callback user data to pass to callback
12224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
12324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    static nub_break_t GetNextID();
12424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
12524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner};
12624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
12724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
12824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerclass DNBBreakpointList
12924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
13024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerpublic:
13124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                DNBBreakpointList();
13224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                ~DNBBreakpointList();
13324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
13424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            nub_break_t         Add (const DNBBreakpoint& bp);
13524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            nub_break_t         FindIDByAddress (nub_addr_t addr);
13624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            bool                ShouldStop (nub_process_t pid, nub_thread_t tid, nub_break_t breakID);
13724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            bool                Remove (nub_break_t breakID);
13824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            bool                SetCallback (nub_break_t breakID, DNBCallbackBreakpointHit callback, void *callback_baton);
13924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DNBBreakpoint *     FindByAddress (nub_addr_t addr);
14024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const   DNBBreakpoint *     FindByAddress (nub_addr_t addr) const;
14124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DNBBreakpoint *     FindByID (nub_break_t breakID);
14224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const   DNBBreakpoint *     FindByID (nub_break_t breakID) const;
14324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            void                Dump () const;
14424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
14524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            size_t              Size() const { return m_breakpoints.size(); }
14624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DNBBreakpoint *     GetByIndex (uint32_t i);
14724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const   DNBBreakpoint *     GetByIndex (uint32_t i) const;
14824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
14924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerprotected:
15024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    typedef std::list<DNBBreakpoint>    collection;
15124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    typedef collection::iterator        iterator;
15224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    typedef collection::const_iterator  const_iterator;
15324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            iterator                    GetBreakIDIterator(nub_break_t breakID);
15424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            const_iterator              GetBreakIDConstIterator(nub_break_t breakID) const;
15524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            collection                  m_breakpoints;
15624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner};
15724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
15824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#endif
15924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
160