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

source code of lldb/tools/debugserver/source/DNBBreakpoint.h