1af245d11STodd Fiala //===-- NativeThreadLinux.cpp --------------------------------- -*- C++ -*-===//
2af245d11STodd Fiala //
3af245d11STodd Fiala //                     The LLVM Compiler Infrastructure
4af245d11STodd Fiala //
5af245d11STodd Fiala // This file is distributed under the University of Illinois Open Source
6af245d11STodd Fiala // License. See LICENSE.TXT for details.
7af245d11STodd Fiala //
8af245d11STodd Fiala //===----------------------------------------------------------------------===//
9af245d11STodd Fiala 
10af245d11STodd Fiala #include "NativeThreadLinux.h"
11af245d11STodd Fiala 
12af245d11STodd Fiala #include <signal.h>
1318fe6404SChaoren Lin #include <sstream>
14af245d11STodd Fiala 
15af245d11STodd Fiala #include "NativeProcessLinux.h"
163f57216cSOmair Javaid #include "NativeRegisterContextLinux_arm.h"
171e209fccSTamas Berghammer #include "NativeRegisterContextLinux_arm64.h"
182850b1beSTodd Fiala #include "NativeRegisterContextLinux_x86_64.h"
193df471c3SMohit K. Bhakkad #include "NativeRegisterContextLinux_mips64.h"
202850b1beSTodd Fiala 
21af245d11STodd Fiala #include "lldb/Core/Log.h"
22af245d11STodd Fiala #include "lldb/Core/State.h"
2339de3110SZachary Turner #include "lldb/Host/HostNativeThread.h"
24c16f5dcaSChaoren Lin #include "lldb/Utility/LLDBAssert.h"
25af245d11STodd Fiala #include "lldb/lldb-enumerations.h"
2639de3110SZachary Turner 
2739de3110SZachary Turner #include "llvm/ADT/SmallString.h"
2839de3110SZachary Turner 
2928e57429SChaoren Lin #include "Plugins/Process/POSIX/CrashReason.h"
3028e57429SChaoren Lin 
318c8ff7afSPavel Labath #include <sys/syscall.h>
328c8ff7afSPavel Labath // Try to define a macro to encapsulate the tgkill syscall
338c8ff7afSPavel Labath #define tgkill(pid, tid, sig) \
348c8ff7afSPavel Labath     syscall(SYS_tgkill, static_cast<::pid_t>(pid), static_cast<::pid_t>(tid), sig)
358c8ff7afSPavel Labath 
36af245d11STodd Fiala using namespace lldb;
37af245d11STodd Fiala using namespace lldb_private;
38db264a6dSTamas Berghammer using namespace lldb_private::process_linux;
39af245d11STodd Fiala 
40af245d11STodd Fiala namespace
41af245d11STodd Fiala {
42af245d11STodd Fiala     void LogThreadStopInfo (Log &log, const ThreadStopInfo &stop_info, const char *const header)
43af245d11STodd Fiala     {
44af245d11STodd Fiala         switch (stop_info.reason)
45af245d11STodd Fiala         {
4612fd3756SPavel Labath             case eStopReasonNone:
4712fd3756SPavel Labath                 log.Printf ("%s: %s no stop reason", __FUNCTION__, header);
4812fd3756SPavel Labath                 return;
4912fd3756SPavel Labath             case eStopReasonTrace:
5012fd3756SPavel Labath                 log.Printf ("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
5112fd3756SPavel Labath                 return;
5212fd3756SPavel Labath             case eStopReasonBreakpoint:
5312fd3756SPavel Labath                 log.Printf ("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
5412fd3756SPavel Labath                 return;
5512fd3756SPavel Labath             case eStopReasonWatchpoint:
5612fd3756SPavel Labath                 log.Printf ("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
5712fd3756SPavel Labath                 return;
58af245d11STodd Fiala             case eStopReasonSignal:
59ae29d395SChaoren Lin                 log.Printf ("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
60af245d11STodd Fiala                 return;
61af245d11STodd Fiala             case eStopReasonException:
62ae29d395SChaoren Lin                 log.Printf ("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header, stop_info.details.exception.type);
63a9882ceeSTodd Fiala                 return;
64a9882ceeSTodd Fiala             case eStopReasonExec:
65a9882ceeSTodd Fiala                 log.Printf ("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
66af245d11STodd Fiala                 return;
6712fd3756SPavel Labath             case eStopReasonPlanComplete:
6812fd3756SPavel Labath                 log.Printf ("%s: %s plan complete", __FUNCTION__, header);
6912fd3756SPavel Labath                 return;
7012fd3756SPavel Labath             case eStopReasonThreadExiting:
7112fd3756SPavel Labath                 log.Printf ("%s: %s thread exiting", __FUNCTION__, header);
7212fd3756SPavel Labath                 return;
7312fd3756SPavel Labath             case eStopReasonInstrumentation:
7412fd3756SPavel Labath                 log.Printf ("%s: %s instrumentation", __FUNCTION__, header);
7512fd3756SPavel Labath                 return;
76af245d11STodd Fiala             default:
77a9882ceeSTodd Fiala                 log.Printf ("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header, static_cast<uint32_t> (stop_info.reason));
78af245d11STodd Fiala         }
79af245d11STodd Fiala     }
80af245d11STodd Fiala }
81af245d11STodd Fiala 
82af245d11STodd Fiala NativeThreadLinux::NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid) :
83af245d11STodd Fiala     NativeThreadProtocol (process, tid),
84af245d11STodd Fiala     m_state (StateType::eStateInvalid),
85af245d11STodd Fiala     m_stop_info (),
8628e57429SChaoren Lin     m_reg_context_sp (),
8728e57429SChaoren Lin     m_stop_description ()
88af245d11STodd Fiala {
89af245d11STodd Fiala }
90af245d11STodd Fiala 
917206c6d1STodd Fiala std::string
92af245d11STodd Fiala NativeThreadLinux::GetName()
93af245d11STodd Fiala {
94af245d11STodd Fiala     NativeProcessProtocolSP process_sp = m_process_wp.lock ();
95af245d11STodd Fiala     if (!process_sp)
96af245d11STodd Fiala         return "<unknown: no process>";
97af245d11STodd Fiala 
98af245d11STodd Fiala     // const NativeProcessLinux *const process = reinterpret_cast<NativeProcessLinux*> (process_sp->get ());
9939de3110SZachary Turner     llvm::SmallString<32> thread_name;
10039de3110SZachary Turner     HostNativeThread::GetName(GetID(), thread_name);
10139de3110SZachary Turner     return thread_name.c_str();
102af245d11STodd Fiala }
103af245d11STodd Fiala 
104af245d11STodd Fiala lldb::StateType
105af245d11STodd Fiala NativeThreadLinux::GetState ()
106af245d11STodd Fiala {
107af245d11STodd Fiala     return m_state;
108af245d11STodd Fiala }
109af245d11STodd Fiala 
110af245d11STodd Fiala 
111af245d11STodd Fiala bool
11228e57429SChaoren Lin NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info, std::string& description)
113af245d11STodd Fiala {
114af245d11STodd Fiala     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
11528e57429SChaoren Lin 
11628e57429SChaoren Lin     description.clear();
11728e57429SChaoren Lin 
118af245d11STodd Fiala     switch (m_state)
119af245d11STodd Fiala     {
120af245d11STodd Fiala     case eStateStopped:
121af245d11STodd Fiala     case eStateCrashed:
122af245d11STodd Fiala     case eStateExited:
123af245d11STodd Fiala     case eStateSuspended:
124af245d11STodd Fiala     case eStateUnloaded:
125af245d11STodd Fiala         if (log)
126af245d11STodd Fiala             LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread:");
127af245d11STodd Fiala         stop_info = m_stop_info;
12828e57429SChaoren Lin         description = m_stop_description;
129af245d11STodd Fiala         if (log)
130af245d11STodd Fiala             LogThreadStopInfo (*log, stop_info, "returned stop_info:");
13128e57429SChaoren Lin 
132af245d11STodd Fiala         return true;
133af245d11STodd Fiala 
134af245d11STodd Fiala     case eStateInvalid:
135af245d11STodd Fiala     case eStateConnected:
136af245d11STodd Fiala     case eStateAttaching:
137af245d11STodd Fiala     case eStateLaunching:
138af245d11STodd Fiala     case eStateRunning:
139af245d11STodd Fiala     case eStateStepping:
140af245d11STodd Fiala     case eStateDetached:
141af245d11STodd Fiala         if (log)
142af245d11STodd Fiala         {
143af245d11STodd Fiala             log->Printf ("NativeThreadLinux::%s tid %" PRIu64 " in state %s cannot answer stop reason",
144af245d11STodd Fiala                     __FUNCTION__, GetID (), StateAsCString (m_state));
145af245d11STodd Fiala         }
146af245d11STodd Fiala         return false;
147af245d11STodd Fiala     }
1488faf9370SDavid Majnemer     llvm_unreachable("unhandled StateType!");
149af245d11STodd Fiala }
150af245d11STodd Fiala 
151db264a6dSTamas Berghammer NativeRegisterContextSP
152af245d11STodd Fiala NativeThreadLinux::GetRegisterContext ()
153af245d11STodd Fiala {
154af245d11STodd Fiala     // Return the register context if we already created it.
155af245d11STodd Fiala     if (m_reg_context_sp)
156af245d11STodd Fiala         return m_reg_context_sp;
157af245d11STodd Fiala 
158af245d11STodd Fiala     NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
159af245d11STodd Fiala     if (!m_process_sp)
160af245d11STodd Fiala         return NativeRegisterContextSP ();
161af245d11STodd Fiala 
162af245d11STodd Fiala     ArchSpec target_arch;
163af245d11STodd Fiala     if (!m_process_sp->GetArchitecture (target_arch))
164af245d11STodd Fiala         return NativeRegisterContextSP ();
165af245d11STodd Fiala 
1663df471c3SMohit K. Bhakkad     const uint32_t concrete_frame_idx = 0;
167068f8a7eSTamas Berghammer     m_reg_context_sp.reset (NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(target_arch,
168068f8a7eSTamas Berghammer                                                                                              *this,
169068f8a7eSTamas Berghammer                                                                                              concrete_frame_idx));
170af245d11STodd Fiala 
171af245d11STodd Fiala     return m_reg_context_sp;
172af245d11STodd Fiala }
173af245d11STodd Fiala 
174af245d11STodd Fiala Error
175af245d11STodd Fiala NativeThreadLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
176af245d11STodd Fiala {
17718fe6404SChaoren Lin     if (!hardware)
178af245d11STodd Fiala         return Error ("not implemented");
179f591f69fSChaoren Lin     if (m_state == eStateLaunching)
180f591f69fSChaoren Lin         return Error ();
18118fe6404SChaoren Lin     Error error = RemoveWatchpoint(addr);
18218fe6404SChaoren Lin     if (error.Fail()) return error;
18318fe6404SChaoren Lin     NativeRegisterContextSP reg_ctx = GetRegisterContext ();
18418fe6404SChaoren Lin     uint32_t wp_index =
18518fe6404SChaoren Lin         reg_ctx->SetHardwareWatchpoint (addr, size, watch_flags);
18618fe6404SChaoren Lin     if (wp_index == LLDB_INVALID_INDEX32)
18718fe6404SChaoren Lin         return Error ("Setting hardware watchpoint failed.");
18818fe6404SChaoren Lin     m_watchpoint_index_map.insert({addr, wp_index});
18918fe6404SChaoren Lin     return Error ();
190af245d11STodd Fiala }
191af245d11STodd Fiala 
192af245d11STodd Fiala Error
193af245d11STodd Fiala NativeThreadLinux::RemoveWatchpoint (lldb::addr_t addr)
194af245d11STodd Fiala {
19518fe6404SChaoren Lin     auto wp = m_watchpoint_index_map.find(addr);
19618fe6404SChaoren Lin     if (wp == m_watchpoint_index_map.end())
19718fe6404SChaoren Lin         return Error ();
19818fe6404SChaoren Lin     uint32_t wp_index = wp->second;
19918fe6404SChaoren Lin     m_watchpoint_index_map.erase(wp);
20018fe6404SChaoren Lin     if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
20118fe6404SChaoren Lin         return Error ();
20218fe6404SChaoren Lin     return Error ("Clearing hardware watchpoint failed.");
203af245d11STodd Fiala }
204af245d11STodd Fiala 
205af245d11STodd Fiala void
206af245d11STodd Fiala NativeThreadLinux::SetRunning ()
207af245d11STodd Fiala {
208af245d11STodd Fiala     const StateType new_state = StateType::eStateRunning;
209af245d11STodd Fiala     MaybeLogStateChange (new_state);
210af245d11STodd Fiala     m_state = new_state;
211af245d11STodd Fiala 
212af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonNone;
21328e57429SChaoren Lin     m_stop_description.clear();
21418fe6404SChaoren Lin 
21518fe6404SChaoren Lin     // If watchpoints have been set, but none on this thread,
21618fe6404SChaoren Lin     // then this is a new thread. So set all existing watchpoints.
21718fe6404SChaoren Lin     if (m_watchpoint_index_map.empty())
21818fe6404SChaoren Lin     {
2198bc34f4dSOleksiy Vyalov         const auto process_sp = GetProcess();
2208bc34f4dSOleksiy Vyalov         if (process_sp)
2218bc34f4dSOleksiy Vyalov         {
2228bc34f4dSOleksiy Vyalov             const auto &watchpoint_map = process_sp->GetWatchpointMap();
22318fe6404SChaoren Lin             if (watchpoint_map.empty()) return;
22418fe6404SChaoren Lin             GetRegisterContext()->ClearAllHardwareWatchpoints();
22518fe6404SChaoren Lin             for (const auto &pair : watchpoint_map)
22618fe6404SChaoren Lin             {
22718fe6404SChaoren Lin                 const auto& wp = pair.second;
22818fe6404SChaoren Lin                 SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware);
22918fe6404SChaoren Lin             }
23018fe6404SChaoren Lin         }
231af245d11STodd Fiala     }
2328bc34f4dSOleksiy Vyalov }
233af245d11STodd Fiala 
234af245d11STodd Fiala void
235af245d11STodd Fiala NativeThreadLinux::SetStepping ()
236af245d11STodd Fiala {
237af245d11STodd Fiala     const StateType new_state = StateType::eStateStepping;
238af245d11STodd Fiala     MaybeLogStateChange (new_state);
239af245d11STodd Fiala     m_state = new_state;
240af245d11STodd Fiala 
241af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonNone;
242af245d11STodd Fiala }
243af245d11STodd Fiala 
244af245d11STodd Fiala void
245*c4e25c96SPavel Labath NativeThreadLinux::SetStoppedBySignal(uint32_t signo, const siginfo_t *info)
246af245d11STodd Fiala {
247af245d11STodd Fiala     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
248af245d11STodd Fiala     if (log)
249b8af31d4SChaoren Lin         log->Printf ("NativeThreadLinux::%s called with signal 0x%02" PRIx32, __FUNCTION__, signo);
250af245d11STodd Fiala 
251af245d11STodd Fiala     const StateType new_state = StateType::eStateStopped;
252af245d11STodd Fiala     MaybeLogStateChange (new_state);
253af245d11STodd Fiala     m_state = new_state;
254af245d11STodd Fiala 
255af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonSignal;
256af245d11STodd Fiala     m_stop_info.details.signal.signo = signo;
257*c4e25c96SPavel Labath 
258*c4e25c96SPavel Labath     m_stop_description.clear();
259*c4e25c96SPavel Labath     switch (signo)
260*c4e25c96SPavel Labath     {
261*c4e25c96SPavel Labath     case SIGSEGV:
262*c4e25c96SPavel Labath     case SIGBUS:
263*c4e25c96SPavel Labath     case SIGFPE:
264*c4e25c96SPavel Labath     case SIGILL:
265*c4e25c96SPavel Labath         if (! info)
266*c4e25c96SPavel Labath             break;
267*c4e25c96SPavel Labath         const auto reason = GetCrashReason(*info);
268*c4e25c96SPavel Labath         m_stop_description = GetCrashReasonString(reason, reinterpret_cast<uintptr_t>(info->si_addr));
269*c4e25c96SPavel Labath         break;
270*c4e25c96SPavel Labath     }
271af245d11STodd Fiala }
272af245d11STodd Fiala 
273511e5cdcSTodd Fiala bool
274511e5cdcSTodd Fiala NativeThreadLinux::IsStopped (int *signo)
275511e5cdcSTodd Fiala {
276511e5cdcSTodd Fiala     if (!StateIsStoppedState (m_state, false))
277511e5cdcSTodd Fiala         return false;
278511e5cdcSTodd Fiala 
279511e5cdcSTodd Fiala     // If we are stopped by a signal, return the signo.
280511e5cdcSTodd Fiala     if (signo &&
281511e5cdcSTodd Fiala         m_state == StateType::eStateStopped &&
282511e5cdcSTodd Fiala         m_stop_info.reason == StopReason::eStopReasonSignal)
283511e5cdcSTodd Fiala     {
284511e5cdcSTodd Fiala         *signo = m_stop_info.details.signal.signo;
285511e5cdcSTodd Fiala     }
286511e5cdcSTodd Fiala 
287511e5cdcSTodd Fiala     // Regardless, we are stopped.
288511e5cdcSTodd Fiala     return true;
289511e5cdcSTodd Fiala }
290511e5cdcSTodd Fiala 
291511e5cdcSTodd Fiala 
292af245d11STodd Fiala void
293a9882ceeSTodd Fiala NativeThreadLinux::SetStoppedByExec ()
294a9882ceeSTodd Fiala {
295a9882ceeSTodd Fiala     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
296a9882ceeSTodd Fiala     if (log)
297a9882ceeSTodd Fiala         log->Printf ("NativeThreadLinux::%s()", __FUNCTION__);
298a9882ceeSTodd Fiala 
299a9882ceeSTodd Fiala     const StateType new_state = StateType::eStateStopped;
300a9882ceeSTodd Fiala     MaybeLogStateChange (new_state);
301a9882ceeSTodd Fiala     m_state = new_state;
302a9882ceeSTodd Fiala 
303a9882ceeSTodd Fiala     m_stop_info.reason = StopReason::eStopReasonExec;
304a9882ceeSTodd Fiala     m_stop_info.details.signal.signo = SIGSTOP;
305a9882ceeSTodd Fiala }
306a9882ceeSTodd Fiala 
307a9882ceeSTodd Fiala void
308af245d11STodd Fiala NativeThreadLinux::SetStoppedByBreakpoint ()
309af245d11STodd Fiala {
310af245d11STodd Fiala     const StateType new_state = StateType::eStateStopped;
311af245d11STodd Fiala     MaybeLogStateChange (new_state);
312af245d11STodd Fiala     m_state = new_state;
313af245d11STodd Fiala 
31428e57429SChaoren Lin     m_stop_info.reason = StopReason::eStopReasonBreakpoint;
315af245d11STodd Fiala     m_stop_info.details.signal.signo = SIGTRAP;
31618fe6404SChaoren Lin     m_stop_description.clear();
31718fe6404SChaoren Lin }
31818fe6404SChaoren Lin 
31918fe6404SChaoren Lin void
320c16f5dcaSChaoren Lin NativeThreadLinux::SetStoppedByWatchpoint (uint32_t wp_index)
32118fe6404SChaoren Lin {
32218fe6404SChaoren Lin     const StateType new_state = StateType::eStateStopped;
32318fe6404SChaoren Lin     MaybeLogStateChange (new_state);
32418fe6404SChaoren Lin     m_state = new_state;
32518fe6404SChaoren Lin     m_stop_description.clear ();
326c16f5dcaSChaoren Lin 
327c16f5dcaSChaoren Lin     lldbassert(wp_index != LLDB_INVALID_INDEX32 &&
328c16f5dcaSChaoren Lin                "wp_index cannot be invalid");
329eadb2a9eSTamas Berghammer 
33018fe6404SChaoren Lin     std::ostringstream ostr;
331c16f5dcaSChaoren Lin     ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
332c16f5dcaSChaoren Lin     ostr << wp_index;
33318fe6404SChaoren Lin     m_stop_description = ostr.str();
334eadb2a9eSTamas Berghammer 
335eadb2a9eSTamas Berghammer     m_stop_info.reason = StopReason::eStopReasonWatchpoint;
336eadb2a9eSTamas Berghammer     m_stop_info.details.signal.signo = SIGTRAP;
337af245d11STodd Fiala }
338af245d11STodd Fiala 
339af245d11STodd Fiala bool
340af245d11STodd Fiala NativeThreadLinux::IsStoppedAtBreakpoint ()
341af245d11STodd Fiala {
34218fe6404SChaoren Lin     return GetState () == StateType::eStateStopped &&
34318fe6404SChaoren Lin         m_stop_info.reason == StopReason::eStopReasonBreakpoint;
34418fe6404SChaoren Lin }
345af245d11STodd Fiala 
34618fe6404SChaoren Lin bool
34718fe6404SChaoren Lin NativeThreadLinux::IsStoppedAtWatchpoint ()
34818fe6404SChaoren Lin {
34918fe6404SChaoren Lin     return GetState () == StateType::eStateStopped &&
35018fe6404SChaoren Lin         m_stop_info.reason == StopReason::eStopReasonWatchpoint;
351af245d11STodd Fiala }
352af245d11STodd Fiala 
353af245d11STodd Fiala void
35428e57429SChaoren Lin NativeThreadLinux::SetStoppedByTrace ()
35528e57429SChaoren Lin {
35628e57429SChaoren Lin     const StateType new_state = StateType::eStateStopped;
35728e57429SChaoren Lin     MaybeLogStateChange (new_state);
35828e57429SChaoren Lin     m_state = new_state;
35928e57429SChaoren Lin 
36028e57429SChaoren Lin     m_stop_info.reason = StopReason::eStopReasonTrace;
36128e57429SChaoren Lin     m_stop_info.details.signal.signo = SIGTRAP;
36228e57429SChaoren Lin }
36328e57429SChaoren Lin 
36428e57429SChaoren Lin void
365af245d11STodd Fiala NativeThreadLinux::SetSuspended ()
366af245d11STodd Fiala {
367af245d11STodd Fiala     const StateType new_state = StateType::eStateSuspended;
368af245d11STodd Fiala     MaybeLogStateChange (new_state);
369af245d11STodd Fiala     m_state = new_state;
370af245d11STodd Fiala 
371af245d11STodd Fiala     // FIXME what makes sense here? Do we need a suspended StopReason?
372af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonNone;
373af245d11STodd Fiala }
374af245d11STodd Fiala 
375af245d11STodd Fiala void
376af245d11STodd Fiala NativeThreadLinux::SetExited ()
377af245d11STodd Fiala {
378af245d11STodd Fiala     const StateType new_state = StateType::eStateExited;
379af245d11STodd Fiala     MaybeLogStateChange (new_state);
380af245d11STodd Fiala     m_state = new_state;
381af245d11STodd Fiala 
382af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonThreadExiting;
383af245d11STodd Fiala }
384af245d11STodd Fiala 
3858c8ff7afSPavel Labath Error
3868c8ff7afSPavel Labath NativeThreadLinux::RequestStop ()
3878c8ff7afSPavel Labath {
3888c8ff7afSPavel Labath     Log* log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
3898c8ff7afSPavel Labath 
3908c8ff7afSPavel Labath     const auto process_sp = GetProcess();
3918c8ff7afSPavel Labath     if (! process_sp)
3928c8ff7afSPavel Labath         return Error("Process is null.");
3938c8ff7afSPavel Labath 
3948c8ff7afSPavel Labath     lldb::pid_t pid = process_sp->GetID();
3958c8ff7afSPavel Labath     lldb::tid_t tid = GetID();
3968c8ff7afSPavel Labath 
3978c8ff7afSPavel Labath     if (log)
3988c8ff7afSPavel Labath         log->Printf ("NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64 ", tid: %" PRIu64 ")", __FUNCTION__, pid, tid);
3998c8ff7afSPavel Labath 
4008c8ff7afSPavel Labath     Error err;
4018c8ff7afSPavel Labath     errno = 0;
4028c8ff7afSPavel Labath     if (::tgkill (pid, tid, SIGSTOP) != 0)
4038c8ff7afSPavel Labath     {
4048c8ff7afSPavel Labath         err.SetErrorToErrno ();
4058c8ff7afSPavel Labath         if (log)
4068c8ff7afSPavel Labath             log->Printf ("NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64 ", SIGSTOP) failed: %s", __FUNCTION__, pid, tid, err.AsCString ());
4078c8ff7afSPavel Labath     }
4088c8ff7afSPavel Labath     else
4098c8ff7afSPavel Labath         m_thread_context.stop_requested = true;
4108c8ff7afSPavel Labath 
4118c8ff7afSPavel Labath     return err;
4128c8ff7afSPavel Labath }
4138c8ff7afSPavel Labath 
414af245d11STodd Fiala void
415af245d11STodd Fiala NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state)
416af245d11STodd Fiala {
417af245d11STodd Fiala     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
418af245d11STodd Fiala     // If we're not logging, we're done.
419af245d11STodd Fiala     if (!log)
420af245d11STodd Fiala         return;
421af245d11STodd Fiala 
422af245d11STodd Fiala     // If this is a state change to the same state, we're done.
423af245d11STodd Fiala     lldb::StateType old_state = m_state;
424af245d11STodd Fiala     if (new_state == old_state)
425af245d11STodd Fiala         return;
426af245d11STodd Fiala 
427af245d11STodd Fiala     NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
428af245d11STodd Fiala     lldb::pid_t pid = m_process_sp ? m_process_sp->GetID () : LLDB_INVALID_PROCESS_ID;
429af245d11STodd Fiala 
430af245d11STodd Fiala     // Log it.
431af245d11STodd Fiala     log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state));
432af245d11STodd Fiala }
433