1061da546Spatrick //===-- DNBBreakpoint.h -----------------------------------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick //
9061da546Spatrick //  Created by Greg Clayton on 6/29/07.
10061da546Spatrick //
11061da546Spatrick //===----------------------------------------------------------------------===//
12061da546Spatrick 
13*dda28197Spatrick #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBBREAKPOINT_H
14*dda28197Spatrick #define LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBBREAKPOINT_H
15061da546Spatrick 
16061da546Spatrick #include <mach/mach.h>
17061da546Spatrick 
18061da546Spatrick #include <map>
19061da546Spatrick #include <vector>
20061da546Spatrick 
21061da546Spatrick #include "DNBDefs.h"
22061da546Spatrick 
23061da546Spatrick class MachProcess;
24061da546Spatrick 
25061da546Spatrick class DNBBreakpoint {
26061da546Spatrick public:
27061da546Spatrick   DNBBreakpoint(nub_addr_t m_addr, nub_size_t byte_size, bool hardware);
28061da546Spatrick   ~DNBBreakpoint();
29061da546Spatrick 
ByteSize()30061da546Spatrick   nub_size_t ByteSize() const { return m_byte_size; }
SavedOpcodeBytes()31061da546Spatrick   uint8_t *SavedOpcodeBytes() { return &m_opcode[0]; }
SavedOpcodeBytes()32061da546Spatrick   const uint8_t *SavedOpcodeBytes() const { return &m_opcode[0]; }
Address()33061da546Spatrick   nub_addr_t Address() const { return m_addr; }
34061da546Spatrick   //    nub_thread_t ThreadID() const { return m_tid; }
IsEnabled()35061da546Spatrick   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)36061da546Spatrick   bool IntersectsRange(nub_addr_t addr, nub_size_t size,
37061da546Spatrick                        nub_addr_t *intersect_addr, nub_size_t *intersect_size,
38061da546Spatrick                        nub_size_t *opcode_offset) const {
39061da546Spatrick     // We only use software traps for software breakpoints
40061da546Spatrick     if (IsBreakpoint() && IsEnabled() && !IsHardware()) {
41061da546Spatrick       if (m_byte_size > 0) {
42061da546Spatrick         const nub_addr_t bp_end_addr = m_addr + m_byte_size;
43061da546Spatrick         const nub_addr_t end_addr = addr + size;
44061da546Spatrick         // Is the breakpoint end address before the passed in start address?
45061da546Spatrick         if (bp_end_addr <= addr)
46061da546Spatrick           return false;
47061da546Spatrick         // Is the breakpoint start address after passed in end address?
48061da546Spatrick         if (end_addr <= m_addr)
49061da546Spatrick           return false;
50061da546Spatrick         if (intersect_addr || intersect_size || opcode_offset) {
51061da546Spatrick           if (m_addr < addr) {
52061da546Spatrick             if (intersect_addr)
53061da546Spatrick               *intersect_addr = addr;
54061da546Spatrick             if (intersect_size)
55061da546Spatrick               *intersect_size =
56061da546Spatrick                   std::min<nub_addr_t>(bp_end_addr, end_addr) - addr;
57061da546Spatrick             if (opcode_offset)
58061da546Spatrick               *opcode_offset = addr - m_addr;
59061da546Spatrick           } else {
60061da546Spatrick             if (intersect_addr)
61061da546Spatrick               *intersect_addr = m_addr;
62061da546Spatrick             if (intersect_size)
63061da546Spatrick               *intersect_size =
64061da546Spatrick                   std::min<nub_addr_t>(bp_end_addr, end_addr) - m_addr;
65061da546Spatrick             if (opcode_offset)
66061da546Spatrick               *opcode_offset = 0;
67061da546Spatrick           }
68061da546Spatrick         }
69061da546Spatrick         return true;
70061da546Spatrick       }
71061da546Spatrick     }
72061da546Spatrick     return false;
73061da546Spatrick   }
SetEnabled(bool enabled)74061da546Spatrick   void SetEnabled(bool enabled) {
75061da546Spatrick     if (!enabled)
76061da546Spatrick       SetHardwareIndex(INVALID_NUB_HW_INDEX);
77061da546Spatrick     m_enabled = enabled;
78061da546Spatrick   }
SetIsWatchpoint(uint32_t type)79061da546Spatrick   void SetIsWatchpoint(uint32_t type) {
80061da546Spatrick     m_is_watchpoint = 1;
81061da546Spatrick     m_watch_read = (type & WATCH_TYPE_READ) != 0;
82061da546Spatrick     m_watch_write = (type & WATCH_TYPE_WRITE) != 0;
83061da546Spatrick   }
IsBreakpoint()84061da546Spatrick   bool IsBreakpoint() const { return m_is_watchpoint == 0; }
IsWatchpoint()85061da546Spatrick   bool IsWatchpoint() const { return m_is_watchpoint == 1; }
WatchpointRead()86061da546Spatrick   bool WatchpointRead() const { return m_watch_read != 0; }
WatchpointWrite()87061da546Spatrick   bool WatchpointWrite() const { return m_watch_write != 0; }
HardwarePreferred()88061da546Spatrick   bool HardwarePreferred() const { return m_hw_preferred; }
IsHardware()89061da546Spatrick   bool IsHardware() const { return m_hw_index != INVALID_NUB_HW_INDEX; }
GetHardwareIndex()90061da546Spatrick   uint32_t GetHardwareIndex() const { return m_hw_index; }
SetHardwareIndex(uint32_t hw_index)91061da546Spatrick   void SetHardwareIndex(uint32_t hw_index) { m_hw_index = hw_index; }
92061da546Spatrick   void Dump() const;
Retain()93061da546Spatrick   uint32_t Retain() { return ++m_retain_count; }
Release()94061da546Spatrick   uint32_t Release() {
95061da546Spatrick     if (m_retain_count == 0)
96061da546Spatrick       return 0;
97061da546Spatrick     return --m_retain_count;
98061da546Spatrick   }
99061da546Spatrick 
100061da546Spatrick private:
101061da546Spatrick   uint32_t m_retain_count; // Each breakpoint is maintained by address and is
102061da546Spatrick                            // ref counted in case multiple people set a
103061da546Spatrick                            // breakpoint at the same address
104061da546Spatrick   uint32_t m_byte_size;    // Length in bytes of the breakpoint if set in memory
105061da546Spatrick   uint8_t m_opcode[8];     // Saved opcode bytes
106061da546Spatrick   nub_addr_t m_addr;       // Address of this breakpoint
107061da546Spatrick   uint32_t m_enabled : 1,  // Flags for this breakpoint
108061da546Spatrick       m_hw_preferred : 1,  // 1 if this point has been requested to be set using
109061da546Spatrick                            // hardware (which may fail due to lack of resources)
110061da546Spatrick       m_is_watchpoint : 1, // 1 if this is a watchpoint
111061da546Spatrick       m_watch_read : 1,    // 1 if we stop when the watched data is read from
112061da546Spatrick       m_watch_write : 1;   // 1 if we stop when the watched data is written to
113061da546Spatrick   uint32_t
114061da546Spatrick       m_hw_index; // The hardware resource index for this breakpoint/watchpoint
115061da546Spatrick };
116061da546Spatrick 
117061da546Spatrick class DNBBreakpointList {
118061da546Spatrick public:
119061da546Spatrick   DNBBreakpointList();
120061da546Spatrick   ~DNBBreakpointList();
121061da546Spatrick 
122061da546Spatrick   DNBBreakpoint *Add(nub_addr_t addr, nub_size_t length, bool hardware);
123061da546Spatrick   bool Remove(nub_addr_t addr);
124061da546Spatrick   DNBBreakpoint *FindByAddress(nub_addr_t addr);
125061da546Spatrick   const DNBBreakpoint *FindByAddress(nub_addr_t addr) const;
126061da546Spatrick 
127061da546Spatrick   size_t FindBreakpointsThatOverlapRange(nub_addr_t addr, nub_addr_t size,
128061da546Spatrick                                          std::vector<DNBBreakpoint *> &bps);
129061da546Spatrick 
130061da546Spatrick   void Dump() const;
131061da546Spatrick 
Size()132061da546Spatrick   size_t Size() const { return m_breakpoints.size(); }
133061da546Spatrick   void DisableAll();
134061da546Spatrick 
135061da546Spatrick   void RemoveTrapsFromBuffer(nub_addr_t addr, nub_size_t size, void *buf) const;
136061da546Spatrick 
137061da546Spatrick   void DisableAllBreakpoints(MachProcess *process);
138061da546Spatrick   void DisableAllWatchpoints(MachProcess *process);
139061da546Spatrick   void RemoveDisabled();
140061da546Spatrick 
141061da546Spatrick protected:
142061da546Spatrick   typedef std::map<nub_addr_t, DNBBreakpoint> collection;
143061da546Spatrick   typedef collection::iterator iterator;
144061da546Spatrick   typedef collection::const_iterator const_iterator;
145061da546Spatrick   collection m_breakpoints;
146061da546Spatrick };
147061da546Spatrick 
148061da546Spatrick #endif
149