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
245c4e25c96SPavel 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;
257c4e25c96SPavel Labath 
258c4e25c96SPavel Labath     m_stop_description.clear();
2593681c5b8SMohit K. Bhakkad     if (info)
2603681c5b8SMohit K. Bhakkad     {
261c4e25c96SPavel Labath         switch (signo)
262c4e25c96SPavel Labath         {
263c4e25c96SPavel Labath         case SIGSEGV:
264c4e25c96SPavel Labath         case SIGBUS:
265c4e25c96SPavel Labath         case SIGFPE:
266c4e25c96SPavel Labath         case SIGILL:
2673681c5b8SMohit K. Bhakkad              //In case of MIPS64 target, SI_KERNEL is generated for invalid 64bit address.
2683681c5b8SMohit K. Bhakkad              const auto reason = (info->si_signo == SIGBUS && info->si_code == SI_KERNEL) ?
2693681c5b8SMohit K. Bhakkad                                   CrashReason::eInvalidAddress : GetCrashReason(*info);
270c4e25c96SPavel Labath              m_stop_description = GetCrashReasonString(reason, reinterpret_cast<uintptr_t>(info->si_addr));
271c4e25c96SPavel Labath              break;
272c4e25c96SPavel Labath         }
273af245d11STodd Fiala     }
2743681c5b8SMohit K. Bhakkad }
275af245d11STodd Fiala 
276511e5cdcSTodd Fiala bool
277511e5cdcSTodd Fiala NativeThreadLinux::IsStopped (int *signo)
278511e5cdcSTodd Fiala {
279511e5cdcSTodd Fiala     if (!StateIsStoppedState (m_state, false))
280511e5cdcSTodd Fiala         return false;
281511e5cdcSTodd Fiala 
282511e5cdcSTodd Fiala     // If we are stopped by a signal, return the signo.
283511e5cdcSTodd Fiala     if (signo &&
284511e5cdcSTodd Fiala         m_state == StateType::eStateStopped &&
285511e5cdcSTodd Fiala         m_stop_info.reason == StopReason::eStopReasonSignal)
286511e5cdcSTodd Fiala     {
287511e5cdcSTodd Fiala         *signo = m_stop_info.details.signal.signo;
288511e5cdcSTodd Fiala     }
289511e5cdcSTodd Fiala 
290511e5cdcSTodd Fiala     // Regardless, we are stopped.
291511e5cdcSTodd Fiala     return true;
292511e5cdcSTodd Fiala }
293511e5cdcSTodd Fiala 
294511e5cdcSTodd Fiala 
295af245d11STodd Fiala void
296a9882ceeSTodd Fiala NativeThreadLinux::SetStoppedByExec ()
297a9882ceeSTodd Fiala {
298a9882ceeSTodd Fiala     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
299a9882ceeSTodd Fiala     if (log)
300a9882ceeSTodd Fiala         log->Printf ("NativeThreadLinux::%s()", __FUNCTION__);
301a9882ceeSTodd Fiala 
302a9882ceeSTodd Fiala     const StateType new_state = StateType::eStateStopped;
303a9882ceeSTodd Fiala     MaybeLogStateChange (new_state);
304a9882ceeSTodd Fiala     m_state = new_state;
305a9882ceeSTodd Fiala 
306a9882ceeSTodd Fiala     m_stop_info.reason = StopReason::eStopReasonExec;
307a9882ceeSTodd Fiala     m_stop_info.details.signal.signo = SIGSTOP;
308a9882ceeSTodd Fiala }
309a9882ceeSTodd Fiala 
310a9882ceeSTodd Fiala void
311af245d11STodd Fiala NativeThreadLinux::SetStoppedByBreakpoint ()
312af245d11STodd Fiala {
313af245d11STodd Fiala     const StateType new_state = StateType::eStateStopped;
314af245d11STodd Fiala     MaybeLogStateChange (new_state);
315af245d11STodd Fiala     m_state = new_state;
316af245d11STodd Fiala 
31728e57429SChaoren Lin     m_stop_info.reason = StopReason::eStopReasonBreakpoint;
318af245d11STodd Fiala     m_stop_info.details.signal.signo = SIGTRAP;
31918fe6404SChaoren Lin     m_stop_description.clear();
32018fe6404SChaoren Lin }
32118fe6404SChaoren Lin 
32218fe6404SChaoren Lin void
323c16f5dcaSChaoren Lin NativeThreadLinux::SetStoppedByWatchpoint (uint32_t wp_index)
32418fe6404SChaoren Lin {
32518fe6404SChaoren Lin     const StateType new_state = StateType::eStateStopped;
32618fe6404SChaoren Lin     MaybeLogStateChange (new_state);
32718fe6404SChaoren Lin     m_state = new_state;
32818fe6404SChaoren Lin     m_stop_description.clear ();
329c16f5dcaSChaoren Lin 
330c16f5dcaSChaoren Lin     lldbassert(wp_index != LLDB_INVALID_INDEX32 &&
331c16f5dcaSChaoren Lin                "wp_index cannot be invalid");
332eadb2a9eSTamas Berghammer 
33318fe6404SChaoren Lin     std::ostringstream ostr;
334c16f5dcaSChaoren Lin     ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
335c16f5dcaSChaoren Lin     ostr << wp_index;
336*83143504SJaydeep Patil 
337*83143504SJaydeep Patil     /*
338*83143504SJaydeep Patil      * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For example:
339*83143504SJaydeep Patil      * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at 'm', then
340*83143504SJaydeep Patil      * watch exception is generated even when 'n' is read/written. To handle this case,
341*83143504SJaydeep Patil      * find the base address of the load/store instruction and append it in the stop-info
342*83143504SJaydeep Patil      * packet.
343*83143504SJaydeep Patil     */
344*83143504SJaydeep Patil     ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index);
345*83143504SJaydeep Patil 
34618fe6404SChaoren Lin     m_stop_description = ostr.str();
347eadb2a9eSTamas Berghammer 
348eadb2a9eSTamas Berghammer     m_stop_info.reason = StopReason::eStopReasonWatchpoint;
349eadb2a9eSTamas Berghammer     m_stop_info.details.signal.signo = SIGTRAP;
350af245d11STodd Fiala }
351af245d11STodd Fiala 
352af245d11STodd Fiala bool
353af245d11STodd Fiala NativeThreadLinux::IsStoppedAtBreakpoint ()
354af245d11STodd Fiala {
35518fe6404SChaoren Lin     return GetState () == StateType::eStateStopped &&
35618fe6404SChaoren Lin         m_stop_info.reason == StopReason::eStopReasonBreakpoint;
35718fe6404SChaoren Lin }
358af245d11STodd Fiala 
35918fe6404SChaoren Lin bool
36018fe6404SChaoren Lin NativeThreadLinux::IsStoppedAtWatchpoint ()
36118fe6404SChaoren Lin {
36218fe6404SChaoren Lin     return GetState () == StateType::eStateStopped &&
36318fe6404SChaoren Lin         m_stop_info.reason == StopReason::eStopReasonWatchpoint;
364af245d11STodd Fiala }
365af245d11STodd Fiala 
366af245d11STodd Fiala void
36728e57429SChaoren Lin NativeThreadLinux::SetStoppedByTrace ()
36828e57429SChaoren Lin {
36928e57429SChaoren Lin     const StateType new_state = StateType::eStateStopped;
37028e57429SChaoren Lin     MaybeLogStateChange (new_state);
37128e57429SChaoren Lin     m_state = new_state;
37228e57429SChaoren Lin 
37328e57429SChaoren Lin     m_stop_info.reason = StopReason::eStopReasonTrace;
37428e57429SChaoren Lin     m_stop_info.details.signal.signo = SIGTRAP;
37528e57429SChaoren Lin }
37628e57429SChaoren Lin 
37728e57429SChaoren Lin void
37805569f67SPavel Labath NativeThreadLinux::SetStoppedWithNoReason ()
379af245d11STodd Fiala {
38005569f67SPavel Labath     const StateType new_state = StateType::eStateStopped;
381af245d11STodd Fiala     MaybeLogStateChange (new_state);
382af245d11STodd Fiala     m_state = new_state;
383af245d11STodd Fiala 
384af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonNone;
38505569f67SPavel Labath     m_stop_info.details.signal.signo = 0;
386af245d11STodd Fiala }
387af245d11STodd Fiala 
388af245d11STodd Fiala void
389af245d11STodd Fiala NativeThreadLinux::SetExited ()
390af245d11STodd Fiala {
391af245d11STodd Fiala     const StateType new_state = StateType::eStateExited;
392af245d11STodd Fiala     MaybeLogStateChange (new_state);
393af245d11STodd Fiala     m_state = new_state;
394af245d11STodd Fiala 
395af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonThreadExiting;
396af245d11STodd Fiala }
397af245d11STodd Fiala 
3988c8ff7afSPavel Labath Error
3998c8ff7afSPavel Labath NativeThreadLinux::RequestStop ()
4008c8ff7afSPavel Labath {
4018c8ff7afSPavel Labath     Log* log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
4028c8ff7afSPavel Labath 
4038c8ff7afSPavel Labath     const auto process_sp = GetProcess();
4048c8ff7afSPavel Labath     if (! process_sp)
4058c8ff7afSPavel Labath         return Error("Process is null.");
4068c8ff7afSPavel Labath 
4078c8ff7afSPavel Labath     lldb::pid_t pid = process_sp->GetID();
4088c8ff7afSPavel Labath     lldb::tid_t tid = GetID();
4098c8ff7afSPavel Labath 
4108c8ff7afSPavel Labath     if (log)
4118c8ff7afSPavel Labath         log->Printf ("NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64 ", tid: %" PRIu64 ")", __FUNCTION__, pid, tid);
4128c8ff7afSPavel Labath 
4138c8ff7afSPavel Labath     Error err;
4148c8ff7afSPavel Labath     errno = 0;
4158c8ff7afSPavel Labath     if (::tgkill (pid, tid, SIGSTOP) != 0)
4168c8ff7afSPavel Labath     {
4178c8ff7afSPavel Labath         err.SetErrorToErrno ();
4188c8ff7afSPavel Labath         if (log)
4198c8ff7afSPavel Labath             log->Printf ("NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64 ", SIGSTOP) failed: %s", __FUNCTION__, pid, tid, err.AsCString ());
4208c8ff7afSPavel Labath     }
4218c8ff7afSPavel Labath     else
4228c8ff7afSPavel Labath         m_thread_context.stop_requested = true;
4238c8ff7afSPavel Labath 
4248c8ff7afSPavel Labath     return err;
4258c8ff7afSPavel Labath }
4268c8ff7afSPavel Labath 
427af245d11STodd Fiala void
428af245d11STodd Fiala NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state)
429af245d11STodd Fiala {
430af245d11STodd Fiala     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
431af245d11STodd Fiala     // If we're not logging, we're done.
432af245d11STodd Fiala     if (!log)
433af245d11STodd Fiala         return;
434af245d11STodd Fiala 
435af245d11STodd Fiala     // If this is a state change to the same state, we're done.
436af245d11STodd Fiala     lldb::StateType old_state = m_state;
437af245d11STodd Fiala     if (new_state == old_state)
438af245d11STodd Fiala         return;
439af245d11STodd Fiala 
440af245d11STodd Fiala     NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
441af245d11STodd Fiala     lldb::pid_t pid = m_process_sp ? m_process_sp->GetID () : LLDB_INVALID_PROCESS_ID;
442af245d11STodd Fiala 
443af245d11STodd Fiala     // Log it.
444af245d11STodd Fiala     log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state));
445af245d11STodd Fiala }
446