1 //===-- NativeBreakpointList.cpp --------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Host/common/NativeBreakpointList.h"
12 #include "lldb/Utility/Log.h"
14 #include "lldb/Host/common/NativeBreakpoint.h"
15 #include "lldb/Host/common/SoftwareBreakpoint.h"
18 using namespace lldb_private;
20 NativeBreakpointList::NativeBreakpointList() : m_mutex() {}
22 Status NativeBreakpointList::AddRef(lldb::addr_t addr, size_t size_hint,
24 CreateBreakpointFunc create_func) {
25 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
27 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
28 ", size_hint = %zu, hardware = %s",
29 __FUNCTION__, addr, size_hint, hardware ? "true" : "false");
31 std::lock_guard<std::recursive_mutex> guard(m_mutex);
33 // Check if the breakpoint is already set.
34 auto iter = m_breakpoints.find(addr);
35 if (iter != m_breakpoints.end()) {
36 // Yes - bump up ref count.
38 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
39 " -- already enabled, upping ref count",
42 iter->second->AddRef();
46 // Create a new breakpoint using the given create func.
49 "NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64
50 ", size_hint = %zu, hardware = %s",
51 __FUNCTION__, addr, size_hint, hardware ? "true" : "false");
53 NativeBreakpointSP breakpoint_sp;
54 Status error = create_func(addr, size_hint, hardware, breakpoint_sp);
58 "NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64
59 ", size_hint = %zu, hardware = %s -- FAILED: %s",
60 __FUNCTION__, addr, size_hint, hardware ? "true" : "false",
65 // Remember the breakpoint.
66 assert(breakpoint_sp && "NativeBreakpoint create function succeeded but "
67 "returned NULL breakpoint");
68 m_breakpoints.insert(BreakpointMap::value_type(addr, breakpoint_sp));
73 Status NativeBreakpointList::DecRef(lldb::addr_t addr) {
76 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
78 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__,
81 std::lock_guard<std::recursive_mutex> guard(m_mutex);
83 // Check if the breakpoint is already set.
84 auto iter = m_breakpoints.find(addr);
85 if (iter == m_breakpoints.end()) {
88 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND",
90 error.SetErrorString("breakpoint not found");
94 // Decrement ref count.
95 const int32_t new_ref_count = iter->second->DecRef();
96 assert(new_ref_count >= 0 && "NativeBreakpoint ref count went negative");
98 if (new_ref_count > 0) {
99 // Still references to this breakpoint. Leave it alone.
101 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
102 " -- new breakpoint ref count %" PRIu32,
103 __FUNCTION__, addr, new_ref_count);
107 // Breakpoint has no more references. Disable it if it's not already
110 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
111 " -- removing due to no remaining references",
114 // If it's enabled, we need to disable it.
115 if (iter->second->IsEnabled()) {
117 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
118 " -- currently enabled, now disabling",
120 error = iter->second->Disable();
123 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
124 " -- removal FAILED: %s",
125 __FUNCTION__, addr, error.AsCString());
126 // Continue since we still want to take it out of the breakpoint list.
130 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
131 " -- already disabled, nothing to do",
135 // Take the breakpoint out of the list.
137 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
138 " -- removed from breakpoint map",
141 m_breakpoints.erase(iter);
145 Status NativeBreakpointList::EnableBreakpoint(lldb::addr_t addr) {
146 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
148 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__,
151 std::lock_guard<std::recursive_mutex> guard(m_mutex);
153 // Ensure we have said breakpoint.
154 auto iter = m_breakpoints.find(addr);
155 if (iter == m_breakpoints.end()) {
158 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND",
160 return Status("breakpoint not found");
164 return iter->second->Enable();
167 Status NativeBreakpointList::DisableBreakpoint(lldb::addr_t addr) {
168 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
170 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__,
173 std::lock_guard<std::recursive_mutex> guard(m_mutex);
175 // Ensure we have said breakpoint.
176 auto iter = m_breakpoints.find(addr);
177 if (iter == m_breakpoints.end()) {
180 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND",
182 return Status("breakpoint not found");
186 return iter->second->Disable();
189 Status NativeBreakpointList::GetBreakpoint(lldb::addr_t addr,
190 NativeBreakpointSP &breakpoint_sp) {
191 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
193 log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__,
196 std::lock_guard<std::recursive_mutex> guard(m_mutex);
198 // Ensure we have said breakpoint.
199 auto iter = m_breakpoints.find(addr);
200 if (iter == m_breakpoints.end()) {
202 breakpoint_sp.reset();
203 return Status("breakpoint not found");
207 breakpoint_sp = iter->second;
211 Status NativeBreakpointList::RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf,
213 for (const auto &map : m_breakpoints) {
214 lldb::addr_t bp_addr = map.first;
215 // Breapoint not in range, ignore
216 if (bp_addr < addr || addr + size <= bp_addr)
218 const auto &bp_sp = map.second;
219 // Not software breakpoint, ignore
220 if (!bp_sp->IsSoftwareBreakpoint())
222 auto software_bp_sp = std::static_pointer_cast<SoftwareBreakpoint>(bp_sp);
223 auto opcode_addr = static_cast<char *>(buf) + bp_addr - addr;
224 auto saved_opcodes = software_bp_sp->m_saved_opcodes;
225 auto opcode_size = software_bp_sp->m_opcode_size;
226 ::memcpy(opcode_addr, saved_opcodes, opcode_size);