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