blob: de7c8fc2620bcf754fb8bea14742408368be68da [file] [log] [blame]
Todd Fialaaf245d12014-06-30 21:05:18 +00001//===-- NativeThreadLinux.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 "NativeThreadLinux.h"
11
12#include <signal.h>
Chaoren Lin18fe6402015-02-03 01:51:47 +000013#include <sstream>
Todd Fialaaf245d12014-06-30 21:05:18 +000014
15#include "NativeProcessLinux.h"
Tamas Berghammer1e209fc2015-03-13 11:36:47 +000016#include "NativeRegisterContextLinux_arm64.h"
Todd Fiala2850b1b2014-06-30 23:51:35 +000017#include "NativeRegisterContextLinux_x86_64.h"
Mohit K. Bhakkad3df471c2015-03-17 11:43:56 +000018#include "NativeRegisterContextLinux_mips64.h"
Todd Fiala2850b1b2014-06-30 23:51:35 +000019
Todd Fialaaf245d12014-06-30 21:05:18 +000020#include "lldb/Core/Log.h"
21#include "lldb/Core/State.h"
22#include "lldb/Host/Host.h"
Zachary Turner13b18262014-08-20 16:42:51 +000023#include "lldb/Host/HostInfo.h"
Zachary Turner39de3112014-09-09 20:54:56 +000024#include "lldb/Host/HostNativeThread.h"
Todd Fialaaf245d12014-06-30 21:05:18 +000025#include "lldb/lldb-enumerations.h"
26#include "lldb/lldb-private-log.h"
Zachary Turner39de3112014-09-09 20:54:56 +000027
28#include "llvm/ADT/SmallString.h"
29
Chaoren Lin28e57422015-02-03 01:51:25 +000030#include "Plugins/Process/POSIX/CrashReason.h"
31
Todd Fialab71e89e2014-08-29 16:01:35 +000032#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
Todd Fialaaf245d12014-06-30 21:05:18 +000033#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
34#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
Mohit K. Bhakkad3df471c2015-03-17 11:43:56 +000035#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
Todd Fialaaf245d12014-06-30 21:05:18 +000036#include "Plugins/Process/Utility/RegisterInfoInterface.h"
37
38using namespace lldb;
39using namespace lldb_private;
40
41namespace
42{
43 void LogThreadStopInfo (Log &log, const ThreadStopInfo &stop_info, const char *const header)
44 {
45 switch (stop_info.reason)
46 {
47 case eStopReasonSignal:
Chaoren Linae29d392015-02-03 01:50:46 +000048 log.Printf ("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
Todd Fialaaf245d12014-06-30 21:05:18 +000049 return;
50 case eStopReasonException:
Chaoren Linae29d392015-02-03 01:50:46 +000051 log.Printf ("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header, stop_info.details.exception.type);
Todd Fialaa9882ce2014-08-28 15:46:54 +000052 return;
53 case eStopReasonExec:
54 log.Printf ("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
Todd Fialaaf245d12014-06-30 21:05:18 +000055 return;
56 default:
Todd Fialaa9882ce2014-08-28 15:46:54 +000057 log.Printf ("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header, static_cast<uint32_t> (stop_info.reason));
Todd Fialaaf245d12014-06-30 21:05:18 +000058 }
59 }
60}
61
62NativeThreadLinux::NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid) :
63 NativeThreadProtocol (process, tid),
64 m_state (StateType::eStateInvalid),
65 m_stop_info (),
Chaoren Lin28e57422015-02-03 01:51:25 +000066 m_reg_context_sp (),
67 m_stop_description ()
Todd Fialaaf245d12014-06-30 21:05:18 +000068{
69}
70
Todd Fiala7206c6d2014-09-12 22:51:49 +000071std::string
Todd Fialaaf245d12014-06-30 21:05:18 +000072NativeThreadLinux::GetName()
73{
74 NativeProcessProtocolSP process_sp = m_process_wp.lock ();
75 if (!process_sp)
76 return "<unknown: no process>";
77
78 // const NativeProcessLinux *const process = reinterpret_cast<NativeProcessLinux*> (process_sp->get ());
Zachary Turner39de3112014-09-09 20:54:56 +000079 llvm::SmallString<32> thread_name;
80 HostNativeThread::GetName(GetID(), thread_name);
81 return thread_name.c_str();
Todd Fialaaf245d12014-06-30 21:05:18 +000082}
83
84lldb::StateType
85NativeThreadLinux::GetState ()
86{
87 return m_state;
88}
89
90
91bool
Chaoren Lin28e57422015-02-03 01:51:25 +000092NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info, std::string& description)
Todd Fialaaf245d12014-06-30 21:05:18 +000093{
94 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
Chaoren Lin28e57422015-02-03 01:51:25 +000095
96 description.clear();
97
Todd Fialaaf245d12014-06-30 21:05:18 +000098 switch (m_state)
99 {
100 case eStateStopped:
101 case eStateCrashed:
102 case eStateExited:
103 case eStateSuspended:
104 case eStateUnloaded:
105 if (log)
Todd Fialaa9882ce2014-08-28 15:46:54 +0000106 LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread:");
Todd Fialaaf245d12014-06-30 21:05:18 +0000107 stop_info = m_stop_info;
Chaoren Lin18fe6402015-02-03 01:51:47 +0000108 switch (m_stop_info.reason)
109 {
110 case StopReason::eStopReasonException:
111 case StopReason::eStopReasonBreakpoint:
112 case StopReason::eStopReasonWatchpoint:
113 description = m_stop_description;
114 default:
115 break;
116 }
Todd Fialaaf245d12014-06-30 21:05:18 +0000117 if (log)
Todd Fialaa9882ce2014-08-28 15:46:54 +0000118 LogThreadStopInfo (*log, stop_info, "returned stop_info:");
Chaoren Lin28e57422015-02-03 01:51:25 +0000119
Todd Fialaaf245d12014-06-30 21:05:18 +0000120 return true;
121
122 case eStateInvalid:
123 case eStateConnected:
124 case eStateAttaching:
125 case eStateLaunching:
126 case eStateRunning:
127 case eStateStepping:
128 case eStateDetached:
Todd Fialaaf245d12014-06-30 21:05:18 +0000129 if (log)
130 {
131 log->Printf ("NativeThreadLinux::%s tid %" PRIu64 " in state %s cannot answer stop reason",
132 __FUNCTION__, GetID (), StateAsCString (m_state));
133 }
134 return false;
135 }
David Majnemer8faf9372014-09-16 06:34:29 +0000136 llvm_unreachable("unhandled StateType!");
Todd Fialaaf245d12014-06-30 21:05:18 +0000137}
138
139lldb_private::NativeRegisterContextSP
140NativeThreadLinux::GetRegisterContext ()
141{
142 // Return the register context if we already created it.
143 if (m_reg_context_sp)
144 return m_reg_context_sp;
145
146 // First select the appropriate RegisterInfoInterface.
147 RegisterInfoInterface *reg_interface = nullptr;
148 NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
149 if (!m_process_sp)
150 return NativeRegisterContextSP ();
151
152 ArchSpec target_arch;
153 if (!m_process_sp->GetArchitecture (target_arch))
154 return NativeRegisterContextSP ();
155
156 switch (target_arch.GetTriple().getOS())
157 {
158 case llvm::Triple::Linux:
159 switch (target_arch.GetMachine())
160 {
Todd Fialab71e89e2014-08-29 16:01:35 +0000161 case llvm::Triple::aarch64:
162 assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host");
163 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm64(target_arch));
164 break;
Todd Fialaaf245d12014-06-30 21:05:18 +0000165 case llvm::Triple::x86:
166 case llvm::Triple::x86_64:
Zachary Turner13b18262014-08-20 16:42:51 +0000167 if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
Todd Fialaaf245d12014-06-30 21:05:18 +0000168 {
169 // 32-bit hosts run with a RegisterContextLinux_i386 context.
170 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_i386(target_arch));
171 }
172 else
173 {
Zachary Turner13b18262014-08-20 16:42:51 +0000174 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
175 "Register setting path assumes this is a 64-bit host");
Todd Fialaaf245d12014-06-30 21:05:18 +0000176 // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context.
177 reg_interface = static_cast<RegisterInfoInterface*> (new RegisterContextLinux_x86_64 (target_arch));
178 }
179 break;
Mohit K. Bhakkad3df471c2015-03-17 11:43:56 +0000180 case llvm::Triple::mips64:
181 case llvm::Triple::mips64el:
182 assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8)
183 && "Register setting path assumes this is a 64-bit host");
184 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_mips64 (target_arch));
185 break;
Todd Fialaaf245d12014-06-30 21:05:18 +0000186 default:
187 break;
188 }
189 break;
190 default:
191 break;
192 }
193
194 assert(reg_interface && "OS or CPU not supported!");
195 if (!reg_interface)
196 return NativeRegisterContextSP ();
197
198 // Now create the register context.
199 switch (target_arch.GetMachine())
200 {
201#if 0
202 case llvm::Triple::mips64:
203 {
204 RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
205 m_posix_thread = reg_ctx;
206 m_reg_context_sp.reset(reg_ctx);
207 break;
208 }
209#endif
Mohit K. Bhakkad3df471c2015-03-17 11:43:56 +0000210 case llvm::Triple::mips64:
211 case llvm::Triple::mips64el:
212 {
213 const uint32_t concrete_frame_idx = 0;
214 m_reg_context_sp.reset (new NativeRegisterContextLinux_mips64 (*this, concrete_frame_idx, reg_interface));
215 break;
216 }
Tamas Berghammer1e209fc2015-03-13 11:36:47 +0000217 case llvm::Triple::aarch64:
218 {
219 const uint32_t concrete_frame_idx = 0;
220 m_reg_context_sp.reset (new NativeRegisterContextLinux_arm64(*this, concrete_frame_idx, reg_interface));
221 break;
222 }
Todd Fialaaf245d12014-06-30 21:05:18 +0000223 case llvm::Triple::x86:
Todd Fialaaf245d12014-06-30 21:05:18 +0000224 case llvm::Triple::x86_64:
225 {
226 const uint32_t concrete_frame_idx = 0;
227 m_reg_context_sp.reset (new NativeRegisterContextLinux_x86_64(*this, concrete_frame_idx, reg_interface));
228 break;
229 }
230 default:
231 break;
232 }
233
234 return m_reg_context_sp;
235}
236
237Error
238NativeThreadLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
239{
Chaoren Lin18fe6402015-02-03 01:51:47 +0000240 if (!hardware)
241 return Error ("not implemented");
Chaoren Linf591f692015-02-26 19:48:15 +0000242 if (m_state == eStateLaunching)
243 return Error ();
Chaoren Lin18fe6402015-02-03 01:51:47 +0000244 Error error = RemoveWatchpoint(addr);
245 if (error.Fail()) return error;
246 NativeRegisterContextSP reg_ctx = GetRegisterContext ();
247 uint32_t wp_index =
248 reg_ctx->SetHardwareWatchpoint (addr, size, watch_flags);
249 if (wp_index == LLDB_INVALID_INDEX32)
250 return Error ("Setting hardware watchpoint failed.");
251 m_watchpoint_index_map.insert({addr, wp_index});
252 return Error ();
Todd Fialaaf245d12014-06-30 21:05:18 +0000253}
254
255Error
256NativeThreadLinux::RemoveWatchpoint (lldb::addr_t addr)
257{
Chaoren Lin18fe6402015-02-03 01:51:47 +0000258 auto wp = m_watchpoint_index_map.find(addr);
259 if (wp == m_watchpoint_index_map.end())
260 return Error ();
261 uint32_t wp_index = wp->second;
262 m_watchpoint_index_map.erase(wp);
263 if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
264 return Error ();
265 return Error ("Clearing hardware watchpoint failed.");
Todd Fialaaf245d12014-06-30 21:05:18 +0000266}
267
268void
269NativeThreadLinux::SetLaunching ()
270{
271 const StateType new_state = StateType::eStateLaunching;
272 MaybeLogStateChange (new_state);
273 m_state = new_state;
274
275 // Also mark it as stopped since launching temporarily stops the newly created thread
276 // in the ptrace machinery.
277 m_stop_info.reason = StopReason::eStopReasonSignal;
278 m_stop_info.details.signal.signo = SIGSTOP;
279}
280
281
282void
283NativeThreadLinux::SetRunning ()
284{
285 const StateType new_state = StateType::eStateRunning;
286 MaybeLogStateChange (new_state);
287 m_state = new_state;
288
289 m_stop_info.reason = StopReason::eStopReasonNone;
Chaoren Lin28e57422015-02-03 01:51:25 +0000290 m_stop_description.clear();
Chaoren Lin18fe6402015-02-03 01:51:47 +0000291
292 // If watchpoints have been set, but none on this thread,
293 // then this is a new thread. So set all existing watchpoints.
294 if (m_watchpoint_index_map.empty())
295 {
Oleksiy Vyalov8bc34f42015-02-19 17:58:04 +0000296 const auto process_sp = GetProcess();
297 if (process_sp)
Chaoren Lin18fe6402015-02-03 01:51:47 +0000298 {
Oleksiy Vyalov8bc34f42015-02-19 17:58:04 +0000299 const auto &watchpoint_map = process_sp->GetWatchpointMap();
300 if (watchpoint_map.empty()) return;
301 GetRegisterContext()->ClearAllHardwareWatchpoints();
302 for (const auto &pair : watchpoint_map)
303 {
304 const auto& wp = pair.second;
305 SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware);
306 }
Chaoren Lin18fe6402015-02-03 01:51:47 +0000307 }
308 }
Todd Fialaaf245d12014-06-30 21:05:18 +0000309}
310
311void
312NativeThreadLinux::SetStepping ()
313{
314 const StateType new_state = StateType::eStateStepping;
315 MaybeLogStateChange (new_state);
316 m_state = new_state;
317
318 m_stop_info.reason = StopReason::eStopReasonNone;
319}
320
321void
322NativeThreadLinux::SetStoppedBySignal (uint32_t signo)
323{
324 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
325 if (log)
Chaoren Linb8af31d2015-02-03 01:50:51 +0000326 log->Printf ("NativeThreadLinux::%s called with signal 0x%02" PRIx32, __FUNCTION__, signo);
Todd Fialaaf245d12014-06-30 21:05:18 +0000327
328 const StateType new_state = StateType::eStateStopped;
329 MaybeLogStateChange (new_state);
330 m_state = new_state;
331
332 m_stop_info.reason = StopReason::eStopReasonSignal;
333 m_stop_info.details.signal.signo = signo;
334}
335
Todd Fiala511e5cd2014-09-11 23:29:14 +0000336bool
337NativeThreadLinux::IsStopped (int *signo)
338{
339 if (!StateIsStoppedState (m_state, false))
340 return false;
341
342 // If we are stopped by a signal, return the signo.
343 if (signo &&
344 m_state == StateType::eStateStopped &&
345 m_stop_info.reason == StopReason::eStopReasonSignal)
346 {
347 *signo = m_stop_info.details.signal.signo;
348 }
349
350 // Regardless, we are stopped.
351 return true;
352}
353
354
Todd Fialaaf245d12014-06-30 21:05:18 +0000355void
Todd Fialaa9882ce2014-08-28 15:46:54 +0000356NativeThreadLinux::SetStoppedByExec ()
357{
358 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
359 if (log)
360 log->Printf ("NativeThreadLinux::%s()", __FUNCTION__);
361
362 const StateType new_state = StateType::eStateStopped;
363 MaybeLogStateChange (new_state);
364 m_state = new_state;
365
366 m_stop_info.reason = StopReason::eStopReasonExec;
367 m_stop_info.details.signal.signo = SIGSTOP;
368}
369
370void
Todd Fialaaf245d12014-06-30 21:05:18 +0000371NativeThreadLinux::SetStoppedByBreakpoint ()
372{
373 const StateType new_state = StateType::eStateStopped;
374 MaybeLogStateChange (new_state);
375 m_state = new_state;
376
Chaoren Lin28e57422015-02-03 01:51:25 +0000377 m_stop_info.reason = StopReason::eStopReasonBreakpoint;
Todd Fialaaf245d12014-06-30 21:05:18 +0000378 m_stop_info.details.signal.signo = SIGTRAP;
Chaoren Lin18fe6402015-02-03 01:51:47 +0000379 m_stop_description.clear();
380}
381
382void
383NativeThreadLinux::SetStoppedByWatchpoint ()
384{
385 const StateType new_state = StateType::eStateStopped;
386 MaybeLogStateChange (new_state);
387 m_state = new_state;
388
389 m_stop_info.reason = StopReason::eStopReasonWatchpoint;
390 m_stop_info.details.signal.signo = SIGTRAP;
391
392 NativeRegisterContextLinux_x86_64 *reg_ctx =
393 reinterpret_cast<NativeRegisterContextLinux_x86_64*> (GetRegisterContext().get());
394 const uint32_t num_hw_watchpoints =
395 reg_ctx->NumSupportedHardwareWatchpoints();
396
397 m_stop_description.clear ();
398 for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index)
399 if (reg_ctx->IsWatchpointHit(wp_index).Success())
400 {
401 std::ostringstream ostr;
402 ostr << reg_ctx->GetWatchpointAddress(wp_index) << " " << wp_index;
403 m_stop_description = ostr.str();
404 return;
405 }
406 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
407 if (log)
408 {
409 NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
410 lldb::pid_t pid = m_process_sp ? m_process_sp->GetID () : LLDB_INVALID_PROCESS_ID;
411 log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") "
412 "stopped by a watchpoint, but failed to find it",
413 pid, GetID ());
414 }
Todd Fialaaf245d12014-06-30 21:05:18 +0000415}
416
417bool
418NativeThreadLinux::IsStoppedAtBreakpoint ()
419{
Chaoren Lin18fe6402015-02-03 01:51:47 +0000420 return GetState () == StateType::eStateStopped &&
421 m_stop_info.reason == StopReason::eStopReasonBreakpoint;
422}
Todd Fialaaf245d12014-06-30 21:05:18 +0000423
Chaoren Lin18fe6402015-02-03 01:51:47 +0000424bool
425NativeThreadLinux::IsStoppedAtWatchpoint ()
426{
427 return GetState () == StateType::eStateStopped &&
428 m_stop_info.reason == StopReason::eStopReasonWatchpoint;
Todd Fialaaf245d12014-06-30 21:05:18 +0000429}
430
431void
Chaoren Lin28e57422015-02-03 01:51:25 +0000432NativeThreadLinux::SetStoppedByTrace ()
433{
434 const StateType new_state = StateType::eStateStopped;
435 MaybeLogStateChange (new_state);
436 m_state = new_state;
437
438 m_stop_info.reason = StopReason::eStopReasonTrace;
439 m_stop_info.details.signal.signo = SIGTRAP;
440}
441
442void
443NativeThreadLinux::SetCrashedWithException (const siginfo_t& info)
Todd Fialaaf245d12014-06-30 21:05:18 +0000444{
445 const StateType new_state = StateType::eStateCrashed;
446 MaybeLogStateChange (new_state);
447 m_state = new_state;
448
449 m_stop_info.reason = StopReason::eStopReasonException;
Chaoren Lin28e57422015-02-03 01:51:25 +0000450 m_stop_info.details.signal.signo = info.si_signo;
Todd Fialaaf245d12014-06-30 21:05:18 +0000451
Chaoren Lin28e57422015-02-03 01:51:25 +0000452 const auto reason = GetCrashReason (info);
453 m_stop_description = GetCrashReasonString (reason, reinterpret_cast<lldb::addr_t> (info.si_addr));
454}
Todd Fialaaf245d12014-06-30 21:05:18 +0000455
456void
457NativeThreadLinux::SetSuspended ()
458{
459 const StateType new_state = StateType::eStateSuspended;
460 MaybeLogStateChange (new_state);
461 m_state = new_state;
462
463 // FIXME what makes sense here? Do we need a suspended StopReason?
464 m_stop_info.reason = StopReason::eStopReasonNone;
465}
466
467void
468NativeThreadLinux::SetExited ()
469{
470 const StateType new_state = StateType::eStateExited;
471 MaybeLogStateChange (new_state);
472 m_state = new_state;
473
474 m_stop_info.reason = StopReason::eStopReasonThreadExiting;
475}
476
477void
478NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state)
479{
480 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
481 // If we're not logging, we're done.
482 if (!log)
483 return;
484
485 // If this is a state change to the same state, we're done.
486 lldb::StateType old_state = m_state;
487 if (new_state == old_state)
488 return;
489
490 NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
491 lldb::pid_t pid = m_process_sp ? m_process_sp->GetID () : LLDB_INVALID_PROCESS_ID;
492
493 // Log it.
494 log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state));
495}