]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Host/common/NativeBreakpointList.cpp
MFC r345805: Unify SCSI_STATUS_BUSY retry handling with other cases.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Host / common / NativeBreakpointList.cpp
1 //===-- NativeBreakpointList.cpp --------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Host/common/NativeBreakpointList.h"
11
12 #include "lldb/Utility/Log.h"
13
14 #include "lldb/Host/common/NativeBreakpoint.h"
15 #include "lldb/Host/common/SoftwareBreakpoint.h"
16
17 using namespace lldb;
18 using namespace lldb_private;
19
20 NativeBreakpointList::NativeBreakpointList() : m_mutex() {}
21
22 Status NativeBreakpointList::AddRef(lldb::addr_t addr, size_t size_hint,
23                                     bool hardware,
24                                     CreateBreakpointFunc create_func) {
25   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
26   if (log)
27     log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
28                 ", size_hint = %zu, hardware = %s",
29                 __FUNCTION__, addr, size_hint, hardware ? "true" : "false");
30
31   std::lock_guard<std::recursive_mutex> guard(m_mutex);
32
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.
37     if (log)
38       log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
39                   " -- already enabled, upping ref count",
40                   __FUNCTION__, addr);
41
42     iter->second->AddRef();
43     return Status();
44   }
45
46   // Create a new breakpoint using the given create func.
47   if (log)
48     log->Printf(
49         "NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64
50         ", size_hint = %zu, hardware = %s",
51         __FUNCTION__, addr, size_hint, hardware ? "true" : "false");
52
53   NativeBreakpointSP breakpoint_sp;
54   Status error = create_func(addr, size_hint, hardware, breakpoint_sp);
55   if (error.Fail()) {
56     if (log)
57       log->Printf(
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",
61           error.AsCString());
62     return error;
63   }
64
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));
69
70   return error;
71 }
72
73 Status NativeBreakpointList::DecRef(lldb::addr_t addr) {
74   Status error;
75
76   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
77   if (log)
78     log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__,
79                 addr);
80
81   std::lock_guard<std::recursive_mutex> guard(m_mutex);
82
83   // Check if the breakpoint is already set.
84   auto iter = m_breakpoints.find(addr);
85   if (iter == m_breakpoints.end()) {
86     // Not found!
87     if (log)
88       log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND",
89                   __FUNCTION__, addr);
90     error.SetErrorString("breakpoint not found");
91     return error;
92   }
93
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");
97
98   if (new_ref_count > 0) {
99     // Still references to this breakpoint.  Leave it alone.
100     if (log)
101       log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
102                   " -- new breakpoint ref count %" PRIu32,
103                   __FUNCTION__, addr, new_ref_count);
104     return error;
105   }
106
107   // Breakpoint has no more references.  Disable it if it's not already
108   // disabled.
109   if (log)
110     log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
111                 " -- removing due to no remaining references",
112                 __FUNCTION__, addr);
113
114   // If it's enabled, we need to disable it.
115   if (iter->second->IsEnabled()) {
116     if (log)
117       log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
118                   " -- currently enabled, now disabling",
119                   __FUNCTION__, addr);
120     error = iter->second->Disable();
121     if (error.Fail()) {
122       if (log)
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.
127     }
128   } else {
129     if (log)
130       log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
131                   " -- already disabled, nothing to do",
132                   __FUNCTION__, addr);
133   }
134
135   // Take the breakpoint out of the list.
136   if (log)
137     log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
138                 " -- removed from breakpoint map",
139                 __FUNCTION__, addr);
140
141   m_breakpoints.erase(iter);
142   return error;
143 }
144
145 Status NativeBreakpointList::EnableBreakpoint(lldb::addr_t addr) {
146   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
147   if (log)
148     log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__,
149                 addr);
150
151   std::lock_guard<std::recursive_mutex> guard(m_mutex);
152
153   // Ensure we have said breakpoint.
154   auto iter = m_breakpoints.find(addr);
155   if (iter == m_breakpoints.end()) {
156     // Not found!
157     if (log)
158       log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND",
159                   __FUNCTION__, addr);
160     return Status("breakpoint not found");
161   }
162
163   // Enable it.
164   return iter->second->Enable();
165 }
166
167 Status NativeBreakpointList::DisableBreakpoint(lldb::addr_t addr) {
168   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
169   if (log)
170     log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__,
171                 addr);
172
173   std::lock_guard<std::recursive_mutex> guard(m_mutex);
174
175   // Ensure we have said breakpoint.
176   auto iter = m_breakpoints.find(addr);
177   if (iter == m_breakpoints.end()) {
178     // Not found!
179     if (log)
180       log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND",
181                   __FUNCTION__, addr);
182     return Status("breakpoint not found");
183   }
184
185   // Disable it.
186   return iter->second->Disable();
187 }
188
189 Status NativeBreakpointList::GetBreakpoint(lldb::addr_t addr,
190                                            NativeBreakpointSP &breakpoint_sp) {
191   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
192   if (log)
193     log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__,
194                 addr);
195
196   std::lock_guard<std::recursive_mutex> guard(m_mutex);
197
198   // Ensure we have said breakpoint.
199   auto iter = m_breakpoints.find(addr);
200   if (iter == m_breakpoints.end()) {
201     // Not found!
202     breakpoint_sp.reset();
203     return Status("breakpoint not found");
204   }
205
206   // Disable it.
207   breakpoint_sp = iter->second;
208   return Status();
209 }
210
211 Status NativeBreakpointList::RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf,
212                                                    size_t size) const {
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)
217       continue;
218     const auto &bp_sp = map.second;
219     // Not software breakpoint, ignore
220     if (!bp_sp->IsSoftwareBreakpoint())
221       continue;
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);
227   }
228   return Status();
229 }