blob: c7c13a5a471342d6440b740e0366788641e78d11 [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
Pavel Labath8c8ff7a2015-05-11 10:03:10 +000040#include <sys/syscall.h>
41// Try to define a macro to encapsulate the tgkill syscall
42#define tgkill(pid, tid, sig) \
43 syscall(SYS_tgkill, static_cast<::pid_t>(pid), static_cast<::pid_t>(tid), sig)
44
Todd Fialaaf245d12014-06-30 21:05:18 +000045using namespace lldb;
46using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000047using namespace lldb_private::process_linux;
Todd Fialaaf245d12014-06-30 21:05:18 +000048
49namespace
50{
51 void LogThreadStopInfo (Log &log, const ThreadStopInfo &stop_info, const char *const header)
52 {
53 switch (stop_info.reason)
54 {
Pavel Labath12fd3752015-03-20 14:45:13 +000055 case eStopReasonNone:
56 log.Printf ("%s: %s no stop reason", __FUNCTION__, header);
57 return;
58 case eStopReasonTrace:
59 log.Printf ("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
60 return;
61 case eStopReasonBreakpoint:
62 log.Printf ("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
63 return;
64 case eStopReasonWatchpoint:
65 log.Printf ("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
66 return;
Todd Fialaaf245d12014-06-30 21:05:18 +000067 case eStopReasonSignal:
Chaoren Linae29d392015-02-03 01:50:46 +000068 log.Printf ("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
Todd Fialaaf245d12014-06-30 21:05:18 +000069 return;
70 case eStopReasonException:
Chaoren Linae29d392015-02-03 01:50:46 +000071 log.Printf ("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header, stop_info.details.exception.type);
Todd Fialaa9882ce2014-08-28 15:46:54 +000072 return;
73 case eStopReasonExec:
74 log.Printf ("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
Todd Fialaaf245d12014-06-30 21:05:18 +000075 return;
Pavel Labath12fd3752015-03-20 14:45:13 +000076 case eStopReasonPlanComplete:
77 log.Printf ("%s: %s plan complete", __FUNCTION__, header);
78 return;
79 case eStopReasonThreadExiting:
80 log.Printf ("%s: %s thread exiting", __FUNCTION__, header);
81 return;
82 case eStopReasonInstrumentation:
83 log.Printf ("%s: %s instrumentation", __FUNCTION__, header);
84 return;
Todd Fialaaf245d12014-06-30 21:05:18 +000085 default:
Todd Fialaa9882ce2014-08-28 15:46:54 +000086 log.Printf ("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header, static_cast<uint32_t> (stop_info.reason));
Todd Fialaaf245d12014-06-30 21:05:18 +000087 }
88 }
89}
90
91NativeThreadLinux::NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid) :
92 NativeThreadProtocol (process, tid),
93 m_state (StateType::eStateInvalid),
94 m_stop_info (),
Chaoren Lin28e57422015-02-03 01:51:25 +000095 m_reg_context_sp (),
96 m_stop_description ()
Todd Fialaaf245d12014-06-30 21:05:18 +000097{
98}
99
Todd Fiala7206c6d2014-09-12 22:51:49 +0000100std::string
Todd Fialaaf245d12014-06-30 21:05:18 +0000101NativeThreadLinux::GetName()
102{
103 NativeProcessProtocolSP process_sp = m_process_wp.lock ();
104 if (!process_sp)
105 return "<unknown: no process>";
106
107 // const NativeProcessLinux *const process = reinterpret_cast<NativeProcessLinux*> (process_sp->get ());
Zachary Turner39de3112014-09-09 20:54:56 +0000108 llvm::SmallString<32> thread_name;
109 HostNativeThread::GetName(GetID(), thread_name);
110 return thread_name.c_str();
Todd Fialaaf245d12014-06-30 21:05:18 +0000111}
112
113lldb::StateType
114NativeThreadLinux::GetState ()
115{
116 return m_state;
117}
118
119
120bool
Chaoren Lin28e57422015-02-03 01:51:25 +0000121NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info, std::string& description)
Todd Fialaaf245d12014-06-30 21:05:18 +0000122{
123 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
Chaoren Lin28e57422015-02-03 01:51:25 +0000124
125 description.clear();
126
Todd Fialaaf245d12014-06-30 21:05:18 +0000127 switch (m_state)
128 {
129 case eStateStopped:
130 case eStateCrashed:
131 case eStateExited:
132 case eStateSuspended:
133 case eStateUnloaded:
134 if (log)
Todd Fialaa9882ce2014-08-28 15:46:54 +0000135 LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread:");
Todd Fialaaf245d12014-06-30 21:05:18 +0000136 stop_info = m_stop_info;
Chaoren Lin18fe6402015-02-03 01:51:47 +0000137 switch (m_stop_info.reason)
138 {
139 case StopReason::eStopReasonException:
140 case StopReason::eStopReasonBreakpoint:
141 case StopReason::eStopReasonWatchpoint:
142 description = m_stop_description;
143 default:
144 break;
145 }
Todd Fialaaf245d12014-06-30 21:05:18 +0000146 if (log)
Todd Fialaa9882ce2014-08-28 15:46:54 +0000147 LogThreadStopInfo (*log, stop_info, "returned stop_info:");
Chaoren Lin28e57422015-02-03 01:51:25 +0000148
Todd Fialaaf245d12014-06-30 21:05:18 +0000149 return true;
150
151 case eStateInvalid:
152 case eStateConnected:
153 case eStateAttaching:
154 case eStateLaunching:
155 case eStateRunning:
156 case eStateStepping:
157 case eStateDetached:
Todd Fialaaf245d12014-06-30 21:05:18 +0000158 if (log)
159 {
160 log->Printf ("NativeThreadLinux::%s tid %" PRIu64 " in state %s cannot answer stop reason",
161 __FUNCTION__, GetID (), StateAsCString (m_state));
162 }
163 return false;
164 }
David Majnemer8faf9372014-09-16 06:34:29 +0000165 llvm_unreachable("unhandled StateType!");
Todd Fialaaf245d12014-06-30 21:05:18 +0000166}
167
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000168NativeRegisterContextSP
Todd Fialaaf245d12014-06-30 21:05:18 +0000169NativeThreadLinux::GetRegisterContext ()
170{
171 // Return the register context if we already created it.
172 if (m_reg_context_sp)
173 return m_reg_context_sp;
174
175 // First select the appropriate RegisterInfoInterface.
176 RegisterInfoInterface *reg_interface = nullptr;
177 NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
178 if (!m_process_sp)
179 return NativeRegisterContextSP ();
180
181 ArchSpec target_arch;
182 if (!m_process_sp->GetArchitecture (target_arch))
183 return NativeRegisterContextSP ();
184
185 switch (target_arch.GetTriple().getOS())
186 {
187 case llvm::Triple::Linux:
188 switch (target_arch.GetMachine())
189 {
Todd Fialab71e89e2014-08-29 16:01:35 +0000190 case llvm::Triple::aarch64:
191 assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host");
192 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm64(target_arch));
193 break;
Omair Javaid3f572162015-04-14 07:30:20 +0000194 case llvm::Triple::arm:
195 assert(HostInfo::GetArchitecture ().GetAddressByteSize() == 4);
196 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm(target_arch));
197 break;
Todd Fialaaf245d12014-06-30 21:05:18 +0000198 case llvm::Triple::x86:
199 case llvm::Triple::x86_64:
Zachary Turner13b18262014-08-20 16:42:51 +0000200 if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
Todd Fialaaf245d12014-06-30 21:05:18 +0000201 {
202 // 32-bit hosts run with a RegisterContextLinux_i386 context.
203 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_i386(target_arch));
204 }
205 else
206 {
Zachary Turner13b18262014-08-20 16:42:51 +0000207 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
208 "Register setting path assumes this is a 64-bit host");
Todd Fialaaf245d12014-06-30 21:05:18 +0000209 // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context.
210 reg_interface = static_cast<RegisterInfoInterface*> (new RegisterContextLinux_x86_64 (target_arch));
211 }
212 break;
Mohit K. Bhakkad3df471c2015-03-17 11:43:56 +0000213 case llvm::Triple::mips64:
214 case llvm::Triple::mips64el:
215 assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8)
216 && "Register setting path assumes this is a 64-bit host");
217 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_mips64 (target_arch));
218 break;
Todd Fialaaf245d12014-06-30 21:05:18 +0000219 default:
220 break;
221 }
222 break;
223 default:
224 break;
225 }
226
227 assert(reg_interface && "OS or CPU not supported!");
228 if (!reg_interface)
229 return NativeRegisterContextSP ();
230
231 // Now create the register context.
232 switch (target_arch.GetMachine())
233 {
234#if 0
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#endif
Mohit K. Bhakkad3df471c2015-03-17 11:43:56 +0000243 case llvm::Triple::mips64:
244 case llvm::Triple::mips64el:
245 {
246 const uint32_t concrete_frame_idx = 0;
247 m_reg_context_sp.reset (new NativeRegisterContextLinux_mips64 (*this, concrete_frame_idx, reg_interface));
248 break;
249 }
Tamas Berghammer1e209fc2015-03-13 11:36:47 +0000250 case llvm::Triple::aarch64:
251 {
252 const uint32_t concrete_frame_idx = 0;
253 m_reg_context_sp.reset (new NativeRegisterContextLinux_arm64(*this, concrete_frame_idx, reg_interface));
254 break;
255 }
Omair Javaid3f572162015-04-14 07:30:20 +0000256 case llvm::Triple::arm:
257 {
258 const uint32_t concrete_frame_idx = 0;
259 m_reg_context_sp.reset (new NativeRegisterContextLinux_arm(*this, concrete_frame_idx, reg_interface));
260 break;
261 }
Todd Fialaaf245d12014-06-30 21:05:18 +0000262 case llvm::Triple::x86:
Todd Fialaaf245d12014-06-30 21:05:18 +0000263 case llvm::Triple::x86_64:
264 {
265 const uint32_t concrete_frame_idx = 0;
266 m_reg_context_sp.reset (new NativeRegisterContextLinux_x86_64(*this, concrete_frame_idx, reg_interface));
267 break;
268 }
269 default:
270 break;
271 }
272
273 return m_reg_context_sp;
274}
275
276Error
277NativeThreadLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
278{
Chaoren Lin18fe6402015-02-03 01:51:47 +0000279 if (!hardware)
280 return Error ("not implemented");
Chaoren Linf591f692015-02-26 19:48:15 +0000281 if (m_state == eStateLaunching)
282 return Error ();
Chaoren Lin18fe6402015-02-03 01:51:47 +0000283 Error error = RemoveWatchpoint(addr);
284 if (error.Fail()) return error;
285 NativeRegisterContextSP reg_ctx = GetRegisterContext ();
286 uint32_t wp_index =
287 reg_ctx->SetHardwareWatchpoint (addr, size, watch_flags);
288 if (wp_index == LLDB_INVALID_INDEX32)
289 return Error ("Setting hardware watchpoint failed.");
290 m_watchpoint_index_map.insert({addr, wp_index});
291 return Error ();
Todd Fialaaf245d12014-06-30 21:05:18 +0000292}
293
294Error
295NativeThreadLinux::RemoveWatchpoint (lldb::addr_t addr)
296{
Chaoren Lin18fe6402015-02-03 01:51:47 +0000297 auto wp = m_watchpoint_index_map.find(addr);
298 if (wp == m_watchpoint_index_map.end())
299 return Error ();
300 uint32_t wp_index = wp->second;
301 m_watchpoint_index_map.erase(wp);
302 if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
303 return Error ();
304 return Error ("Clearing hardware watchpoint failed.");
Todd Fialaaf245d12014-06-30 21:05:18 +0000305}
306
307void
Todd Fialaaf245d12014-06-30 21:05:18 +0000308NativeThreadLinux::SetRunning ()
309{
310 const StateType new_state = StateType::eStateRunning;
311 MaybeLogStateChange (new_state);
312 m_state = new_state;
313
314 m_stop_info.reason = StopReason::eStopReasonNone;
Chaoren Lin28e57422015-02-03 01:51:25 +0000315 m_stop_description.clear();
Chaoren Lin18fe6402015-02-03 01:51:47 +0000316
317 // If watchpoints have been set, but none on this thread,
318 // then this is a new thread. So set all existing watchpoints.
319 if (m_watchpoint_index_map.empty())
320 {
Oleksiy Vyalov8bc34f42015-02-19 17:58:04 +0000321 const auto process_sp = GetProcess();
322 if (process_sp)
Chaoren Lin18fe6402015-02-03 01:51:47 +0000323 {
Oleksiy Vyalov8bc34f42015-02-19 17:58:04 +0000324 const auto &watchpoint_map = process_sp->GetWatchpointMap();
325 if (watchpoint_map.empty()) return;
326 GetRegisterContext()->ClearAllHardwareWatchpoints();
327 for (const auto &pair : watchpoint_map)
328 {
329 const auto& wp = pair.second;
330 SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware);
331 }
Chaoren Lin18fe6402015-02-03 01:51:47 +0000332 }
333 }
Todd Fialaaf245d12014-06-30 21:05:18 +0000334}
335
336void
337NativeThreadLinux::SetStepping ()
338{
339 const StateType new_state = StateType::eStateStepping;
340 MaybeLogStateChange (new_state);
341 m_state = new_state;
342
343 m_stop_info.reason = StopReason::eStopReasonNone;
344}
345
346void
347NativeThreadLinux::SetStoppedBySignal (uint32_t signo)
348{
349 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
350 if (log)
Chaoren Linb8af31d2015-02-03 01:50:51 +0000351 log->Printf ("NativeThreadLinux::%s called with signal 0x%02" PRIx32, __FUNCTION__, signo);
Todd Fialaaf245d12014-06-30 21:05:18 +0000352
353 const StateType new_state = StateType::eStateStopped;
354 MaybeLogStateChange (new_state);
355 m_state = new_state;
356
357 m_stop_info.reason = StopReason::eStopReasonSignal;
358 m_stop_info.details.signal.signo = signo;
359}
360
Todd Fiala511e5cd2014-09-11 23:29:14 +0000361bool
362NativeThreadLinux::IsStopped (int *signo)
363{
364 if (!StateIsStoppedState (m_state, false))
365 return false;
366
367 // If we are stopped by a signal, return the signo.
368 if (signo &&
369 m_state == StateType::eStateStopped &&
370 m_stop_info.reason == StopReason::eStopReasonSignal)
371 {
372 *signo = m_stop_info.details.signal.signo;
373 }
374
375 // Regardless, we are stopped.
376 return true;
377}
378
379
Todd Fialaaf245d12014-06-30 21:05:18 +0000380void
Todd Fialaa9882ce2014-08-28 15:46:54 +0000381NativeThreadLinux::SetStoppedByExec ()
382{
383 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
384 if (log)
385 log->Printf ("NativeThreadLinux::%s()", __FUNCTION__);
386
387 const StateType new_state = StateType::eStateStopped;
388 MaybeLogStateChange (new_state);
389 m_state = new_state;
390
391 m_stop_info.reason = StopReason::eStopReasonExec;
392 m_stop_info.details.signal.signo = SIGSTOP;
393}
394
395void
Todd Fialaaf245d12014-06-30 21:05:18 +0000396NativeThreadLinux::SetStoppedByBreakpoint ()
397{
398 const StateType new_state = StateType::eStateStopped;
399 MaybeLogStateChange (new_state);
400 m_state = new_state;
401
Chaoren Lin28e57422015-02-03 01:51:25 +0000402 m_stop_info.reason = StopReason::eStopReasonBreakpoint;
Todd Fialaaf245d12014-06-30 21:05:18 +0000403 m_stop_info.details.signal.signo = SIGTRAP;
Chaoren Lin18fe6402015-02-03 01:51:47 +0000404 m_stop_description.clear();
405}
406
407void
Chaoren Linc16f5dc2015-03-19 23:28:10 +0000408NativeThreadLinux::SetStoppedByWatchpoint (uint32_t wp_index)
Chaoren Lin18fe6402015-02-03 01:51:47 +0000409{
410 const StateType new_state = StateType::eStateStopped;
411 MaybeLogStateChange (new_state);
412 m_state = new_state;
Chaoren Lin18fe6402015-02-03 01:51:47 +0000413 m_stop_description.clear ();
Tamas Berghammereadb2a92015-03-17 14:40:57 +0000414
Chaoren Linc16f5dc2015-03-19 23:28:10 +0000415 lldbassert(wp_index != LLDB_INVALID_INDEX32 &&
416 "wp_index cannot be invalid");
Tamas Berghammereadb2a92015-03-17 14:40:57 +0000417
Chaoren Linc16f5dc2015-03-19 23:28:10 +0000418 std::ostringstream ostr;
419 ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
420 ostr << wp_index;
421 m_stop_description = ostr.str();
Tamas Berghammereadb2a92015-03-17 14:40:57 +0000422
Chaoren Linc16f5dc2015-03-19 23:28:10 +0000423 m_stop_info.reason = StopReason::eStopReasonWatchpoint;
424 m_stop_info.details.signal.signo = SIGTRAP;
Todd Fialaaf245d12014-06-30 21:05:18 +0000425}
426
427bool
428NativeThreadLinux::IsStoppedAtBreakpoint ()
429{
Chaoren Lin18fe6402015-02-03 01:51:47 +0000430 return GetState () == StateType::eStateStopped &&
431 m_stop_info.reason == StopReason::eStopReasonBreakpoint;
432}
Todd Fialaaf245d12014-06-30 21:05:18 +0000433
Chaoren Lin18fe6402015-02-03 01:51:47 +0000434bool
435NativeThreadLinux::IsStoppedAtWatchpoint ()
436{
437 return GetState () == StateType::eStateStopped &&
438 m_stop_info.reason == StopReason::eStopReasonWatchpoint;
Todd Fialaaf245d12014-06-30 21:05:18 +0000439}
440
441void
Chaoren Lin28e57422015-02-03 01:51:25 +0000442NativeThreadLinux::SetStoppedByTrace ()
443{
444 const StateType new_state = StateType::eStateStopped;
445 MaybeLogStateChange (new_state);
446 m_state = new_state;
447
448 m_stop_info.reason = StopReason::eStopReasonTrace;
449 m_stop_info.details.signal.signo = SIGTRAP;
450}
451
452void
453NativeThreadLinux::SetCrashedWithException (const siginfo_t& info)
Todd Fialaaf245d12014-06-30 21:05:18 +0000454{
455 const StateType new_state = StateType::eStateCrashed;
456 MaybeLogStateChange (new_state);
457 m_state = new_state;
458
459 m_stop_info.reason = StopReason::eStopReasonException;
Chaoren Lin28e57422015-02-03 01:51:25 +0000460 m_stop_info.details.signal.signo = info.si_signo;
Todd Fialaaf245d12014-06-30 21:05:18 +0000461
Chaoren Lin28e57422015-02-03 01:51:25 +0000462 const auto reason = GetCrashReason (info);
Tamas Berghammer1fab7b92015-04-16 14:06:15 +0000463 m_stop_description = GetCrashReasonString (reason, reinterpret_cast<uintptr_t>(info.si_addr));
Chaoren Lin28e57422015-02-03 01:51:25 +0000464}
Todd Fialaaf245d12014-06-30 21:05:18 +0000465
466void
467NativeThreadLinux::SetSuspended ()
468{
469 const StateType new_state = StateType::eStateSuspended;
470 MaybeLogStateChange (new_state);
471 m_state = new_state;
472
473 // FIXME what makes sense here? Do we need a suspended StopReason?
474 m_stop_info.reason = StopReason::eStopReasonNone;
475}
476
477void
478NativeThreadLinux::SetExited ()
479{
480 const StateType new_state = StateType::eStateExited;
481 MaybeLogStateChange (new_state);
482 m_state = new_state;
483
484 m_stop_info.reason = StopReason::eStopReasonThreadExiting;
485}
486
Pavel Labath8c8ff7a2015-05-11 10:03:10 +0000487Error
488NativeThreadLinux::RequestStop ()
489{
490 Log* log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
491
492 const auto process_sp = GetProcess();
493 if (! process_sp)
494 return Error("Process is null.");
495
496 lldb::pid_t pid = process_sp->GetID();
497 lldb::tid_t tid = GetID();
498
499 if (log)
500 log->Printf ("NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64 ", tid: %" PRIu64 ")", __FUNCTION__, pid, tid);
501
502 Error err;
503 errno = 0;
504 if (::tgkill (pid, tid, SIGSTOP) != 0)
505 {
506 err.SetErrorToErrno ();
507 if (log)
508 log->Printf ("NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64 ", SIGSTOP) failed: %s", __FUNCTION__, pid, tid, err.AsCString ());
509 }
510 else
511 m_thread_context.stop_requested = true;
512
513 return err;
514}
515
Todd Fialaaf245d12014-06-30 21:05:18 +0000516void
517NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state)
518{
519 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
520 // If we're not logging, we're done.
521 if (!log)
522 return;
523
524 // If this is a state change to the same state, we're done.
525 lldb::StateType old_state = m_state;
526 if (new_state == old_state)
527 return;
528
529 NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
530 lldb::pid_t pid = m_process_sp ? m_process_sp->GetID () : LLDB_INVALID_PROCESS_ID;
531
532 // Log it.
533 log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state));
534}