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