blob: 455caa1789d475eee5ee391558ea8ef4e7f3b031 [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"
Omair Javaid3f572162015-04-14 07:30:20 +000016#include "NativeRegisterContextLinux_arm.h"
Tamas Berghammer1e209fc2015-03-13 11:36:47 +000017#include "NativeRegisterContextLinux_arm64.h"
Todd Fiala2850b1b2014-06-30 23:51:35 +000018#include "NativeRegisterContextLinux_x86_64.h"
Mohit K. Bhakkad3df471c2015-03-17 11:43:56 +000019#include "NativeRegisterContextLinux_mips64.h"
Todd Fiala2850b1b2014-06-30 23:51:35 +000020
Todd Fialaaf245d12014-06-30 21:05:18 +000021#include "lldb/Core/Log.h"
22#include "lldb/Core/State.h"
23#include "lldb/Host/Host.h"
Zachary Turner13b18262014-08-20 16:42:51 +000024#include "lldb/Host/HostInfo.h"
Zachary Turner39de3112014-09-09 20:54:56 +000025#include "lldb/Host/HostNativeThread.h"
Chaoren Linc16f5dc2015-03-19 23:28:10 +000026#include "lldb/Utility/LLDBAssert.h"
Todd Fialaaf245d12014-06-30 21:05:18 +000027#include "lldb/lldb-enumerations.h"
Zachary Turner39de3112014-09-09 20:54:56 +000028
29#include "llvm/ADT/SmallString.h"
30
Chaoren Lin28e57422015-02-03 01:51:25 +000031#include "Plugins/Process/POSIX/CrashReason.h"
32
Omair Javaid3f572162015-04-14 07:30:20 +000033#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
Todd Fialab71e89e2014-08-29 16:01:35 +000034#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
Todd Fialaaf245d12014-06-30 21:05:18 +000035#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
36#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
Mohit K. Bhakkad3df471c2015-03-17 11:43:56 +000037#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
Todd Fialaaf245d12014-06-30 21:05:18 +000038#include "Plugins/Process/Utility/RegisterInfoInterface.h"
39
40using namespace lldb;
41using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000042using namespace lldb_private::process_linux;
Todd Fialaaf245d12014-06-30 21:05:18 +000043
44namespace
45{
46 void LogThreadStopInfo (Log &log, const ThreadStopInfo &stop_info, const char *const header)
47 {
48 switch (stop_info.reason)
49 {
Pavel Labath12fd3752015-03-20 14:45:13 +000050 case eStopReasonNone:
51 log.Printf ("%s: %s no stop reason", __FUNCTION__, header);
52 return;
53 case eStopReasonTrace:
54 log.Printf ("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
55 return;
56 case eStopReasonBreakpoint:
57 log.Printf ("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
58 return;
59 case eStopReasonWatchpoint:
60 log.Printf ("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
61 return;
Todd Fialaaf245d12014-06-30 21:05:18 +000062 case eStopReasonSignal:
Chaoren Linae29d392015-02-03 01:50:46 +000063 log.Printf ("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
Todd Fialaaf245d12014-06-30 21:05:18 +000064 return;
65 case eStopReasonException:
Chaoren Linae29d392015-02-03 01:50:46 +000066 log.Printf ("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header, stop_info.details.exception.type);
Todd Fialaa9882ce2014-08-28 15:46:54 +000067 return;
68 case eStopReasonExec:
69 log.Printf ("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
Todd Fialaaf245d12014-06-30 21:05:18 +000070 return;
Pavel Labath12fd3752015-03-20 14:45:13 +000071 case eStopReasonPlanComplete:
72 log.Printf ("%s: %s plan complete", __FUNCTION__, header);
73 return;
74 case eStopReasonThreadExiting:
75 log.Printf ("%s: %s thread exiting", __FUNCTION__, header);
76 return;
77 case eStopReasonInstrumentation:
78 log.Printf ("%s: %s instrumentation", __FUNCTION__, header);
79 return;
Todd Fialaaf245d12014-06-30 21:05:18 +000080 default:
Todd Fialaa9882ce2014-08-28 15:46:54 +000081 log.Printf ("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header, static_cast<uint32_t> (stop_info.reason));
Todd Fialaaf245d12014-06-30 21:05:18 +000082 }
83 }
84}
85
86NativeThreadLinux::NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid) :
87 NativeThreadProtocol (process, tid),
88 m_state (StateType::eStateInvalid),
89 m_stop_info (),
Chaoren Lin28e57422015-02-03 01:51:25 +000090 m_reg_context_sp (),
91 m_stop_description ()
Todd Fialaaf245d12014-06-30 21:05:18 +000092{
93}
94
Todd Fiala7206c6d2014-09-12 22:51:49 +000095std::string
Todd Fialaaf245d12014-06-30 21:05:18 +000096NativeThreadLinux::GetName()
97{
98 NativeProcessProtocolSP process_sp = m_process_wp.lock ();
99 if (!process_sp)
100 return "<unknown: no process>";
101
102 // const NativeProcessLinux *const process = reinterpret_cast<NativeProcessLinux*> (process_sp->get ());
Zachary Turner39de3112014-09-09 20:54:56 +0000103 llvm::SmallString<32> thread_name;
104 HostNativeThread::GetName(GetID(), thread_name);
105 return thread_name.c_str();
Todd Fialaaf245d12014-06-30 21:05:18 +0000106}
107
108lldb::StateType
109NativeThreadLinux::GetState ()
110{
111 return m_state;
112}
113
114
115bool
Chaoren Lin28e57422015-02-03 01:51:25 +0000116NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info, std::string& description)
Todd Fialaaf245d12014-06-30 21:05:18 +0000117{
118 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
Chaoren Lin28e57422015-02-03 01:51:25 +0000119
120 description.clear();
121
Todd Fialaaf245d12014-06-30 21:05:18 +0000122 switch (m_state)
123 {
124 case eStateStopped:
125 case eStateCrashed:
126 case eStateExited:
127 case eStateSuspended:
128 case eStateUnloaded:
129 if (log)
Todd Fialaa9882ce2014-08-28 15:46:54 +0000130 LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread:");
Todd Fialaaf245d12014-06-30 21:05:18 +0000131 stop_info = m_stop_info;
Chaoren Lin18fe6402015-02-03 01:51:47 +0000132 switch (m_stop_info.reason)
133 {
134 case StopReason::eStopReasonException:
135 case StopReason::eStopReasonBreakpoint:
136 case StopReason::eStopReasonWatchpoint:
137 description = m_stop_description;
138 default:
139 break;
140 }
Todd Fialaaf245d12014-06-30 21:05:18 +0000141 if (log)
Todd Fialaa9882ce2014-08-28 15:46:54 +0000142 LogThreadStopInfo (*log, stop_info, "returned stop_info:");
Chaoren Lin28e57422015-02-03 01:51:25 +0000143
Todd Fialaaf245d12014-06-30 21:05:18 +0000144 return true;
145
146 case eStateInvalid:
147 case eStateConnected:
148 case eStateAttaching:
149 case eStateLaunching:
150 case eStateRunning:
151 case eStateStepping:
152 case eStateDetached:
Todd Fialaaf245d12014-06-30 21:05:18 +0000153 if (log)
154 {
155 log->Printf ("NativeThreadLinux::%s tid %" PRIu64 " in state %s cannot answer stop reason",
156 __FUNCTION__, GetID (), StateAsCString (m_state));
157 }
158 return false;
159 }
David Majnemer8faf9372014-09-16 06:34:29 +0000160 llvm_unreachable("unhandled StateType!");
Todd Fialaaf245d12014-06-30 21:05:18 +0000161}
162
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000163NativeRegisterContextSP
Todd Fialaaf245d12014-06-30 21:05:18 +0000164NativeThreadLinux::GetRegisterContext ()
165{
166 // Return the register context if we already created it.
167 if (m_reg_context_sp)
168 return m_reg_context_sp;
169
170 // First select the appropriate RegisterInfoInterface.
171 RegisterInfoInterface *reg_interface = nullptr;
172 NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
173 if (!m_process_sp)
174 return NativeRegisterContextSP ();
175
176 ArchSpec target_arch;
177 if (!m_process_sp->GetArchitecture (target_arch))
178 return NativeRegisterContextSP ();
179
180 switch (target_arch.GetTriple().getOS())
181 {
182 case llvm::Triple::Linux:
183 switch (target_arch.GetMachine())
184 {
Todd Fialab71e89e2014-08-29 16:01:35 +0000185 case llvm::Triple::aarch64:
186 assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host");
187 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm64(target_arch));
188 break;
Omair Javaid3f572162015-04-14 07:30:20 +0000189 case llvm::Triple::arm:
190 assert(HostInfo::GetArchitecture ().GetAddressByteSize() == 4);
191 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm(target_arch));
192 break;
Todd Fialaaf245d12014-06-30 21:05:18 +0000193 case llvm::Triple::x86:
194 case llvm::Triple::x86_64:
Zachary Turner13b18262014-08-20 16:42:51 +0000195 if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
Todd Fialaaf245d12014-06-30 21:05:18 +0000196 {
197 // 32-bit hosts run with a RegisterContextLinux_i386 context.
198 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_i386(target_arch));
199 }
200 else
201 {
Zachary Turner13b18262014-08-20 16:42:51 +0000202 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
203 "Register setting path assumes this is a 64-bit host");
Todd Fialaaf245d12014-06-30 21:05:18 +0000204 // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context.
205 reg_interface = static_cast<RegisterInfoInterface*> (new RegisterContextLinux_x86_64 (target_arch));
206 }
207 break;
Mohit K. Bhakkad3df471c2015-03-17 11:43:56 +0000208 case llvm::Triple::mips64:
209 case llvm::Triple::mips64el:
210 assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8)
211 && "Register setting path assumes this is a 64-bit host");
212 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_mips64 (target_arch));
213 break;
Todd Fialaaf245d12014-06-30 21:05:18 +0000214 default:
215 break;
216 }
217 break;
218 default:
219 break;
220 }
221
222 assert(reg_interface && "OS or CPU not supported!");
223 if (!reg_interface)
224 return NativeRegisterContextSP ();
225
226 // Now create the register context.
227 switch (target_arch.GetMachine())
228 {
229#if 0
230 case llvm::Triple::mips64:
231 {
232 RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
233 m_posix_thread = reg_ctx;
234 m_reg_context_sp.reset(reg_ctx);
235 break;
236 }
237#endif
Mohit K. Bhakkad3df471c2015-03-17 11:43:56 +0000238 case llvm::Triple::mips64:
239 case llvm::Triple::mips64el:
240 {
241 const uint32_t concrete_frame_idx = 0;
242 m_reg_context_sp.reset (new NativeRegisterContextLinux_mips64 (*this, concrete_frame_idx, reg_interface));
243 break;
244 }
Tamas Berghammer1e209fc2015-03-13 11:36:47 +0000245 case llvm::Triple::aarch64:
246 {
247 const uint32_t concrete_frame_idx = 0;
248 m_reg_context_sp.reset (new NativeRegisterContextLinux_arm64(*this, concrete_frame_idx, reg_interface));
249 break;
250 }
Omair Javaid3f572162015-04-14 07:30:20 +0000251 case llvm::Triple::arm:
252 {
253 const uint32_t concrete_frame_idx = 0;
254 m_reg_context_sp.reset (new NativeRegisterContextLinux_arm(*this, concrete_frame_idx, reg_interface));
255 break;
256 }
Todd Fialaaf245d12014-06-30 21:05:18 +0000257 case llvm::Triple::x86:
Todd Fialaaf245d12014-06-30 21:05:18 +0000258 case llvm::Triple::x86_64:
259 {
260 const uint32_t concrete_frame_idx = 0;
261 m_reg_context_sp.reset (new NativeRegisterContextLinux_x86_64(*this, concrete_frame_idx, reg_interface));
262 break;
263 }
264 default:
265 break;
266 }
267
268 return m_reg_context_sp;
269}
270
271Error
272NativeThreadLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
273{
Chaoren Lin18fe6402015-02-03 01:51:47 +0000274 if (!hardware)
275 return Error ("not implemented");
Chaoren Linf591f692015-02-26 19:48:15 +0000276 if (m_state == eStateLaunching)
277 return Error ();
Chaoren Lin18fe6402015-02-03 01:51:47 +0000278 Error error = RemoveWatchpoint(addr);
279 if (error.Fail()) return error;
280 NativeRegisterContextSP reg_ctx = GetRegisterContext ();
281 uint32_t wp_index =
282 reg_ctx->SetHardwareWatchpoint (addr, size, watch_flags);
283 if (wp_index == LLDB_INVALID_INDEX32)
284 return Error ("Setting hardware watchpoint failed.");
285 m_watchpoint_index_map.insert({addr, wp_index});
286 return Error ();
Todd Fialaaf245d12014-06-30 21:05:18 +0000287}
288
289Error
290NativeThreadLinux::RemoveWatchpoint (lldb::addr_t addr)
291{
Chaoren Lin18fe6402015-02-03 01:51:47 +0000292 auto wp = m_watchpoint_index_map.find(addr);
293 if (wp == m_watchpoint_index_map.end())
294 return Error ();
295 uint32_t wp_index = wp->second;
296 m_watchpoint_index_map.erase(wp);
297 if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
298 return Error ();
299 return Error ("Clearing hardware watchpoint failed.");
Todd Fialaaf245d12014-06-30 21:05:18 +0000300}
301
302void
303NativeThreadLinux::SetLaunching ()
304{
305 const StateType new_state = StateType::eStateLaunching;
306 MaybeLogStateChange (new_state);
307 m_state = new_state;
308
309 // Also mark it as stopped since launching temporarily stops the newly created thread
310 // in the ptrace machinery.
311 m_stop_info.reason = StopReason::eStopReasonSignal;
312 m_stop_info.details.signal.signo = SIGSTOP;
313}
314
315
316void
317NativeThreadLinux::SetRunning ()
318{
319 const StateType new_state = StateType::eStateRunning;
320 MaybeLogStateChange (new_state);
321 m_state = new_state;
322
323 m_stop_info.reason = StopReason::eStopReasonNone;
Chaoren Lin28e57422015-02-03 01:51:25 +0000324 m_stop_description.clear();
Chaoren Lin18fe6402015-02-03 01:51:47 +0000325
326 // If watchpoints have been set, but none on this thread,
327 // then this is a new thread. So set all existing watchpoints.
328 if (m_watchpoint_index_map.empty())
329 {
Oleksiy Vyalov8bc34f42015-02-19 17:58:04 +0000330 const auto process_sp = GetProcess();
331 if (process_sp)
Chaoren Lin18fe6402015-02-03 01:51:47 +0000332 {
Oleksiy Vyalov8bc34f42015-02-19 17:58:04 +0000333 const auto &watchpoint_map = process_sp->GetWatchpointMap();
334 if (watchpoint_map.empty()) return;
335 GetRegisterContext()->ClearAllHardwareWatchpoints();
336 for (const auto &pair : watchpoint_map)
337 {
338 const auto& wp = pair.second;
339 SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware);
340 }
Chaoren Lin18fe6402015-02-03 01:51:47 +0000341 }
342 }
Todd Fialaaf245d12014-06-30 21:05:18 +0000343}
344
345void
346NativeThreadLinux::SetStepping ()
347{
348 const StateType new_state = StateType::eStateStepping;
349 MaybeLogStateChange (new_state);
350 m_state = new_state;
351
352 m_stop_info.reason = StopReason::eStopReasonNone;
353}
354
355void
356NativeThreadLinux::SetStoppedBySignal (uint32_t signo)
357{
358 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
359 if (log)
Chaoren Linb8af31d2015-02-03 01:50:51 +0000360 log->Printf ("NativeThreadLinux::%s called with signal 0x%02" PRIx32, __FUNCTION__, signo);
Todd Fialaaf245d12014-06-30 21:05:18 +0000361
362 const StateType new_state = StateType::eStateStopped;
363 MaybeLogStateChange (new_state);
364 m_state = new_state;
365
366 m_stop_info.reason = StopReason::eStopReasonSignal;
367 m_stop_info.details.signal.signo = signo;
368}
369
Todd Fiala511e5cd2014-09-11 23:29:14 +0000370bool
371NativeThreadLinux::IsStopped (int *signo)
372{
373 if (!StateIsStoppedState (m_state, false))
374 return false;
375
376 // If we are stopped by a signal, return the signo.
377 if (signo &&
378 m_state == StateType::eStateStopped &&
379 m_stop_info.reason == StopReason::eStopReasonSignal)
380 {
381 *signo = m_stop_info.details.signal.signo;
382 }
383
384 // Regardless, we are stopped.
385 return true;
386}
387
388
Todd Fialaaf245d12014-06-30 21:05:18 +0000389void
Todd Fialaa9882ce2014-08-28 15:46:54 +0000390NativeThreadLinux::SetStoppedByExec ()
391{
392 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
393 if (log)
394 log->Printf ("NativeThreadLinux::%s()", __FUNCTION__);
395
396 const StateType new_state = StateType::eStateStopped;
397 MaybeLogStateChange (new_state);
398 m_state = new_state;
399
400 m_stop_info.reason = StopReason::eStopReasonExec;
401 m_stop_info.details.signal.signo = SIGSTOP;
402}
403
404void
Todd Fialaaf245d12014-06-30 21:05:18 +0000405NativeThreadLinux::SetStoppedByBreakpoint ()
406{
407 const StateType new_state = StateType::eStateStopped;
408 MaybeLogStateChange (new_state);
409 m_state = new_state;
410
Chaoren Lin28e57422015-02-03 01:51:25 +0000411 m_stop_info.reason = StopReason::eStopReasonBreakpoint;
Todd Fialaaf245d12014-06-30 21:05:18 +0000412 m_stop_info.details.signal.signo = SIGTRAP;
Chaoren Lin18fe6402015-02-03 01:51:47 +0000413 m_stop_description.clear();
414}
415
416void
Chaoren Linc16f5dc2015-03-19 23:28:10 +0000417NativeThreadLinux::SetStoppedByWatchpoint (uint32_t wp_index)
Chaoren Lin18fe6402015-02-03 01:51:47 +0000418{
419 const StateType new_state = StateType::eStateStopped;
420 MaybeLogStateChange (new_state);
421 m_state = new_state;
Chaoren Lin18fe6402015-02-03 01:51:47 +0000422 m_stop_description.clear ();
Tamas Berghammereadb2a92015-03-17 14:40:57 +0000423
Chaoren Linc16f5dc2015-03-19 23:28:10 +0000424 lldbassert(wp_index != LLDB_INVALID_INDEX32 &&
425 "wp_index cannot be invalid");
Tamas Berghammereadb2a92015-03-17 14:40:57 +0000426
Chaoren Linc16f5dc2015-03-19 23:28:10 +0000427 std::ostringstream ostr;
428 ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
429 ostr << wp_index;
430 m_stop_description = ostr.str();
Tamas Berghammereadb2a92015-03-17 14:40:57 +0000431
Chaoren Linc16f5dc2015-03-19 23:28:10 +0000432 m_stop_info.reason = StopReason::eStopReasonWatchpoint;
433 m_stop_info.details.signal.signo = SIGTRAP;
Todd Fialaaf245d12014-06-30 21:05:18 +0000434}
435
436bool
437NativeThreadLinux::IsStoppedAtBreakpoint ()
438{
Chaoren Lin18fe6402015-02-03 01:51:47 +0000439 return GetState () == StateType::eStateStopped &&
440 m_stop_info.reason == StopReason::eStopReasonBreakpoint;
441}
Todd Fialaaf245d12014-06-30 21:05:18 +0000442
Chaoren Lin18fe6402015-02-03 01:51:47 +0000443bool
444NativeThreadLinux::IsStoppedAtWatchpoint ()
445{
446 return GetState () == StateType::eStateStopped &&
447 m_stop_info.reason == StopReason::eStopReasonWatchpoint;
Todd Fialaaf245d12014-06-30 21:05:18 +0000448}
449
450void
Chaoren Lin28e57422015-02-03 01:51:25 +0000451NativeThreadLinux::SetStoppedByTrace ()
452{
453 const StateType new_state = StateType::eStateStopped;
454 MaybeLogStateChange (new_state);
455 m_state = new_state;
456
457 m_stop_info.reason = StopReason::eStopReasonTrace;
458 m_stop_info.details.signal.signo = SIGTRAP;
459}
460
461void
462NativeThreadLinux::SetCrashedWithException (const siginfo_t& info)
Todd Fialaaf245d12014-06-30 21:05:18 +0000463{
464 const StateType new_state = StateType::eStateCrashed;
465 MaybeLogStateChange (new_state);
466 m_state = new_state;
467
468 m_stop_info.reason = StopReason::eStopReasonException;
Chaoren Lin28e57422015-02-03 01:51:25 +0000469 m_stop_info.details.signal.signo = info.si_signo;
Todd Fialaaf245d12014-06-30 21:05:18 +0000470
Chaoren Lin28e57422015-02-03 01:51:25 +0000471 const auto reason = GetCrashReason (info);
472 m_stop_description = GetCrashReasonString (reason, reinterpret_cast<lldb::addr_t> (info.si_addr));
473}
Todd Fialaaf245d12014-06-30 21:05:18 +0000474
475void
476NativeThreadLinux::SetSuspended ()
477{
478 const StateType new_state = StateType::eStateSuspended;
479 MaybeLogStateChange (new_state);
480 m_state = new_state;
481
482 // FIXME what makes sense here? Do we need a suspended StopReason?
483 m_stop_info.reason = StopReason::eStopReasonNone;
484}
485
486void
487NativeThreadLinux::SetExited ()
488{
489 const StateType new_state = StateType::eStateExited;
490 MaybeLogStateChange (new_state);
491 m_state = new_state;
492
493 m_stop_info.reason = StopReason::eStopReasonThreadExiting;
494}
495
496void
497NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state)
498{
499 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
500 // If we're not logging, we're done.
501 if (!log)
502 return;
503
504 // If this is a state change to the same state, we're done.
505 lldb::StateType old_state = m_state;
506 if (new_state == old_state)
507 return;
508
509 NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
510 lldb::pid_t pid = m_process_sp ? m_process_sp->GetID () : LLDB_INVALID_PROCESS_ID;
511
512 // Log it.
513 log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state));
514}