File: | tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp |
Location: | line 262, column 12 |
Description: | Potential leak of memory pointed to by 'reg_interface' |
1 | //===-- POSIXThread.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/lldb-python.h" | |||||
11 | ||||||
12 | // C Includes | |||||
13 | #include <errno(*__errno_location ()).h> | |||||
14 | ||||||
15 | // C++ Includes | |||||
16 | // Other libraries and framework includes | |||||
17 | // Project includes | |||||
18 | #include "lldb/Breakpoint/Watchpoint.h" | |||||
19 | #include "lldb/Breakpoint/BreakpointLocation.h" | |||||
20 | #include "lldb/Core/Debugger.h" | |||||
21 | #include "lldb/Core/State.h" | |||||
22 | #include "lldb/Host/Host.h" | |||||
23 | #include "lldb/Host/HostNativeThread.h" | |||||
24 | #include "lldb/Host/HostInfo.h" | |||||
25 | #include "lldb/Target/Process.h" | |||||
26 | #include "lldb/Target/StopInfo.h" | |||||
27 | #include "lldb/Target/Target.h" | |||||
28 | #include "lldb/Target/ThreadSpec.h" | |||||
29 | #include "llvm/ADT/SmallString.h" | |||||
30 | #include "POSIXStopInfo.h" | |||||
31 | #include "POSIXThread.h" | |||||
32 | #include "ProcessPOSIX.h" | |||||
33 | #include "ProcessPOSIXLog.h" | |||||
34 | #include "Plugins/Process/Linux/ProcessMonitor.h" | |||||
35 | #include "RegisterContextPOSIXProcessMonitor_arm64.h" | |||||
36 | #include "RegisterContextPOSIXProcessMonitor_mips64.h" | |||||
37 | #include "RegisterContextPOSIXProcessMonitor_powerpc.h" | |||||
38 | #include "RegisterContextPOSIXProcessMonitor_x86.h" | |||||
39 | #include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" | |||||
40 | #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" | |||||
41 | #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" | |||||
42 | #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" | |||||
43 | #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" | |||||
44 | #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" | |||||
45 | #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" | |||||
46 | #include "Plugins/Process/Utility/UnwindLLDB.h" | |||||
47 | ||||||
48 | using namespace lldb; | |||||
49 | using namespace lldb_private; | |||||
50 | ||||||
51 | ||||||
52 | POSIXThread::POSIXThread(Process &process, lldb::tid_t tid) | |||||
53 | : Thread(process, tid), | |||||
54 | m_frame_ap (), | |||||
55 | m_breakpoint (), | |||||
56 | m_thread_name_valid (false), | |||||
57 | m_thread_name (), | |||||
58 | m_posix_thread(NULL__null) | |||||
59 | { | |||||
60 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD(1u << 2))); | |||||
61 | if (log && log->GetMask().Test(POSIX_LOG_VERBOSE(1u << 0))) | |||||
62 | log->Printf ("POSIXThread::%s (tid = %" PRIi64"l" "i" ")", __FUNCTION__, tid); | |||||
63 | ||||||
64 | // Set the current watchpoints for this thread. | |||||
65 | Target &target = GetProcess()->GetTarget(); | |||||
66 | const WatchpointList &wp_list = target.GetWatchpointList(); | |||||
67 | size_t wp_size = wp_list.GetSize(); | |||||
68 | ||||||
69 | for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++) | |||||
70 | { | |||||
71 | lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx); | |||||
72 | if (wp.get() && wp->IsEnabled()) | |||||
73 | { | |||||
74 | // This watchpoint as been enabled; obviously this "new" thread | |||||
75 | // has been created since that watchpoint was enabled. Since | |||||
76 | // the POSIXBreakpointProtocol has yet to be initialized, its | |||||
77 | // m_watchpoints_initialized member will be FALSE. Attempting to | |||||
78 | // read the debug status register to determine if a watchpoint | |||||
79 | // has been hit would result in the zeroing of that register. | |||||
80 | // Since the active debug registers would have been cloned when | |||||
81 | // this thread was created, simply force the m_watchpoints_initized | |||||
82 | // member to TRUE and avoid resetting dr6 and dr7. | |||||
83 | GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized(); | |||||
84 | } | |||||
85 | } | |||||
86 | } | |||||
87 | ||||||
88 | POSIXThread::~POSIXThread() | |||||
89 | { | |||||
90 | DestroyThread(); | |||||
91 | } | |||||
92 | ||||||
93 | ProcessMonitor & | |||||
94 | POSIXThread::GetMonitor() | |||||
95 | { | |||||
96 | ProcessSP base = GetProcess(); | |||||
97 | ProcessPOSIX &process = static_cast<ProcessPOSIX&>(*base); | |||||
98 | return process.GetMonitor(); | |||||
99 | } | |||||
100 | ||||||
101 | // Overridden by FreeBSDThread; this is used only on Linux. | |||||
102 | void | |||||
103 | POSIXThread::RefreshStateAfterStop() | |||||
104 | { | |||||
105 | // Invalidate all registers in our register context. We don't set "force" to | |||||
106 | // true because the stop reply packet might have had some register values | |||||
107 | // that were expedited and these will already be copied into the register | |||||
108 | // context by the time this function gets called. The KDPRegisterContext | |||||
109 | // class has been made smart enough to detect when it needs to invalidate | |||||
110 | // which registers are valid by putting hooks in the register read and | |||||
111 | // register supply functions where they check the process stop ID and do | |||||
112 | // the right thing. | |||||
113 | //if (StateIsStoppedState(GetState()) | |||||
114 | { | |||||
115 | const bool force = false; | |||||
116 | GetRegisterContext()->InvalidateIfNeeded (force); | |||||
117 | } | |||||
118 | // FIXME: This should probably happen somewhere else. | |||||
119 | SetResumeState(eStateRunning, true); | |||||
120 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD(1u << 2))); | |||||
121 | if (log) | |||||
122 | log->Printf ("POSIXThread::%s (tid = %" PRIi64"l" "i" ") setting thread resume state to running", __FUNCTION__, GetID()); | |||||
123 | } | |||||
124 | ||||||
125 | const char * | |||||
126 | POSIXThread::GetInfo() | |||||
127 | { | |||||
128 | return NULL__null; | |||||
129 | } | |||||
130 | ||||||
131 | void | |||||
132 | POSIXThread::SetName (const char *name) | |||||
133 | { | |||||
134 | m_thread_name_valid = (name && name[0]); | |||||
135 | if (m_thread_name_valid) | |||||
136 | m_thread_name.assign (name); | |||||
137 | else | |||||
138 | m_thread_name.clear(); | |||||
139 | } | |||||
140 | ||||||
141 | const char * | |||||
142 | POSIXThread::GetName () | |||||
143 | { | |||||
144 | if (!m_thread_name_valid) | |||||
145 | { | |||||
146 | llvm::SmallString<32> thread_name; | |||||
147 | HostNativeThread::GetName(GetID(), thread_name); | |||||
148 | m_thread_name = thread_name.c_str(); | |||||
149 | m_thread_name_valid = true; | |||||
150 | } | |||||
151 | ||||||
152 | if (m_thread_name.empty()) | |||||
153 | return NULL__null; | |||||
154 | return m_thread_name.c_str(); | |||||
155 | } | |||||
156 | ||||||
157 | lldb::RegisterContextSP | |||||
158 | POSIXThread::GetRegisterContext() | |||||
159 | { | |||||
160 | if (!m_reg_context_sp) | |||||
161 | { | |||||
162 | m_posix_thread = NULL__null; | |||||
163 | ||||||
164 | RegisterInfoInterface *reg_interface = NULL__null; | |||||
165 | const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture(); | |||||
166 | ||||||
167 | switch (target_arch.GetTriple().getOS()) | |||||
168 | { | |||||
169 | case llvm::Triple::FreeBSD: | |||||
170 | switch (target_arch.GetMachine()) | |||||
171 | { | |||||
172 | case llvm::Triple::ppc: | |||||
173 | #ifndef __powerpc64__ | |||||
174 | reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch); | |||||
175 | break; | |||||
176 | #endif | |||||
177 | case llvm::Triple::ppc64: | |||||
178 | reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch); | |||||
179 | break; | |||||
180 | case llvm::Triple::mips64: | |||||
181 | reg_interface = new RegisterContextFreeBSD_mips64(target_arch); | |||||
182 | break; | |||||
183 | case llvm::Triple::x86: | |||||
184 | reg_interface = new RegisterContextFreeBSD_i386(target_arch); | |||||
185 | break; | |||||
186 | case llvm::Triple::x86_64: | |||||
187 | reg_interface = new RegisterContextFreeBSD_x86_64(target_arch); | |||||
188 | break; | |||||
189 | default: | |||||
190 | break; | |||||
191 | } | |||||
192 | break; | |||||
193 | ||||||
194 | case llvm::Triple::Linux: | |||||
195 | switch (target_arch.GetMachine()) | |||||
196 | { | |||||
197 | case llvm::Triple::aarch64: | |||||
198 | assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host")(((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host") ? static_cast <void> (0) : __assert_fail ("(HostInfo::GetArchitecture().GetAddressByteSize() == 8) && \"Register setting path assumes this is a 64-bit host\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 198, __PRETTY_FUNCTION__)); | |||||
199 | reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm64(target_arch)); | |||||
200 | break; | |||||
201 | case llvm::Triple::x86: | |||||
202 | case llvm::Triple::x86_64: | |||||
203 | if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) | |||||
204 | { | |||||
205 | // 32-bit hosts run with a RegisterContextLinux_i386 context. | |||||
206 | reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_i386(target_arch)); | |||||
207 | } | |||||
208 | else | |||||
209 | { | |||||
210 | assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&(((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host") ? static_cast <void> (0) : __assert_fail ("(HostInfo::GetArchitecture().GetAddressByteSize() == 8) && \"Register setting path assumes this is a 64-bit host\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 211, __PRETTY_FUNCTION__)) | |||||
211 | "Register setting path assumes this is a 64-bit host")(((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host") ? static_cast <void> (0) : __assert_fail ("(HostInfo::GetArchitecture().GetAddressByteSize() == 8) && \"Register setting path assumes this is a 64-bit host\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 211, __PRETTY_FUNCTION__)); | |||||
212 | // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context. | |||||
213 | reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_x86_64(target_arch)); | |||||
214 | } | |||||
215 | break; | |||||
216 | default: | |||||
217 | break; | |||||
218 | } | |||||
219 | ||||||
220 | default: | |||||
221 | break; | |||||
222 | } | |||||
223 | ||||||
224 | assert(reg_interface && "OS or CPU not supported!")((reg_interface && "OS or CPU not supported!") ? static_cast <void> (0) : __assert_fail ("reg_interface && \"OS or CPU not supported!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 224, __PRETTY_FUNCTION__)); | |||||
225 | ||||||
226 | switch (target_arch.GetMachine()) | |||||
227 | { | |||||
228 | case llvm::Triple::aarch64: | |||||
229 | { | |||||
230 | RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface); | |||||
231 | m_posix_thread = reg_ctx; | |||||
232 | m_reg_context_sp.reset(reg_ctx); | |||||
233 | break; | |||||
234 | } | |||||
235 | case llvm::Triple::mips64: | |||||
236 | { | |||||
237 | RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface); | |||||
238 | m_posix_thread = reg_ctx; | |||||
239 | m_reg_context_sp.reset(reg_ctx); | |||||
240 | break; | |||||
241 | } | |||||
242 | case llvm::Triple::ppc: | |||||
243 | case llvm::Triple::ppc64: | |||||
244 | { | |||||
245 | RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, reg_interface); | |||||
246 | m_posix_thread = reg_ctx; | |||||
247 | m_reg_context_sp.reset(reg_ctx); | |||||
248 | break; | |||||
249 | } | |||||
250 | case llvm::Triple::x86: | |||||
251 | case llvm::Triple::x86_64: | |||||
252 | { | |||||
253 | RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface); | |||||
254 | m_posix_thread = reg_ctx; | |||||
255 | m_reg_context_sp.reset(reg_ctx); | |||||
256 | break; | |||||
257 | } | |||||
258 | default: | |||||
259 | break; | |||||
260 | } | |||||
261 | } | |||||
262 | return m_reg_context_sp; | |||||
| ||||||
263 | } | |||||
264 | ||||||
265 | lldb::RegisterContextSP | |||||
266 | POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) | |||||
267 | { | |||||
268 | lldb::RegisterContextSP reg_ctx_sp; | |||||
269 | uint32_t concrete_frame_idx = 0; | |||||
270 | ||||||
271 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD(1u << 2))); | |||||
272 | if (log && log->GetMask().Test(POSIX_LOG_VERBOSE(1u << 0))) | |||||
273 | log->Printf ("POSIXThread::%s ()", __FUNCTION__); | |||||
274 | ||||||
275 | if (frame) | |||||
276 | concrete_frame_idx = frame->GetConcreteFrameIndex(); | |||||
277 | ||||||
278 | if (concrete_frame_idx == 0) | |||||
279 | reg_ctx_sp = GetRegisterContext(); | |||||
280 | else | |||||
281 | { | |||||
282 | assert(GetUnwinder())((GetUnwinder()) ? static_cast<void> (0) : __assert_fail ("GetUnwinder()", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 282, __PRETTY_FUNCTION__)); | |||||
283 | reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); | |||||
284 | } | |||||
285 | ||||||
286 | return reg_ctx_sp; | |||||
287 | } | |||||
288 | ||||||
289 | lldb::addr_t | |||||
290 | POSIXThread::GetThreadPointer () | |||||
291 | { | |||||
292 | ProcessMonitor &monitor = GetMonitor(); | |||||
293 | addr_t addr; | |||||
294 | if (monitor.ReadThreadPointer (GetID(), addr)) | |||||
295 | return addr; | |||||
296 | else | |||||
297 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||||
298 | } | |||||
299 | ||||||
300 | bool | |||||
301 | POSIXThread::CalculateStopInfo() | |||||
302 | { | |||||
303 | SetStopInfo (m_stop_info_sp); | |||||
304 | return true; | |||||
305 | } | |||||
306 | ||||||
307 | Unwind * | |||||
308 | POSIXThread::GetUnwinder() | |||||
309 | { | |||||
310 | if (m_unwinder_ap.get() == NULL__null) | |||||
311 | m_unwinder_ap.reset(new UnwindLLDB(*this)); | |||||
312 | ||||||
313 | return m_unwinder_ap.get(); | |||||
314 | } | |||||
315 | ||||||
316 | // Overridden by FreeBSDThread; this is used only on Linux. | |||||
317 | void | |||||
318 | POSIXThread::WillResume(lldb::StateType resume_state) | |||||
319 | { | |||||
320 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD(1u << 2))); | |||||
321 | if (log) | |||||
322 | log->Printf ("POSIXThread::%s (tid = %" PRIi64"l" "i" ") setting thread resume state to %s", __FUNCTION__, GetID(), StateAsCString(resume_state)); | |||||
323 | // TODO: the line below shouldn't really be done, but | |||||
324 | // the POSIXThread might rely on this so I will leave this in for now | |||||
325 | SetResumeState(resume_state); | |||||
326 | } | |||||
327 | ||||||
328 | void | |||||
329 | POSIXThread::DidStop() | |||||
330 | { | |||||
331 | // Don't set the thread state to stopped unless we really stopped. | |||||
332 | } | |||||
333 | ||||||
334 | bool | |||||
335 | POSIXThread::Resume() | |||||
336 | { | |||||
337 | lldb::StateType resume_state = GetResumeState(); | |||||
338 | ProcessMonitor &monitor = GetMonitor(); | |||||
339 | bool status; | |||||
340 | ||||||
341 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD(1u << 2))); | |||||
342 | if (log) | |||||
343 | log->Printf ("POSIXThread::%s (), resume_state = %s", __FUNCTION__, | |||||
344 | StateAsCString(resume_state)); | |||||
345 | ||||||
346 | switch (resume_state) | |||||
347 | { | |||||
348 | default: | |||||
349 | assert(false && "Unexpected state for resume!")((false && "Unexpected state for resume!") ? static_cast <void> (0) : __assert_fail ("false && \"Unexpected state for resume!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 349, __PRETTY_FUNCTION__)); | |||||
350 | status = false; | |||||
351 | break; | |||||
352 | ||||||
353 | case lldb::eStateRunning: | |||||
354 | SetState(resume_state); | |||||
355 | status = monitor.Resume(GetID(), GetResumeSignal()); | |||||
356 | break; | |||||
357 | ||||||
358 | case lldb::eStateStepping: | |||||
359 | SetState(resume_state); | |||||
360 | status = monitor.SingleStep(GetID(), GetResumeSignal()); | |||||
361 | break; | |||||
362 | case lldb::eStateStopped: | |||||
363 | case lldb::eStateSuspended: | |||||
364 | status = true; | |||||
365 | break; | |||||
366 | } | |||||
367 | ||||||
368 | return status; | |||||
369 | } | |||||
370 | ||||||
371 | void | |||||
372 | POSIXThread::Notify(const ProcessMessage &message) | |||||
373 | { | |||||
374 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD(1u << 2))); | |||||
375 | if (log) | |||||
376 | log->Printf ("POSIXThread::%s () message kind = '%s' for tid %" PRIu64"l" "u", | |||||
377 | __FUNCTION__, message.PrintKind(), GetID()); | |||||
378 | ||||||
379 | switch (message.GetKind()) | |||||
380 | { | |||||
381 | default: | |||||
382 | assert(false && "Unexpected message kind!")((false && "Unexpected message kind!") ? static_cast< void> (0) : __assert_fail ("false && \"Unexpected message kind!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 382, __PRETTY_FUNCTION__)); | |||||
383 | break; | |||||
384 | ||||||
385 | case ProcessMessage::eExitMessage: | |||||
386 | // Nothing to be done. | |||||
387 | break; | |||||
388 | ||||||
389 | case ProcessMessage::eLimboMessage: | |||||
390 | LimboNotify(message); | |||||
391 | break; | |||||
392 | ||||||
393 | case ProcessMessage::eSignalMessage: | |||||
394 | SignalNotify(message); | |||||
395 | break; | |||||
396 | ||||||
397 | case ProcessMessage::eSignalDeliveredMessage: | |||||
398 | SignalDeliveredNotify(message); | |||||
399 | break; | |||||
400 | ||||||
401 | case ProcessMessage::eTraceMessage: | |||||
402 | TraceNotify(message); | |||||
403 | break; | |||||
404 | ||||||
405 | case ProcessMessage::eBreakpointMessage: | |||||
406 | BreakNotify(message); | |||||
407 | break; | |||||
408 | ||||||
409 | case ProcessMessage::eWatchpointMessage: | |||||
410 | WatchNotify(message); | |||||
411 | break; | |||||
412 | ||||||
413 | case ProcessMessage::eCrashMessage: | |||||
414 | CrashNotify(message); | |||||
415 | break; | |||||
416 | ||||||
417 | case ProcessMessage::eNewThreadMessage: | |||||
418 | ThreadNotify(message); | |||||
419 | break; | |||||
420 | ||||||
421 | case ProcessMessage::eExecMessage: | |||||
422 | ExecNotify(message); | |||||
423 | break; | |||||
424 | } | |||||
425 | } | |||||
426 | ||||||
427 | bool | |||||
428 | POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp) | |||||
429 | { | |||||
430 | bool wp_set = false; | |||||
431 | if (wp) | |||||
432 | { | |||||
433 | addr_t wp_addr = wp->GetLoadAddress(); | |||||
434 | size_t wp_size = wp->GetByteSize(); | |||||
435 | bool wp_read = wp->WatchpointRead(); | |||||
436 | bool wp_write = wp->WatchpointWrite(); | |||||
437 | uint32_t wp_hw_index = wp->GetHardwareIndex(); | |||||
438 | POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); | |||||
439 | if (reg_ctx) | |||||
440 | wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size, | |||||
441 | wp_read, wp_write, | |||||
442 | wp_hw_index); | |||||
443 | } | |||||
444 | return wp_set; | |||||
445 | } | |||||
446 | ||||||
447 | bool | |||||
448 | POSIXThread::DisableHardwareWatchpoint(Watchpoint *wp) | |||||
449 | { | |||||
450 | bool result = false; | |||||
451 | if (wp) | |||||
452 | { | |||||
453 | lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); | |||||
454 | if (reg_ctx_sp.get()) | |||||
455 | result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex()); | |||||
456 | } | |||||
457 | return result; | |||||
458 | } | |||||
459 | ||||||
460 | uint32_t | |||||
461 | POSIXThread::NumSupportedHardwareWatchpoints() | |||||
462 | { | |||||
463 | lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); | |||||
464 | if (reg_ctx_sp.get()) | |||||
465 | return reg_ctx_sp->NumSupportedHardwareWatchpoints(); | |||||
466 | return 0; | |||||
467 | } | |||||
468 | ||||||
469 | uint32_t | |||||
470 | POSIXThread::FindVacantWatchpointIndex() | |||||
471 | { | |||||
472 | uint32_t hw_index = LLDB_INVALID_INDEX32(4294967295U); | |||||
473 | uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); | |||||
474 | uint32_t wp_idx; | |||||
475 | POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); | |||||
476 | if (reg_ctx) | |||||
477 | { | |||||
478 | for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) | |||||
479 | { | |||||
480 | if (reg_ctx->IsWatchpointVacant(wp_idx)) | |||||
481 | { | |||||
482 | hw_index = wp_idx; | |||||
483 | break; | |||||
484 | } | |||||
485 | } | |||||
486 | } | |||||
487 | return hw_index; | |||||
488 | } | |||||
489 | ||||||
490 | void | |||||
491 | POSIXThread::BreakNotify(const ProcessMessage &message) | |||||
492 | { | |||||
493 | bool status; | |||||
494 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD(1u << 2))); | |||||
495 | ||||||
496 | assert(GetRegisterContext())((GetRegisterContext()) ? static_cast<void> (0) : __assert_fail ("GetRegisterContext()", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 496, __PRETTY_FUNCTION__)); | |||||
| ||||||
497 | status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint(); | |||||
498 | assert(status && "Breakpoint update failed!")((status && "Breakpoint update failed!") ? static_cast <void> (0) : __assert_fail ("status && \"Breakpoint update failed!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 498, __PRETTY_FUNCTION__)); | |||||
499 | ||||||
500 | // With our register state restored, resolve the breakpoint object | |||||
501 | // corresponding to our current PC. | |||||
502 | assert(GetRegisterContext())((GetRegisterContext()) ? static_cast<void> (0) : __assert_fail ("GetRegisterContext()", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 502, __PRETTY_FUNCTION__)); | |||||
503 | lldb::addr_t pc = GetRegisterContext()->GetPC(); | |||||
504 | if (log) | |||||
505 | log->Printf ("POSIXThread::%s () PC=0x%8.8" PRIx64"l" "x", __FUNCTION__, pc); | |||||
506 | lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); | |||||
507 | ||||||
508 | // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, | |||||
509 | // we create a stop reason with should_stop=false. If there is no breakpoint location, then report | |||||
510 | // an invalid stop reason. We don't need to worry about stepping over the breakpoint here, that will | |||||
511 | // be taken care of when the thread resumes and notices that there's a breakpoint under the pc. | |||||
512 | if (bp_site) | |||||
513 | { | |||||
514 | lldb::break_id_t bp_id = bp_site->GetID(); | |||||
515 | if (bp_site->ValidForThisThread(this)) | |||||
516 | SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id)); | |||||
517 | else | |||||
518 | { | |||||
519 | const bool should_stop = false; | |||||
520 | SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop)); | |||||
521 | } | |||||
522 | } | |||||
523 | else | |||||
524 | SetStopInfo(StopInfoSP()); | |||||
525 | } | |||||
526 | ||||||
527 | void | |||||
528 | POSIXThread::WatchNotify(const ProcessMessage &message) | |||||
529 | { | |||||
530 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD(1u << 2))); | |||||
531 | ||||||
532 | lldb::addr_t halt_addr = message.GetHWAddress(); | |||||
533 | if (log) | |||||
534 | log->Printf ("POSIXThread::%s () Hardware Watchpoint Address = 0x%8.8" | |||||
535 | PRIx64"l" "x", __FUNCTION__, halt_addr); | |||||
536 | ||||||
537 | POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); | |||||
538 | if (reg_ctx) | |||||
539 | { | |||||
540 | uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); | |||||
541 | uint32_t wp_idx; | |||||
542 | for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) | |||||
543 | { | |||||
544 | if (reg_ctx->IsWatchpointHit(wp_idx)) | |||||
545 | { | |||||
546 | // Clear the watchpoint hit here | |||||
547 | reg_ctx->ClearWatchpointHits(); | |||||
548 | break; | |||||
549 | } | |||||
550 | } | |||||
551 | ||||||
552 | if (wp_idx == num_hw_wps) | |||||
553 | return; | |||||
554 | ||||||
555 | Target &target = GetProcess()->GetTarget(); | |||||
556 | lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx); | |||||
557 | const WatchpointList &wp_list = target.GetWatchpointList(); | |||||
558 | lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr); | |||||
559 | ||||||
560 | assert(wp_sp.get() && "No watchpoint found")((wp_sp.get() && "No watchpoint found") ? static_cast <void> (0) : __assert_fail ("wp_sp.get() && \"No watchpoint found\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 560, __PRETTY_FUNCTION__)); | |||||
561 | SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this, | |||||
562 | wp_sp->GetID())); | |||||
563 | } | |||||
564 | } | |||||
565 | ||||||
566 | void | |||||
567 | POSIXThread::TraceNotify(const ProcessMessage &message) | |||||
568 | { | |||||
569 | POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); | |||||
570 | if (reg_ctx) | |||||
571 | { | |||||
572 | uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); | |||||
573 | uint32_t wp_idx; | |||||
574 | for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) | |||||
575 | { | |||||
576 | if (reg_ctx->IsWatchpointHit(wp_idx)) | |||||
577 | { | |||||
578 | WatchNotify(message); | |||||
579 | return; | |||||
580 | } | |||||
581 | } | |||||
582 | } | |||||
583 | ||||||
584 | SetStopInfo (StopInfo::CreateStopReasonToTrace(*this)); | |||||
585 | } | |||||
586 | ||||||
587 | void | |||||
588 | POSIXThread::LimboNotify(const ProcessMessage &message) | |||||
589 | { | |||||
590 | SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this))); | |||||
591 | } | |||||
592 | ||||||
593 | void | |||||
594 | POSIXThread::SignalNotify(const ProcessMessage &message) | |||||
595 | { | |||||
596 | int signo = message.GetSignal(); | |||||
597 | SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); | |||||
598 | } | |||||
599 | ||||||
600 | void | |||||
601 | POSIXThread::SignalDeliveredNotify(const ProcessMessage &message) | |||||
602 | { | |||||
603 | int signo = message.GetSignal(); | |||||
604 | SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); | |||||
605 | } | |||||
606 | ||||||
607 | void | |||||
608 | POSIXThread::CrashNotify(const ProcessMessage &message) | |||||
609 | { | |||||
610 | // FIXME: Update stop reason as per bugzilla 14598 | |||||
611 | int signo = message.GetSignal(); | |||||
612 | ||||||
613 | assert(message.GetKind() == ProcessMessage::eCrashMessage)((message.GetKind() == ProcessMessage::eCrashMessage) ? static_cast <void> (0) : __assert_fail ("message.GetKind() == ProcessMessage::eCrashMessage" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 613, __PRETTY_FUNCTION__)); | |||||
614 | ||||||
615 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD(1u << 2))); | |||||
616 | if (log) | |||||
617 | log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", | |||||
618 | __FUNCTION__, signo, message.PrintCrashReason()); | |||||
619 | ||||||
620 | SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo, | |||||
621 | message.GetCrashReason(), | |||||
622 | message.GetFaultAddress()))); | |||||
623 | } | |||||
624 | ||||||
625 | void | |||||
626 | POSIXThread::ThreadNotify(const ProcessMessage &message) | |||||
627 | { | |||||
628 | SetStopInfo (lldb::StopInfoSP(new POSIXNewThreadStopInfo(*this))); | |||||
629 | } | |||||
630 | ||||||
631 | unsigned | |||||
632 | POSIXThread::GetRegisterIndexFromOffset(unsigned offset) | |||||
633 | { | |||||
634 | unsigned reg = LLDB_INVALID_REGNUM(4294967295U); | |||||
635 | ArchSpec arch = HostInfo::GetArchitecture(); | |||||
636 | ||||||
637 | switch (arch.GetMachine()) | |||||
638 | { | |||||
639 | default: | |||||
640 | llvm_unreachable("CPU type not supported!")::llvm::llvm_unreachable_internal("CPU type not supported!", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 640); | |||||
641 | break; | |||||
642 | ||||||
643 | case llvm::Triple::aarch64: | |||||
644 | case llvm::Triple::mips64: | |||||
645 | case llvm::Triple::ppc: | |||||
646 | case llvm::Triple::ppc64: | |||||
647 | case llvm::Triple::x86: | |||||
648 | case llvm::Triple::x86_64: | |||||
649 | { | |||||
650 | POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); | |||||
651 | reg = reg_ctx->GetRegisterIndexFromOffset(offset); | |||||
652 | } | |||||
653 | break; | |||||
654 | } | |||||
655 | return reg; | |||||
656 | } | |||||
657 | ||||||
658 | void | |||||
659 | POSIXThread::ExecNotify(const ProcessMessage &message) | |||||
660 | { | |||||
661 | SetStopInfo (StopInfo::CreateStopReasonWithExec(*this)); | |||||
662 | } | |||||
663 | ||||||
664 | const char * | |||||
665 | POSIXThread::GetRegisterName(unsigned reg) | |||||
666 | { | |||||
667 | const char * name = nullptr; | |||||
668 | ArchSpec arch = HostInfo::GetArchitecture(); | |||||
669 | ||||||
670 | switch (arch.GetMachine()) | |||||
671 | { | |||||
672 | default: | |||||
673 | assert(false && "CPU type not supported!")((false && "CPU type not supported!") ? static_cast< void> (0) : __assert_fail ("false && \"CPU type not supported!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224369/tools/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp" , 673, __PRETTY_FUNCTION__)); | |||||
674 | break; | |||||
675 | ||||||
676 | case llvm::Triple::aarch64: | |||||
677 | case llvm::Triple::mips64: | |||||
678 | case llvm::Triple::ppc: | |||||
679 | case llvm::Triple::ppc64: | |||||
680 | case llvm::Triple::x86: | |||||
681 | case llvm::Triple::x86_64: | |||||
682 | name = GetRegisterContext()->GetRegisterName(reg); | |||||
683 | break; | |||||
684 | } | |||||
685 | return name; | |||||
686 | } | |||||
687 | ||||||
688 | const char * | |||||
689 | POSIXThread::GetRegisterNameFromOffset(unsigned offset) | |||||
690 | { | |||||
691 | return GetRegisterName(GetRegisterIndexFromOffset(offset)); | |||||
692 | } | |||||
693 |