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