1*af245d11STodd Fiala //===-- NativeThreadLinux.cpp --------------------------------- -*- C++ -*-===//
2*af245d11STodd Fiala //
3*af245d11STodd Fiala //                     The LLVM Compiler Infrastructure
4*af245d11STodd Fiala //
5*af245d11STodd Fiala // This file is distributed under the University of Illinois Open Source
6*af245d11STodd Fiala // License. See LICENSE.TXT for details.
7*af245d11STodd Fiala //
8*af245d11STodd Fiala //===----------------------------------------------------------------------===//
9*af245d11STodd Fiala 
10*af245d11STodd Fiala #include "NativeThreadLinux.h"
11*af245d11STodd Fiala 
12*af245d11STodd Fiala #include <signal.h>
13*af245d11STodd Fiala 
14*af245d11STodd Fiala #include "NativeProcessLinux.h"
15*af245d11STodd Fiala #include "lldb/Core/Log.h"
16*af245d11STodd Fiala #include "lldb/Core/State.h"
17*af245d11STodd Fiala #include "lldb/Host/Host.h"
18*af245d11STodd Fiala #include "lldb/lldb-enumerations.h"
19*af245d11STodd Fiala #include "lldb/lldb-private-log.h"
20*af245d11STodd Fiala #include "Plugins/Process/Utility/NativeRegisterContextLinux_x86_64.h"
21*af245d11STodd Fiala #include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
22*af245d11STodd Fiala #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
23*af245d11STodd Fiala #include "Plugins/Process/Utility/RegisterInfoInterface.h"
24*af245d11STodd Fiala 
25*af245d11STodd Fiala using namespace lldb;
26*af245d11STodd Fiala using namespace lldb_private;
27*af245d11STodd Fiala 
28*af245d11STodd Fiala namespace
29*af245d11STodd Fiala {
30*af245d11STodd Fiala     void LogThreadStopInfo (Log &log, const ThreadStopInfo &stop_info, const char *const header)
31*af245d11STodd Fiala     {
32*af245d11STodd Fiala         switch (stop_info.reason)
33*af245d11STodd Fiala         {
34*af245d11STodd Fiala             case eStopReasonSignal:
35*af245d11STodd Fiala                 log.Printf ("%s: %s: signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
36*af245d11STodd Fiala                 return;
37*af245d11STodd Fiala             case eStopReasonException:
38*af245d11STodd Fiala                 log.Printf ("%s: %s: exception type 0x%" PRIx64, __FUNCTION__, header, stop_info.details.exception.type);
39*af245d11STodd Fiala                 return;
40*af245d11STodd Fiala             default:
41*af245d11STodd Fiala                 log.Printf ("%s: %s: invalid stop reason %" PRIu32, __FUNCTION__, header, static_cast<uint32_t> (stop_info.reason));
42*af245d11STodd Fiala         }
43*af245d11STodd Fiala     }
44*af245d11STodd Fiala }
45*af245d11STodd Fiala 
46*af245d11STodd Fiala NativeThreadLinux::NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid) :
47*af245d11STodd Fiala     NativeThreadProtocol (process, tid),
48*af245d11STodd Fiala     m_state (StateType::eStateInvalid),
49*af245d11STodd Fiala     m_stop_info (),
50*af245d11STodd Fiala     m_reg_context_sp ()
51*af245d11STodd Fiala {
52*af245d11STodd Fiala }
53*af245d11STodd Fiala 
54*af245d11STodd Fiala const char *
55*af245d11STodd Fiala NativeThreadLinux::GetName()
56*af245d11STodd Fiala {
57*af245d11STodd Fiala     NativeProcessProtocolSP process_sp = m_process_wp.lock ();
58*af245d11STodd Fiala     if (!process_sp)
59*af245d11STodd Fiala         return "<unknown: no process>";
60*af245d11STodd Fiala 
61*af245d11STodd Fiala     // const NativeProcessLinux *const process = reinterpret_cast<NativeProcessLinux*> (process_sp->get ());
62*af245d11STodd Fiala     return Host::GetThreadName (process_sp->GetID (), GetID ()).c_str ();
63*af245d11STodd Fiala }
64*af245d11STodd Fiala 
65*af245d11STodd Fiala lldb::StateType
66*af245d11STodd Fiala NativeThreadLinux::GetState ()
67*af245d11STodd Fiala {
68*af245d11STodd Fiala     return m_state;
69*af245d11STodd Fiala }
70*af245d11STodd Fiala 
71*af245d11STodd Fiala 
72*af245d11STodd Fiala bool
73*af245d11STodd Fiala NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info)
74*af245d11STodd Fiala {
75*af245d11STodd Fiala     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
76*af245d11STodd Fiala     switch (m_state)
77*af245d11STodd Fiala     {
78*af245d11STodd Fiala     case eStateStopped:
79*af245d11STodd Fiala     case eStateCrashed:
80*af245d11STodd Fiala     case eStateExited:
81*af245d11STodd Fiala     case eStateSuspended:
82*af245d11STodd Fiala     case eStateUnloaded:
83*af245d11STodd Fiala         if (log)
84*af245d11STodd Fiala             LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread: ");
85*af245d11STodd Fiala         stop_info = m_stop_info;
86*af245d11STodd Fiala         if (log)
87*af245d11STodd Fiala             LogThreadStopInfo (*log, stop_info, "returned stop_info: ");
88*af245d11STodd Fiala         return true;
89*af245d11STodd Fiala 
90*af245d11STodd Fiala     case eStateInvalid:
91*af245d11STodd Fiala     case eStateConnected:
92*af245d11STodd Fiala     case eStateAttaching:
93*af245d11STodd Fiala     case eStateLaunching:
94*af245d11STodd Fiala     case eStateRunning:
95*af245d11STodd Fiala     case eStateStepping:
96*af245d11STodd Fiala     case eStateDetached:
97*af245d11STodd Fiala     default:
98*af245d11STodd Fiala         if (log)
99*af245d11STodd Fiala         {
100*af245d11STodd Fiala             log->Printf ("NativeThreadLinux::%s tid %" PRIu64 " in state %s cannot answer stop reason",
101*af245d11STodd Fiala                     __FUNCTION__, GetID (), StateAsCString (m_state));
102*af245d11STodd Fiala         }
103*af245d11STodd Fiala         return false;
104*af245d11STodd Fiala     }
105*af245d11STodd Fiala }
106*af245d11STodd Fiala 
107*af245d11STodd Fiala lldb_private::NativeRegisterContextSP
108*af245d11STodd Fiala NativeThreadLinux::GetRegisterContext ()
109*af245d11STodd Fiala {
110*af245d11STodd Fiala     // Return the register context if we already created it.
111*af245d11STodd Fiala     if (m_reg_context_sp)
112*af245d11STodd Fiala         return m_reg_context_sp;
113*af245d11STodd Fiala 
114*af245d11STodd Fiala     // First select the appropriate RegisterInfoInterface.
115*af245d11STodd Fiala     RegisterInfoInterface *reg_interface = nullptr;
116*af245d11STodd Fiala     NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
117*af245d11STodd Fiala     if (!m_process_sp)
118*af245d11STodd Fiala         return NativeRegisterContextSP ();
119*af245d11STodd Fiala 
120*af245d11STodd Fiala     ArchSpec target_arch;
121*af245d11STodd Fiala     if (!m_process_sp->GetArchitecture (target_arch))
122*af245d11STodd Fiala         return NativeRegisterContextSP ();
123*af245d11STodd Fiala 
124*af245d11STodd Fiala     switch (target_arch.GetTriple().getOS())
125*af245d11STodd Fiala     {
126*af245d11STodd Fiala         case llvm::Triple::Linux:
127*af245d11STodd Fiala             switch (target_arch.GetMachine())
128*af245d11STodd Fiala             {
129*af245d11STodd Fiala             case llvm::Triple::x86:
130*af245d11STodd Fiala             case llvm::Triple::x86_64:
131*af245d11STodd Fiala                 if (Host::GetArchitecture().GetAddressByteSize() == 4)
132*af245d11STodd Fiala                 {
133*af245d11STodd Fiala                     // 32-bit hosts run with a RegisterContextLinux_i386 context.
134*af245d11STodd Fiala                     reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_i386(target_arch));
135*af245d11STodd Fiala                 }
136*af245d11STodd Fiala                 else
137*af245d11STodd Fiala                 {
138*af245d11STodd Fiala                     assert((Host::GetArchitecture ().GetAddressByteSize () == 8) && "Register setting path assumes this is a 64-bit host");
139*af245d11STodd Fiala                     // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context.
140*af245d11STodd Fiala                     reg_interface = static_cast<RegisterInfoInterface*> (new RegisterContextLinux_x86_64 (target_arch));
141*af245d11STodd Fiala                 }
142*af245d11STodd Fiala                 break;
143*af245d11STodd Fiala             default:
144*af245d11STodd Fiala                 break;
145*af245d11STodd Fiala             }
146*af245d11STodd Fiala             break;
147*af245d11STodd Fiala         default:
148*af245d11STodd Fiala             break;
149*af245d11STodd Fiala     }
150*af245d11STodd Fiala 
151*af245d11STodd Fiala     assert(reg_interface && "OS or CPU not supported!");
152*af245d11STodd Fiala     if (!reg_interface)
153*af245d11STodd Fiala         return NativeRegisterContextSP ();
154*af245d11STodd Fiala 
155*af245d11STodd Fiala     // Now create the register context.
156*af245d11STodd Fiala     switch (target_arch.GetMachine())
157*af245d11STodd Fiala     {
158*af245d11STodd Fiala #if 0
159*af245d11STodd Fiala         case llvm::Triple::mips64:
160*af245d11STodd Fiala         {
161*af245d11STodd Fiala             RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
162*af245d11STodd Fiala             m_posix_thread = reg_ctx;
163*af245d11STodd Fiala             m_reg_context_sp.reset(reg_ctx);
164*af245d11STodd Fiala             break;
165*af245d11STodd Fiala         }
166*af245d11STodd Fiala #endif
167*af245d11STodd Fiala #if 0
168*af245d11STodd Fiala         case llvm::Triple::x86:
169*af245d11STodd Fiala #endif
170*af245d11STodd Fiala         case llvm::Triple::x86_64:
171*af245d11STodd Fiala         {
172*af245d11STodd Fiala             const uint32_t concrete_frame_idx = 0;
173*af245d11STodd Fiala             m_reg_context_sp.reset (new NativeRegisterContextLinux_x86_64(*this, concrete_frame_idx, reg_interface));
174*af245d11STodd Fiala             break;
175*af245d11STodd Fiala         }
176*af245d11STodd Fiala         default:
177*af245d11STodd Fiala             break;
178*af245d11STodd Fiala     }
179*af245d11STodd Fiala 
180*af245d11STodd Fiala     return m_reg_context_sp;
181*af245d11STodd Fiala }
182*af245d11STodd Fiala 
183*af245d11STodd Fiala Error
184*af245d11STodd Fiala NativeThreadLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
185*af245d11STodd Fiala {
186*af245d11STodd Fiala     // TODO implement
187*af245d11STodd Fiala     return Error ("not implemented");
188*af245d11STodd Fiala }
189*af245d11STodd Fiala 
190*af245d11STodd Fiala Error
191*af245d11STodd Fiala NativeThreadLinux::RemoveWatchpoint (lldb::addr_t addr)
192*af245d11STodd Fiala {
193*af245d11STodd Fiala     // TODO implement
194*af245d11STodd Fiala     return Error ("not implemented");
195*af245d11STodd Fiala }
196*af245d11STodd Fiala 
197*af245d11STodd Fiala void
198*af245d11STodd Fiala NativeThreadLinux::SetLaunching ()
199*af245d11STodd Fiala {
200*af245d11STodd Fiala     const StateType new_state = StateType::eStateLaunching;
201*af245d11STodd Fiala     MaybeLogStateChange (new_state);
202*af245d11STodd Fiala     m_state = new_state;
203*af245d11STodd Fiala 
204*af245d11STodd Fiala     // Also mark it as stopped since launching temporarily stops the newly created thread
205*af245d11STodd Fiala     // in the ptrace machinery.
206*af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonSignal;
207*af245d11STodd Fiala     m_stop_info.details.signal.signo = SIGSTOP;
208*af245d11STodd Fiala }
209*af245d11STodd Fiala 
210*af245d11STodd Fiala 
211*af245d11STodd Fiala void
212*af245d11STodd Fiala NativeThreadLinux::SetRunning ()
213*af245d11STodd Fiala {
214*af245d11STodd Fiala     const StateType new_state = StateType::eStateRunning;
215*af245d11STodd Fiala     MaybeLogStateChange (new_state);
216*af245d11STodd Fiala     m_state = new_state;
217*af245d11STodd Fiala 
218*af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonNone;
219*af245d11STodd Fiala }
220*af245d11STodd Fiala 
221*af245d11STodd Fiala void
222*af245d11STodd Fiala NativeThreadLinux::SetStepping ()
223*af245d11STodd Fiala {
224*af245d11STodd Fiala     const StateType new_state = StateType::eStateStepping;
225*af245d11STodd Fiala     MaybeLogStateChange (new_state);
226*af245d11STodd Fiala     m_state = new_state;
227*af245d11STodd Fiala 
228*af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonNone;
229*af245d11STodd Fiala }
230*af245d11STodd Fiala 
231*af245d11STodd Fiala void
232*af245d11STodd Fiala NativeThreadLinux::SetStoppedBySignal (uint32_t signo)
233*af245d11STodd Fiala {
234*af245d11STodd Fiala     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
235*af245d11STodd Fiala     if (log)
236*af245d11STodd Fiala         log->Printf ("NativeThreadLinux::%s called with signal 0x%" PRIx32, __FUNCTION__, signo);
237*af245d11STodd Fiala 
238*af245d11STodd Fiala     const StateType new_state = StateType::eStateStopped;
239*af245d11STodd Fiala     MaybeLogStateChange (new_state);
240*af245d11STodd Fiala     m_state = new_state;
241*af245d11STodd Fiala 
242*af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonSignal;
243*af245d11STodd Fiala     m_stop_info.details.signal.signo = signo;
244*af245d11STodd Fiala }
245*af245d11STodd Fiala 
246*af245d11STodd Fiala void
247*af245d11STodd Fiala NativeThreadLinux::SetStoppedByBreakpoint ()
248*af245d11STodd Fiala {
249*af245d11STodd Fiala     const StateType new_state = StateType::eStateStopped;
250*af245d11STodd Fiala     MaybeLogStateChange (new_state);
251*af245d11STodd Fiala     m_state = new_state;
252*af245d11STodd Fiala 
253*af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonSignal;
254*af245d11STodd Fiala     m_stop_info.details.signal.signo = SIGTRAP;
255*af245d11STodd Fiala }
256*af245d11STodd Fiala 
257*af245d11STodd Fiala bool
258*af245d11STodd Fiala NativeThreadLinux::IsStoppedAtBreakpoint ()
259*af245d11STodd Fiala {
260*af245d11STodd Fiala     // Are we stopped? If not, this can't be a breakpoint.
261*af245d11STodd Fiala     if (GetState () != StateType::eStateStopped)
262*af245d11STodd Fiala         return false;
263*af245d11STodd Fiala 
264*af245d11STodd Fiala     // Was the stop reason a signal with signal number SIGTRAP? If not, not a breakpoint.
265*af245d11STodd Fiala     return (m_stop_info.reason == StopReason::eStopReasonSignal) &&
266*af245d11STodd Fiala             (m_stop_info.details.signal.signo == SIGTRAP);
267*af245d11STodd Fiala }
268*af245d11STodd Fiala 
269*af245d11STodd Fiala void
270*af245d11STodd Fiala NativeThreadLinux::SetCrashedWithException (uint64_t exception_type, lldb::addr_t exception_addr)
271*af245d11STodd Fiala {
272*af245d11STodd Fiala     const StateType new_state = StateType::eStateCrashed;
273*af245d11STodd Fiala     MaybeLogStateChange (new_state);
274*af245d11STodd Fiala     m_state = new_state;
275*af245d11STodd Fiala 
276*af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonException;
277*af245d11STodd Fiala     m_stop_info.details.exception.type = exception_type;
278*af245d11STodd Fiala     m_stop_info.details.exception.data_count = 1;
279*af245d11STodd Fiala     m_stop_info.details.exception.data[0] = exception_addr;
280*af245d11STodd Fiala }
281*af245d11STodd Fiala 
282*af245d11STodd Fiala 
283*af245d11STodd Fiala void
284*af245d11STodd Fiala NativeThreadLinux::SetSuspended ()
285*af245d11STodd Fiala {
286*af245d11STodd Fiala     const StateType new_state = StateType::eStateSuspended;
287*af245d11STodd Fiala     MaybeLogStateChange (new_state);
288*af245d11STodd Fiala     m_state = new_state;
289*af245d11STodd Fiala 
290*af245d11STodd Fiala     // FIXME what makes sense here? Do we need a suspended StopReason?
291*af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonNone;
292*af245d11STodd Fiala }
293*af245d11STodd Fiala 
294*af245d11STodd Fiala void
295*af245d11STodd Fiala NativeThreadLinux::SetExited ()
296*af245d11STodd Fiala {
297*af245d11STodd Fiala     const StateType new_state = StateType::eStateExited;
298*af245d11STodd Fiala     MaybeLogStateChange (new_state);
299*af245d11STodd Fiala     m_state = new_state;
300*af245d11STodd Fiala 
301*af245d11STodd Fiala     m_stop_info.reason = StopReason::eStopReasonThreadExiting;
302*af245d11STodd Fiala }
303*af245d11STodd Fiala 
304*af245d11STodd Fiala void
305*af245d11STodd Fiala NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state)
306*af245d11STodd Fiala {
307*af245d11STodd Fiala     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
308*af245d11STodd Fiala     // If we're not logging, we're done.
309*af245d11STodd Fiala     if (!log)
310*af245d11STodd Fiala         return;
311*af245d11STodd Fiala 
312*af245d11STodd Fiala     // If this is a state change to the same state, we're done.
313*af245d11STodd Fiala     lldb::StateType old_state = m_state;
314*af245d11STodd Fiala     if (new_state == old_state)
315*af245d11STodd Fiala         return;
316*af245d11STodd Fiala 
317*af245d11STodd Fiala     NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
318*af245d11STodd Fiala     lldb::pid_t pid = m_process_sp ? m_process_sp->GetID () : LLDB_INVALID_PROCESS_ID;
319*af245d11STodd Fiala 
320*af245d11STodd Fiala     // Log it.
321*af245d11STodd Fiala     log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state));
322*af245d11STodd Fiala }
323*af245d11STodd Fiala 
324*af245d11STodd Fiala static
325*af245d11STodd Fiala uint32_t MaybeTranslateHostSignoToGdbSigno (uint32_t host_signo)
326*af245d11STodd Fiala {
327*af245d11STodd Fiala     switch (host_signo)
328*af245d11STodd Fiala     {
329*af245d11STodd Fiala         case SIGSEGV: return eGdbSignalBadAccess;
330*af245d11STodd Fiala         case SIGILL:  return eGdbSignalBadInstruction;
331*af245d11STodd Fiala         case SIGFPE:  return eGdbSignalArithmetic;
332*af245d11STodd Fiala         // NOTE: debugserver sends SIGTRAP through unmodified.  Do the same here.
333*af245d11STodd Fiala         // case SIGTRAP: return eGdbSignalBreakpoint;
334*af245d11STodd Fiala 
335*af245d11STodd Fiala         // Nothing for eGdbSignalSoftware (0x95).
336*af245d11STodd Fiala         // Nothing for eGdbSignalEmulation (0x94).
337*af245d11STodd Fiala 
338*af245d11STodd Fiala         default:
339*af245d11STodd Fiala             // No translations.
340*af245d11STodd Fiala             return host_signo;
341*af245d11STodd Fiala     }
342*af245d11STodd Fiala }
343*af245d11STodd Fiala 
344*af245d11STodd Fiala uint32_t
345*af245d11STodd Fiala NativeThreadLinux::TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const
346*af245d11STodd Fiala {
347*af245d11STodd Fiala     switch (stop_info.reason)
348*af245d11STodd Fiala     {
349*af245d11STodd Fiala         case eStopReasonSignal:
350*af245d11STodd Fiala             return MaybeTranslateHostSignoToGdbSigno (stop_info.details.signal.signo);
351*af245d11STodd Fiala             break;
352*af245d11STodd Fiala 
353*af245d11STodd Fiala         case eStopReasonException:
354*af245d11STodd Fiala             // FIXME verify how we handle exception type.
355*af245d11STodd Fiala             return MaybeTranslateHostSignoToGdbSigno (static_cast<uint32_t> (stop_info.details.exception.type));
356*af245d11STodd Fiala             break;
357*af245d11STodd Fiala 
358*af245d11STodd Fiala         default:
359*af245d11STodd Fiala             assert (0 && "unexpected stop_info.reason found");
360*af245d11STodd Fiala             return 0;
361*af245d11STodd Fiala     }
362*af245d11STodd Fiala }
363*af245d11STodd Fiala 
364