blob: b1d13668f327de27c5bb188881c162538c58b187 [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>
Chaoren Lin18fe6402015-02-03 01:51:47 +000013#include <sstream>
Todd Fialaaf245d12014-06-30 21:05:18 +000014
15#include "NativeProcessLinux.h"
Pavel Labath0f4b17d2015-08-24 13:25:54 +000016#include "NativeRegisterContextLinux.h"
Pavel Labath605b51b2016-02-23 13:56:30 +000017#include "SingleStepCheck.h"
Todd Fiala2850b1b2014-06-30 23:51:35 +000018
Todd Fialaaf245d12014-06-30 21:05:18 +000019#include "lldb/Core/State.h"
Zachary Turner39de3112014-09-09 20:54:56 +000020#include "lldb/Host/HostNativeThread.h"
Pavel Labath605b51b2016-02-23 13:56:30 +000021#include "lldb/Host/linux/Ptrace.h"
Pavel Labath225b7952017-03-17 09:51:23 +000022#include "lldb/Host/linux/Support.h"
Chaoren Linc16f5dc2015-03-19 23:28:10 +000023#include "lldb/Utility/LLDBAssert.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000024#include "lldb/Utility/Log.h"
Todd Fialaaf245d12014-06-30 21:05:18 +000025#include "lldb/lldb-enumerations.h"
Zachary Turner39de3112014-09-09 20:54:56 +000026
27#include "llvm/ADT/SmallString.h"
28
Chaoren Lin28e57422015-02-03 01:51:25 +000029#include "Plugins/Process/POSIX/CrashReason.h"
30
Pavel Labath8c8ff7a2015-05-11 10:03:10 +000031#include <sys/syscall.h>
32// Try to define a macro to encapsulate the tgkill syscall
Kate Stoneb9c1b512016-09-06 20:57:50 +000033#define tgkill(pid, tid, sig) \
34 syscall(__NR_tgkill, static_cast<::pid_t>(pid), static_cast<::pid_t>(tid), \
35 sig)
Pavel Labath8c8ff7a2015-05-11 10:03:10 +000036
Todd Fialaaf245d12014-06-30 21:05:18 +000037using namespace lldb;
38using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000039using namespace lldb_private::process_linux;
Todd Fialaaf245d12014-06-30 21:05:18 +000040
Kate Stoneb9c1b512016-09-06 20:57:50 +000041namespace {
42void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info,
43 const char *const header) {
44 switch (stop_info.reason) {
45 case eStopReasonNone:
46 log.Printf("%s: %s no stop reason", __FUNCTION__, header);
47 return;
48 case eStopReasonTrace:
49 log.Printf("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header,
50 stop_info.details.signal.signo);
51 return;
52 case eStopReasonBreakpoint:
53 log.Printf("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__,
54 header, stop_info.details.signal.signo);
55 return;
56 case eStopReasonWatchpoint:
57 log.Printf("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__,
58 header, stop_info.details.signal.signo);
59 return;
60 case eStopReasonSignal:
61 log.Printf("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header,
62 stop_info.details.signal.signo);
63 return;
64 case eStopReasonException:
65 log.Printf("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header,
66 stop_info.details.exception.type);
67 return;
68 case eStopReasonExec:
69 log.Printf("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header,
70 stop_info.details.signal.signo);
71 return;
72 case eStopReasonPlanComplete:
73 log.Printf("%s: %s plan complete", __FUNCTION__, header);
74 return;
75 case eStopReasonThreadExiting:
76 log.Printf("%s: %s thread exiting", __FUNCTION__, header);
77 return;
78 case eStopReasonInstrumentation:
79 log.Printf("%s: %s instrumentation", __FUNCTION__, header);
80 return;
81 default:
82 log.Printf("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header,
83 static_cast<uint32_t>(stop_info.reason));
84 }
85}
Todd Fialaaf245d12014-06-30 21:05:18 +000086}
87
Kate Stoneb9c1b512016-09-06 20:57:50 +000088NativeThreadLinux::NativeThreadLinux(NativeProcessLinux *process,
89 lldb::tid_t tid)
90 : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),
91 m_stop_info(), m_reg_context_sp(), m_stop_description() {}
92
93std::string NativeThreadLinux::GetName() {
Pavel Labath225b7952017-03-17 09:51:23 +000094 NativeProcessLinux &process = GetProcess();
Kate Stoneb9c1b512016-09-06 20:57:50 +000095
Pavel Labath225b7952017-03-17 09:51:23 +000096 auto BufferOrError = getProcFile(process.GetID(), GetID(), "comm");
97 if (!BufferOrError)
98 return "";
99 return BufferOrError.get()->getBuffer().rtrim('\n');
Todd Fialaaf245d12014-06-30 21:05:18 +0000100}
101
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102lldb::StateType NativeThreadLinux::GetState() { return m_state; }
Todd Fialaaf245d12014-06-30 21:05:18 +0000103
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104bool NativeThreadLinux::GetStopReason(ThreadStopInfo &stop_info,
105 std::string &description) {
106 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
Todd Fialaaf245d12014-06-30 21:05:18 +0000107
Kate Stoneb9c1b512016-09-06 20:57:50 +0000108 description.clear();
Todd Fialaaf245d12014-06-30 21:05:18 +0000109
Kate Stoneb9c1b512016-09-06 20:57:50 +0000110 switch (m_state) {
111 case eStateStopped:
112 case eStateCrashed:
113 case eStateExited:
114 case eStateSuspended:
115 case eStateUnloaded:
Todd Fialaaf245d12014-06-30 21:05:18 +0000116 if (log)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000117 LogThreadStopInfo(*log, m_stop_info, "m_stop_info in thread:");
118 stop_info = m_stop_info;
119 description = m_stop_description;
120 if (log)
121 LogThreadStopInfo(*log, stop_info, "returned stop_info:");
Todd Fialaaf245d12014-06-30 21:05:18 +0000122
Todd Fiala511e5cd2014-09-11 23:29:14 +0000123 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124
125 case eStateInvalid:
126 case eStateConnected:
127 case eStateAttaching:
128 case eStateLaunching:
129 case eStateRunning:
130 case eStateStepping:
131 case eStateDetached:
132 if (log) {
133 log->Printf("NativeThreadLinux::%s tid %" PRIu64
134 " in state %s cannot answer stop reason",
135 __FUNCTION__, GetID(), StateAsCString(m_state));
136 }
137 return false;
138 }
139 llvm_unreachable("unhandled StateType!");
Todd Fiala511e5cd2014-09-11 23:29:14 +0000140}
141
Kate Stoneb9c1b512016-09-06 20:57:50 +0000142NativeRegisterContextSP NativeThreadLinux::GetRegisterContext() {
143 // Return the register context if we already created it.
144 if (m_reg_context_sp)
145 return m_reg_context_sp;
Pavel Labath605b51b2016-02-23 13:56:30 +0000146
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147 NativeProcessProtocolSP m_process_sp = m_process_wp.lock();
148 if (!m_process_sp)
149 return NativeRegisterContextSP();
150
151 ArchSpec target_arch;
152 if (!m_process_sp->GetArchitecture(target_arch))
153 return NativeRegisterContextSP();
154
155 const uint32_t concrete_frame_idx = 0;
156 m_reg_context_sp.reset(
157 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
158 target_arch, *this, concrete_frame_idx));
159
160 return m_reg_context_sp;
Pavel Labath605b51b2016-02-23 13:56:30 +0000161}
Todd Fiala511e5cd2014-09-11 23:29:14 +0000162
Zachary Turner97206d52017-05-12 04:51:55 +0000163Status NativeThreadLinux::SetWatchpoint(lldb::addr_t addr, size_t size,
164 uint32_t watch_flags, bool hardware) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000165 if (!hardware)
Zachary Turner97206d52017-05-12 04:51:55 +0000166 return Status("not implemented");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000167 if (m_state == eStateLaunching)
Zachary Turner97206d52017-05-12 04:51:55 +0000168 return Status();
169 Status error = RemoveWatchpoint(addr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000170 if (error.Fail())
171 return error;
172 NativeRegisterContextSP reg_ctx = GetRegisterContext();
173 uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags);
174 if (wp_index == LLDB_INVALID_INDEX32)
Zachary Turner97206d52017-05-12 04:51:55 +0000175 return Status("Setting hardware watchpoint failed.");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000176 m_watchpoint_index_map.insert({addr, wp_index});
Zachary Turner97206d52017-05-12 04:51:55 +0000177 return Status();
Todd Fialaa9882ce2014-08-28 15:46:54 +0000178}
179
Zachary Turner97206d52017-05-12 04:51:55 +0000180Status NativeThreadLinux::RemoveWatchpoint(lldb::addr_t addr) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000181 auto wp = m_watchpoint_index_map.find(addr);
182 if (wp == m_watchpoint_index_map.end())
Zachary Turner97206d52017-05-12 04:51:55 +0000183 return Status();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184 uint32_t wp_index = wp->second;
185 m_watchpoint_index_map.erase(wp);
186 if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
Zachary Turner97206d52017-05-12 04:51:55 +0000187 return Status();
188 return Status("Clearing hardware watchpoint failed.");
Chaoren Lin18fe6402015-02-03 01:51:47 +0000189}
190
Zachary Turner97206d52017-05-12 04:51:55 +0000191Status NativeThreadLinux::SetHardwareBreakpoint(lldb::addr_t addr,
192 size_t size) {
Omair Javaidd5ffbad2017-02-24 13:27:31 +0000193 if (m_state == eStateLaunching)
Zachary Turner97206d52017-05-12 04:51:55 +0000194 return Status();
Omair Javaidd5ffbad2017-02-24 13:27:31 +0000195
Zachary Turner97206d52017-05-12 04:51:55 +0000196 Status error = RemoveHardwareBreakpoint(addr);
Omair Javaidd5ffbad2017-02-24 13:27:31 +0000197 if (error.Fail())
198 return error;
199
200 NativeRegisterContextSP reg_ctx = GetRegisterContext();
201 uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size);
202
203 if (bp_index == LLDB_INVALID_INDEX32)
Zachary Turner97206d52017-05-12 04:51:55 +0000204 return Status("Setting hardware breakpoint failed.");
Omair Javaidd5ffbad2017-02-24 13:27:31 +0000205
206 m_hw_break_index_map.insert({addr, bp_index});
Zachary Turner97206d52017-05-12 04:51:55 +0000207 return Status();
Omair Javaidd5ffbad2017-02-24 13:27:31 +0000208}
209
Zachary Turner97206d52017-05-12 04:51:55 +0000210Status NativeThreadLinux::RemoveHardwareBreakpoint(lldb::addr_t addr) {
Omair Javaidd5ffbad2017-02-24 13:27:31 +0000211 auto bp = m_hw_break_index_map.find(addr);
212 if (bp == m_hw_break_index_map.end())
Zachary Turner97206d52017-05-12 04:51:55 +0000213 return Status();
Omair Javaidd5ffbad2017-02-24 13:27:31 +0000214
215 uint32_t bp_index = bp->second;
216 if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) {
217 m_hw_break_index_map.erase(bp);
Zachary Turner97206d52017-05-12 04:51:55 +0000218 return Status();
Omair Javaidd5ffbad2017-02-24 13:27:31 +0000219 }
220
Zachary Turner97206d52017-05-12 04:51:55 +0000221 return Status("Clearing hardware breakpoint failed.");
Omair Javaidd5ffbad2017-02-24 13:27:31 +0000222}
223
Zachary Turner97206d52017-05-12 04:51:55 +0000224Status NativeThreadLinux::Resume(uint32_t signo) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000225 const StateType new_state = StateType::eStateRunning;
226 MaybeLogStateChange(new_state);
227 m_state = new_state;
Tamas Berghammereadb2a92015-03-17 14:40:57 +0000228
Kate Stoneb9c1b512016-09-06 20:57:50 +0000229 m_stop_info.reason = StopReason::eStopReasonNone;
230 m_stop_description.clear();
Tamas Berghammereadb2a92015-03-17 14:40:57 +0000231
Kate Stoneb9c1b512016-09-06 20:57:50 +0000232 // If watchpoints have been set, but none on this thread,
233 // then this is a new thread. So set all existing watchpoints.
234 if (m_watchpoint_index_map.empty()) {
Pavel Labath605b51b2016-02-23 13:56:30 +0000235 NativeProcessLinux &process = GetProcess();
Pavel Labath8c8ff7a2015-05-11 10:03:10 +0000236
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237 const auto &watchpoint_map = process.GetWatchpointMap();
238 GetRegisterContext()->ClearAllHardwareWatchpoints();
239 for (const auto &pair : watchpoint_map) {
240 const auto &wp = pair.second;
241 SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware);
Pavel Labath8c8ff7a2015-05-11 10:03:10 +0000242 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000243 }
Pavel Labath8c8ff7a2015-05-11 10:03:10 +0000244
Omair Javaidd5ffbad2017-02-24 13:27:31 +0000245 // Set all active hardware breakpoint on all threads.
246 if (m_hw_break_index_map.empty()) {
247 NativeProcessLinux &process = GetProcess();
248
249 const auto &hw_breakpoint_map = process.GetHardwareBreakpointMap();
250 GetRegisterContext()->ClearAllHardwareBreakpoints();
251 for (const auto &pair : hw_breakpoint_map) {
252 const auto &bp = pair.second;
253 SetHardwareBreakpoint(bp.m_addr, bp.m_size);
254 }
255 }
256
Kate Stoneb9c1b512016-09-06 20:57:50 +0000257 intptr_t data = 0;
258
259 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
260 data = signo;
261
262 return NativeProcessLinux::PtraceWrapper(PTRACE_CONT, GetID(), nullptr,
263 reinterpret_cast<void *>(data));
Pavel Labath8c8ff7a2015-05-11 10:03:10 +0000264}
265
Zachary Turner97206d52017-05-12 04:51:55 +0000266Status NativeThreadLinux::SingleStep(uint32_t signo) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000267 const StateType new_state = StateType::eStateStepping;
268 MaybeLogStateChange(new_state);
269 m_state = new_state;
270 m_stop_info.reason = StopReason::eStopReasonNone;
Pavel Labatha37bbbd2017-02-17 11:48:34 +0000271
272 if(!m_step_workaround) {
273 // If we already hava a workaround inplace, don't reset it. Otherwise, the
274 // destructor of the existing instance will run after the new instance has
275 // fetched the cpu mask, and the thread will end up with the wrong mask.
276 m_step_workaround = SingleStepWorkaround::Get(m_tid);
277 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000278
279 intptr_t data = 0;
280 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
281 data = signo;
282
283 // If hardware single-stepping is not supported, we just do a continue. The
284 // breakpoint on the
285 // next instruction has been setup in NativeProcessLinux::Resume.
286 return NativeProcessLinux::PtraceWrapper(
287 GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP
288 : PTRACE_CONT,
289 m_tid, nullptr, reinterpret_cast<void *>(data));
290}
291
292void NativeThreadLinux::SetStoppedBySignal(uint32_t signo,
293 const siginfo_t *info) {
294 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
295 if (log)
296 log->Printf("NativeThreadLinux::%s called with signal 0x%02" PRIx32,
297 __FUNCTION__, signo);
298
299 SetStopped();
300
301 m_stop_info.reason = StopReason::eStopReasonSignal;
302 m_stop_info.details.signal.signo = signo;
303
304 m_stop_description.clear();
305 if (info) {
306 switch (signo) {
307 case SIGSEGV:
308 case SIGBUS:
309 case SIGFPE:
310 case SIGILL:
311 // In case of MIPS64 target, SI_KERNEL is generated for invalid 64bit
312 // address.
313 const auto reason =
314 (info->si_signo == SIGBUS && info->si_code == SI_KERNEL)
315 ? CrashReason::eInvalidAddress
316 : GetCrashReason(*info);
Valentina Giusti6f8c1f82016-10-06 18:05:12 +0000317 m_stop_description = GetCrashReasonString(reason, *info);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000318 break;
319 }
320 }
321}
322
323bool NativeThreadLinux::IsStopped(int *signo) {
324 if (!StateIsStoppedState(m_state, false))
325 return false;
326
327 // If we are stopped by a signal, return the signo.
328 if (signo && m_state == StateType::eStateStopped &&
329 m_stop_info.reason == StopReason::eStopReasonSignal) {
330 *signo = m_stop_info.details.signal.signo;
331 }
332
333 // Regardless, we are stopped.
334 return true;
335}
336
337void NativeThreadLinux::SetStopped() {
338 if (m_state == StateType::eStateStepping)
Pavel Labath8abd34f2017-01-25 11:19:45 +0000339 m_step_workaround.reset();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000340
341 const StateType new_state = StateType::eStateStopped;
342 MaybeLogStateChange(new_state);
343 m_state = new_state;
344 m_stop_description.clear();
345}
346
347void NativeThreadLinux::SetStoppedByExec() {
348 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
349 if (log)
350 log->Printf("NativeThreadLinux::%s()", __FUNCTION__);
351
352 SetStopped();
353
354 m_stop_info.reason = StopReason::eStopReasonExec;
355 m_stop_info.details.signal.signo = SIGSTOP;
356}
357
358void NativeThreadLinux::SetStoppedByBreakpoint() {
359 SetStopped();
360
361 m_stop_info.reason = StopReason::eStopReasonBreakpoint;
362 m_stop_info.details.signal.signo = SIGTRAP;
363 m_stop_description.clear();
364}
365
366void NativeThreadLinux::SetStoppedByWatchpoint(uint32_t wp_index) {
367 SetStopped();
368
369 lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");
370
371 std::ostringstream ostr;
372 ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
373 ostr << wp_index;
374
375 /*
376 * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For
377 * example:
378 * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at
379 * 'm', then
380 * watch exception is generated even when 'n' is read/written. To handle this
381 * case,
382 * find the base address of the load/store instruction and append it in the
383 * stop-info
384 * packet.
385 */
386 ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index);
387
388 m_stop_description = ostr.str();
389
390 m_stop_info.reason = StopReason::eStopReasonWatchpoint;
391 m_stop_info.details.signal.signo = SIGTRAP;
392}
393
394bool NativeThreadLinux::IsStoppedAtBreakpoint() {
395 return GetState() == StateType::eStateStopped &&
396 m_stop_info.reason == StopReason::eStopReasonBreakpoint;
397}
398
399bool NativeThreadLinux::IsStoppedAtWatchpoint() {
400 return GetState() == StateType::eStateStopped &&
401 m_stop_info.reason == StopReason::eStopReasonWatchpoint;
402}
403
404void NativeThreadLinux::SetStoppedByTrace() {
405 SetStopped();
406
407 m_stop_info.reason = StopReason::eStopReasonTrace;
408 m_stop_info.details.signal.signo = SIGTRAP;
409}
410
411void NativeThreadLinux::SetStoppedWithNoReason() {
412 SetStopped();
413
414 m_stop_info.reason = StopReason::eStopReasonNone;
415 m_stop_info.details.signal.signo = 0;
416}
417
418void NativeThreadLinux::SetExited() {
419 const StateType new_state = StateType::eStateExited;
420 MaybeLogStateChange(new_state);
421 m_state = new_state;
422
423 m_stop_info.reason = StopReason::eStopReasonThreadExiting;
424}
425
Zachary Turner97206d52017-05-12 04:51:55 +0000426Status NativeThreadLinux::RequestStop() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000427 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
428
429 NativeProcessLinux &process = GetProcess();
430
431 lldb::pid_t pid = process.GetID();
432 lldb::tid_t tid = GetID();
433
434 if (log)
435 log->Printf("NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64
436 ", tid: %" PRIu64 ")",
437 __FUNCTION__, pid, tid);
438
Zachary Turner97206d52017-05-12 04:51:55 +0000439 Status err;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000440 errno = 0;
441 if (::tgkill(pid, tid, SIGSTOP) != 0) {
442 err.SetErrorToErrno();
443 if (log)
444 log->Printf("NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64
445 ", SIGSTOP) failed: %s",
446 __FUNCTION__, pid, tid, err.AsCString());
447 }
448
449 return err;
450}
451
452void NativeThreadLinux::MaybeLogStateChange(lldb::StateType new_state) {
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 =
465 m_process_sp ? m_process_sp->GetID() : LLDB_INVALID_PROCESS_ID;
466
467 // Log it.
468 log->Printf("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64
469 ") changing from state %s to %s",
470 pid, GetID(), StateAsCString(old_state),
471 StateAsCString(new_state));
472}
473
474NativeProcessLinux &NativeThreadLinux::GetProcess() {
475 auto process_sp = std::static_pointer_cast<NativeProcessLinux>(
476 NativeThreadProtocol::GetProcess());
477 assert(process_sp);
478 return *process_sp;
Pavel Labath605b51b2016-02-23 13:56:30 +0000479}