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