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