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