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