xref: /llvm-project/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp (revision 3294de270e86c0d060f6ca3cf43294286ae68222)
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 #include <sstream>
14 
15 #include "NativeProcessLinux.h"
16 #include "NativeRegisterContextLinux_arm64.h"
17 #include "NativeRegisterContextLinux_x86_64.h"
18 #include "NativeRegisterContextLinux_mips64.h"
19 
20 #include "lldb/Core/Log.h"
21 #include "lldb/Core/State.h"
22 #include "lldb/Host/Host.h"
23 #include "lldb/Host/HostInfo.h"
24 #include "lldb/Host/HostNativeThread.h"
25 #include "lldb/lldb-enumerations.h"
26 
27 #include "llvm/ADT/SmallString.h"
28 
29 #include "Plugins/Process/POSIX/CrashReason.h"
30 
31 #include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
32 #include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
33 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
34 #include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
35 #include "Plugins/Process/Utility/RegisterInfoInterface.h"
36 
37 using namespace lldb;
38 using namespace lldb_private;
39 
40 namespace
41 {
42     void LogThreadStopInfo (Log &log, const ThreadStopInfo &stop_info, const char *const header)
43     {
44         switch (stop_info.reason)
45         {
46             case eStopReasonSignal:
47                 log.Printf ("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
48                 return;
49             case eStopReasonException:
50                 log.Printf ("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header, stop_info.details.exception.type);
51                 return;
52             case eStopReasonExec:
53                 log.Printf ("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
54                 return;
55             default:
56                 log.Printf ("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header, static_cast<uint32_t> (stop_info.reason));
57         }
58     }
59 }
60 
61 NativeThreadLinux::NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid) :
62     NativeThreadProtocol (process, tid),
63     m_state (StateType::eStateInvalid),
64     m_stop_info (),
65     m_reg_context_sp (),
66     m_stop_description ()
67 {
68 }
69 
70 std::string
71 NativeThreadLinux::GetName()
72 {
73     NativeProcessProtocolSP process_sp = m_process_wp.lock ();
74     if (!process_sp)
75         return "<unknown: no process>";
76 
77     // const NativeProcessLinux *const process = reinterpret_cast<NativeProcessLinux*> (process_sp->get ());
78     llvm::SmallString<32> thread_name;
79     HostNativeThread::GetName(GetID(), thread_name);
80     return thread_name.c_str();
81 }
82 
83 lldb::StateType
84 NativeThreadLinux::GetState ()
85 {
86     return m_state;
87 }
88 
89 
90 bool
91 NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info, std::string& description)
92 {
93     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
94 
95     description.clear();
96 
97     switch (m_state)
98     {
99     case eStateStopped:
100     case eStateCrashed:
101     case eStateExited:
102     case eStateSuspended:
103     case eStateUnloaded:
104         if (log)
105             LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread:");
106         stop_info = m_stop_info;
107         switch (m_stop_info.reason)
108         {
109             case StopReason::eStopReasonException:
110             case StopReason::eStopReasonBreakpoint:
111             case StopReason::eStopReasonWatchpoint:
112                 description = m_stop_description;
113             default:
114                 break;
115         }
116         if (log)
117             LogThreadStopInfo (*log, stop_info, "returned stop_info:");
118 
119         return true;
120 
121     case eStateInvalid:
122     case eStateConnected:
123     case eStateAttaching:
124     case eStateLaunching:
125     case eStateRunning:
126     case eStateStepping:
127     case eStateDetached:
128         if (log)
129         {
130             log->Printf ("NativeThreadLinux::%s tid %" PRIu64 " in state %s cannot answer stop reason",
131                     __FUNCTION__, GetID (), StateAsCString (m_state));
132         }
133         return false;
134     }
135     llvm_unreachable("unhandled StateType!");
136 }
137 
138 lldb_private::NativeRegisterContextSP
139 NativeThreadLinux::GetRegisterContext ()
140 {
141     // Return the register context if we already created it.
142     if (m_reg_context_sp)
143         return m_reg_context_sp;
144 
145     // First select the appropriate RegisterInfoInterface.
146     RegisterInfoInterface *reg_interface = nullptr;
147     NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
148     if (!m_process_sp)
149         return NativeRegisterContextSP ();
150 
151     ArchSpec target_arch;
152     if (!m_process_sp->GetArchitecture (target_arch))
153         return NativeRegisterContextSP ();
154 
155     switch (target_arch.GetTriple().getOS())
156     {
157         case llvm::Triple::Linux:
158             switch (target_arch.GetMachine())
159             {
160             case llvm::Triple::aarch64:
161                 assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host");
162                 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm64(target_arch));
163                 break;
164             case llvm::Triple::x86:
165             case llvm::Triple::x86_64:
166                 if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
167                 {
168                     // 32-bit hosts run with a RegisterContextLinux_i386 context.
169                     reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_i386(target_arch));
170                 }
171                 else
172                 {
173                     assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
174                            "Register setting path assumes this is a 64-bit host");
175                     // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context.
176                     reg_interface = static_cast<RegisterInfoInterface*> (new RegisterContextLinux_x86_64 (target_arch));
177                 }
178                 break;
179             case llvm::Triple::mips64:
180             case llvm::Triple::mips64el:
181                 assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8)
182                     && "Register setting path assumes this is a 64-bit host");
183                 reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_mips64 (target_arch));
184                 break;
185             default:
186                 break;
187             }
188             break;
189         default:
190             break;
191     }
192 
193     assert(reg_interface && "OS or CPU not supported!");
194     if (!reg_interface)
195         return NativeRegisterContextSP ();
196 
197     // Now create the register context.
198     switch (target_arch.GetMachine())
199     {
200 #if 0
201         case llvm::Triple::mips64:
202         {
203             RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
204             m_posix_thread = reg_ctx;
205             m_reg_context_sp.reset(reg_ctx);
206             break;
207         }
208 #endif
209         case llvm::Triple::mips64:
210         case llvm::Triple::mips64el:
211         {
212             const uint32_t concrete_frame_idx = 0;
213             m_reg_context_sp.reset (new NativeRegisterContextLinux_mips64 (*this, concrete_frame_idx, reg_interface));
214             break;
215         }
216         case llvm::Triple::aarch64:
217         {
218             const uint32_t concrete_frame_idx = 0;
219             m_reg_context_sp.reset (new NativeRegisterContextLinux_arm64(*this, concrete_frame_idx, reg_interface));
220             break;
221         }
222         case llvm::Triple::x86:
223         case llvm::Triple::x86_64:
224         {
225             const uint32_t concrete_frame_idx = 0;
226             m_reg_context_sp.reset (new NativeRegisterContextLinux_x86_64(*this, concrete_frame_idx, reg_interface));
227             break;
228         }
229         default:
230             break;
231     }
232 
233     return m_reg_context_sp;
234 }
235 
236 Error
237 NativeThreadLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
238 {
239     if (!hardware)
240         return Error ("not implemented");
241     if (m_state == eStateLaunching)
242         return Error ();
243     Error error = RemoveWatchpoint(addr);
244     if (error.Fail()) return error;
245     NativeRegisterContextSP reg_ctx = GetRegisterContext ();
246     uint32_t wp_index =
247         reg_ctx->SetHardwareWatchpoint (addr, size, watch_flags);
248     if (wp_index == LLDB_INVALID_INDEX32)
249         return Error ("Setting hardware watchpoint failed.");
250     m_watchpoint_index_map.insert({addr, wp_index});
251     return Error ();
252 }
253 
254 Error
255 NativeThreadLinux::RemoveWatchpoint (lldb::addr_t addr)
256 {
257     auto wp = m_watchpoint_index_map.find(addr);
258     if (wp == m_watchpoint_index_map.end())
259         return Error ();
260     uint32_t wp_index = wp->second;
261     m_watchpoint_index_map.erase(wp);
262     if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
263         return Error ();
264     return Error ("Clearing hardware watchpoint failed.");
265 }
266 
267 void
268 NativeThreadLinux::SetLaunching ()
269 {
270     const StateType new_state = StateType::eStateLaunching;
271     MaybeLogStateChange (new_state);
272     m_state = new_state;
273 
274     // Also mark it as stopped since launching temporarily stops the newly created thread
275     // in the ptrace machinery.
276     m_stop_info.reason = StopReason::eStopReasonSignal;
277     m_stop_info.details.signal.signo = SIGSTOP;
278 }
279 
280 
281 void
282 NativeThreadLinux::SetRunning ()
283 {
284     const StateType new_state = StateType::eStateRunning;
285     MaybeLogStateChange (new_state);
286     m_state = new_state;
287 
288     m_stop_info.reason = StopReason::eStopReasonNone;
289     m_stop_description.clear();
290 
291     // If watchpoints have been set, but none on this thread,
292     // then this is a new thread. So set all existing watchpoints.
293     if (m_watchpoint_index_map.empty())
294     {
295         const auto process_sp = GetProcess();
296         if (process_sp)
297         {
298             const auto &watchpoint_map = process_sp->GetWatchpointMap();
299             if (watchpoint_map.empty()) return;
300             GetRegisterContext()->ClearAllHardwareWatchpoints();
301             for (const auto &pair : watchpoint_map)
302             {
303                 const auto& wp = pair.second;
304                 SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware);
305             }
306         }
307     }
308 }
309 
310 void
311 NativeThreadLinux::SetStepping ()
312 {
313     const StateType new_state = StateType::eStateStepping;
314     MaybeLogStateChange (new_state);
315     m_state = new_state;
316 
317     m_stop_info.reason = StopReason::eStopReasonNone;
318 }
319 
320 void
321 NativeThreadLinux::SetStoppedBySignal (uint32_t signo)
322 {
323     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
324     if (log)
325         log->Printf ("NativeThreadLinux::%s called with signal 0x%02" PRIx32, __FUNCTION__, signo);
326 
327     const StateType new_state = StateType::eStateStopped;
328     MaybeLogStateChange (new_state);
329     m_state = new_state;
330 
331     m_stop_info.reason = StopReason::eStopReasonSignal;
332     m_stop_info.details.signal.signo = signo;
333 }
334 
335 bool
336 NativeThreadLinux::IsStopped (int *signo)
337 {
338     if (!StateIsStoppedState (m_state, false))
339         return false;
340 
341     // If we are stopped by a signal, return the signo.
342     if (signo &&
343         m_state == StateType::eStateStopped &&
344         m_stop_info.reason == StopReason::eStopReasonSignal)
345     {
346         *signo = m_stop_info.details.signal.signo;
347     }
348 
349     // Regardless, we are stopped.
350     return true;
351 }
352 
353 
354 void
355 NativeThreadLinux::SetStoppedByExec ()
356 {
357     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
358     if (log)
359         log->Printf ("NativeThreadLinux::%s()", __FUNCTION__);
360 
361     const StateType new_state = StateType::eStateStopped;
362     MaybeLogStateChange (new_state);
363     m_state = new_state;
364 
365     m_stop_info.reason = StopReason::eStopReasonExec;
366     m_stop_info.details.signal.signo = SIGSTOP;
367 }
368 
369 void
370 NativeThreadLinux::SetStoppedByBreakpoint ()
371 {
372     const StateType new_state = StateType::eStateStopped;
373     MaybeLogStateChange (new_state);
374     m_state = new_state;
375 
376     m_stop_info.reason = StopReason::eStopReasonBreakpoint;
377     m_stop_info.details.signal.signo = SIGTRAP;
378     m_stop_description.clear();
379 }
380 
381 void
382 NativeThreadLinux::SetStoppedByWatchpoint ()
383 {
384     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
385     lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
386     if (log)
387     {
388         NativeProcessProtocolSP process_sp = m_process_wp.lock ();
389         if (process_sp)
390             pid = process_sp->GetID ();
391     }
392 
393     const StateType new_state = StateType::eStateStopped;
394     MaybeLogStateChange (new_state);
395     m_state = new_state;
396 
397     NativeRegisterContextSP reg_ctx = GetRegisterContext ();
398     const uint32_t num_hw_watchpoints = reg_ctx->NumSupportedHardwareWatchpoints ();
399 
400     m_stop_description.clear ();
401     for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index)
402     {
403         if (reg_ctx->IsWatchpointHit (wp_index).Success())
404         {
405             if (log)
406                 log->Printf ("NativeThreadLinux:%s (pid=%" PRIu64 ", tid=%" PRIu64 ") watchpoint found with idx: %u",
407                              __FUNCTION__, pid, GetID (), wp_index);
408 
409             std::ostringstream ostr;
410             ostr << reg_ctx->GetWatchpointAddress (wp_index) << " " << wp_index;
411             m_stop_description = ostr.str();
412 
413             m_stop_info.reason = StopReason::eStopReasonWatchpoint;
414             m_stop_info.details.signal.signo = SIGTRAP;
415             return;
416         }
417     }
418 
419     // The process reported a watchpoint was hit, but we haven't found the
420     // watchpoint. Assume that a stopped by trace is reported as a hardware
421     // watchpoint what happens on some linux kernels (e.g.: android-arm64
422     // platfrom-21).
423 
424     if (log)
425         log->Printf ("NativeThreadLinux:%s (pid=%" PRIu64 ", tid=%" PRIu64 ") none of the watchpoint was hit.",
426                      __FUNCTION__, pid, GetID ());
427 
428     SetStoppedByTrace ();
429 }
430 
431 bool
432 NativeThreadLinux::IsStoppedAtBreakpoint ()
433 {
434     return GetState () == StateType::eStateStopped &&
435         m_stop_info.reason == StopReason::eStopReasonBreakpoint;
436 }
437 
438 bool
439 NativeThreadLinux::IsStoppedAtWatchpoint ()
440 {
441     return GetState () == StateType::eStateStopped &&
442         m_stop_info.reason == StopReason::eStopReasonWatchpoint;
443 }
444 
445 void
446 NativeThreadLinux::SetStoppedByTrace ()
447 {
448     const StateType new_state = StateType::eStateStopped;
449     MaybeLogStateChange (new_state);
450     m_state = new_state;
451 
452     m_stop_info.reason = StopReason::eStopReasonTrace;
453     m_stop_info.details.signal.signo = SIGTRAP;
454 }
455 
456 void
457 NativeThreadLinux::SetCrashedWithException (const siginfo_t& info)
458 {
459     const StateType new_state = StateType::eStateCrashed;
460     MaybeLogStateChange (new_state);
461     m_state = new_state;
462 
463     m_stop_info.reason = StopReason::eStopReasonException;
464     m_stop_info.details.signal.signo = info.si_signo;
465 
466     const auto reason = GetCrashReason (info);
467     m_stop_description = GetCrashReasonString (reason, reinterpret_cast<lldb::addr_t> (info.si_addr));
468 }
469 
470 void
471 NativeThreadLinux::SetSuspended ()
472 {
473     const StateType new_state = StateType::eStateSuspended;
474     MaybeLogStateChange (new_state);
475     m_state = new_state;
476 
477     // FIXME what makes sense here? Do we need a suspended StopReason?
478     m_stop_info.reason = StopReason::eStopReasonNone;
479 }
480 
481 void
482 NativeThreadLinux::SetExited ()
483 {
484     const StateType new_state = StateType::eStateExited;
485     MaybeLogStateChange (new_state);
486     m_state = new_state;
487 
488     m_stop_info.reason = StopReason::eStopReasonThreadExiting;
489 }
490 
491 void
492 NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state)
493 {
494     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
495     // If we're not logging, we're done.
496     if (!log)
497         return;
498 
499     // If this is a state change to the same state, we're done.
500     lldb::StateType old_state = m_state;
501     if (new_state == old_state)
502         return;
503 
504     NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
505     lldb::pid_t pid = m_process_sp ? m_process_sp->GetID () : LLDB_INVALID_PROCESS_ID;
506 
507     // Log it.
508     log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state));
509 }
510