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