blob: 2171a6dbb2fd5b2b6019f081b062d933a06f862a [file] [log] [blame]
Stephen Wilsonf6f40332010-07-24 02:19:04 +00001//===-- ProcessLinux.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// C Includes
Stephen Wilsond1fbbb42011-03-23 02:14:42 +000011#include <errno.h>
12
Stephen Wilsonf6f40332010-07-24 02:19:04 +000013// C++ Includes
14// Other libraries and framework includes
15#include "lldb/Core/PluginManager.h"
Peter Collingbournead115462011-06-03 20:40:44 +000016#include "lldb/Core/State.h"
Stephen Wilsonf6f40332010-07-24 02:19:04 +000017#include "lldb/Host/Host.h"
18#include "lldb/Symbol/ObjectFile.h"
Stephen Wilson92241ef2011-01-16 19:45:39 +000019#include "lldb/Target/DynamicLoader.h"
Stephen Wilsonf6f40332010-07-24 02:19:04 +000020#include "lldb/Target/Target.h"
21
22#include "ProcessLinux.h"
Johnny Chenac51e9f2011-10-11 21:21:57 +000023#include "ProcessLinuxLog.h"
Peter Collingbournead115462011-06-03 20:40:44 +000024#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
Stephen Wilsonf6f40332010-07-24 02:19:04 +000025#include "ProcessMonitor.h"
26#include "LinuxThread.h"
27
28using namespace lldb;
29using namespace lldb_private;
30
31//------------------------------------------------------------------------------
32// Static functions.
33
34Process*
35ProcessLinux::CreateInstance(Target& target, Listener &listener)
36{
37 return new ProcessLinux(target, listener);
38}
39
40void
41ProcessLinux::Initialize()
42{
43 static bool g_initialized = false;
44
45 if (!g_initialized)
46 {
Johnny Chenac51e9f2011-10-11 21:21:57 +000047 g_initialized = true;
Stephen Wilsonf6f40332010-07-24 02:19:04 +000048 PluginManager::RegisterPlugin(GetPluginNameStatic(),
49 GetPluginDescriptionStatic(),
50 CreateInstance);
Johnny Chenac51e9f2011-10-11 21:21:57 +000051
52 Log::Callbacks log_callbacks = {
53 ProcessLinuxLog::DisableLog,
54 ProcessLinuxLog::EnableLog,
55 ProcessLinuxLog::ListLogCategories
56 };
57
58 Log::RegisterLogChannel (ProcessLinux::GetPluginNameStatic(), log_callbacks);
Stephen Wilsonf6f40332010-07-24 02:19:04 +000059 }
60}
61
62void
63ProcessLinux::Terminate()
64{
65}
66
67const char *
68ProcessLinux::GetPluginNameStatic()
69{
70 return "plugin.process.linux";
71}
72
73const char *
74ProcessLinux::GetPluginDescriptionStatic()
75{
76 return "Process plugin for Linux";
77}
78
79
80//------------------------------------------------------------------------------
81// Constructors and destructors.
82
83ProcessLinux::ProcessLinux(Target& target, Listener &listener)
84 : Process(target, listener),
85 m_monitor(NULL),
Stephen Wilson67d9f7e2011-03-30 15:55:52 +000086 m_module(NULL),
87 m_in_limbo(false),
88 m_exit_now(false)
Stephen Wilsonf6f40332010-07-24 02:19:04 +000089{
Greg Claytonce65d2f2011-11-05 01:09:16 +000090#if 0
Stephen Wilsonf6f40332010-07-24 02:19:04 +000091 // FIXME: Putting this code in the ctor and saving the byte order in a
92 // member variable is a hack to avoid const qual issues in GetByteOrder.
93 ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();
94 m_byte_order = obj_file->GetByteOrder();
Greg Claytonce65d2f2011-11-05 01:09:16 +000095#else
96 // XXX: Will work only for local processes.
97 m_byte_order = lldb::endian::InlHostByteOrder();
98#endif
Stephen Wilsonf6f40332010-07-24 02:19:04 +000099}
100
101ProcessLinux::~ProcessLinux()
102{
103 delete m_monitor;
104}
105
106//------------------------------------------------------------------------------
107// Process protocol.
108
109bool
Peter Collingbourne47556982011-07-22 19:12:53 +0000110ProcessLinux::CanDebug(Target &target, bool plugin_specified_by_name)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000111{
112 // For now we are just making sure the file exists for a given module
113 ModuleSP exe_module_sp(target.GetExecutableModule());
114 if (exe_module_sp.get())
115 return exe_module_sp->GetFileSpec().Exists();
116 return false;
117}
118
119Error
120ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid)
121{
Johnny Chen9bab8d42011-06-14 19:19:50 +0000122 Error error;
123 assert(m_monitor == NULL);
124
Johnny Chenac51e9f2011-10-11 21:21:57 +0000125 LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS));
126 if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
Johnny Chen3bf3a9d2011-10-18 18:09:30 +0000127 log->Printf ("ProcessLinux::%s(pid = %i)", __FUNCTION__, GetID());
Johnny Chenac51e9f2011-10-11 21:21:57 +0000128
Johnny Chen9bab8d42011-06-14 19:19:50 +0000129 m_monitor = new ProcessMonitor(this, pid, error);
130
131 if (!error.Success())
132 return error;
133
134 SetID(pid);
135 return error;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000136}
137
138Error
Stephen Wilson92241ef2011-01-16 19:45:39 +0000139ProcessLinux::WillLaunch(Module* module)
140{
141 Error error;
Stephen Wilson92241ef2011-01-16 19:45:39 +0000142 return error;
143}
144
145Error
Greg Claytonce65d2f2011-11-05 01:09:16 +0000146ProcessLinux::DoLaunch (Module *module,
147 const ProcessLaunchInfo &launch_info)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000148{
149 Error error;
150 assert(m_monitor == NULL);
151
152 SetPrivateState(eStateLaunching);
Greg Claytonce65d2f2011-11-05 01:09:16 +0000153
Greg Claytonce65d2f2011-11-05 01:09:16 +0000154 const char *stdin_path = NULL;
155 const char *stdout_path = NULL;
156 const char *stderr_path = NULL;
157 const char *working_dir = launch_info.GetWorkingDirectory();
158
159 const ProcessLaunchInfo::FileAction *file_action;
160 file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
161 if (file_action)
162 {
163 if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
164 stdin_path = file_action->GetPath();
165 }
166 file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
167 if (file_action)
168 {
169 if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
170 stdout_path = file_action->GetPath();
171 }
172 file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
173 if (file_action)
174 {
175 if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
176 stderr_path = file_action->GetPath();
177 }
178
179 m_monitor = new ProcessMonitor (this,
180 module,
181 launch_info.GetArguments().GetConstArgumentVector(),
182 launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
183 stdin_path,
184 stdout_path,
185 stderr_path,
186 error);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000187
188 m_module = module;
189
190 if (!error.Success())
191 return error;
192
Stephen Wilson1f004c62011-01-15 00:13:27 +0000193 SetID(m_monitor->GetPID());
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000194 return error;
195}
196
Stephen Wilson92241ef2011-01-16 19:45:39 +0000197void
198ProcessLinux::DidLaunch()
199{
Stephen Wilson92241ef2011-01-16 19:45:39 +0000200}
201
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000202Error
203ProcessLinux::DoResume()
204{
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000205 StateType state = GetPrivateState();
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000206
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000207 assert(state == eStateStopped || state == eStateCrashed);
208
209 // We are about to resume a thread that will cause the process to exit so
210 // set our exit status now. Do not change our state if the inferior
211 // crashed.
212 if (state == eStateStopped)
213 {
214 if (m_in_limbo)
215 SetExitStatus(m_exit_status, NULL);
216 else
217 SetPrivateState(eStateRunning);
218 }
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000219
220 bool did_resume = false;
221 uint32_t thread_count = m_thread_list.GetSize(false);
222 for (uint32_t i = 0; i < thread_count; ++i)
223 {
224 LinuxThread *thread = static_cast<LinuxThread*>(
225 m_thread_list.GetThreadAtIndex(i, false).get());
226 did_resume = thread->Resume() || did_resume;
227 }
228 assert(did_resume && "Process resume failed!");
229
230 return Error();
231}
232
Stephen Wilson01316422011-01-15 00:10:37 +0000233addr_t
234ProcessLinux::GetImageInfoAddress()
235{
236 Target *target = &GetTarget();
237 ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
238 Address addr = obj_file->GetImageInfoAddress();
239
240 if (addr.IsValid())
241 return addr.GetLoadAddress(target);
242 else
243 return LLDB_INVALID_ADDRESS;
244}
245
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000246Error
Stephen Wilson3a804312011-01-04 21:41:31 +0000247ProcessLinux::DoHalt(bool &caused_stop)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000248{
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000249 Error error;
250
251 if (IsStopped())
252 {
253 caused_stop = false;
254 }
255 else if (kill(GetID(), SIGSTOP))
256 {
257 caused_stop = false;
258 error.SetErrorToErrno();
259 }
260 else
261 {
262 caused_stop = true;
263 }
264
265 return error;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000266}
267
268Error
269ProcessLinux::DoDetach()
270{
Greg Clayton48a202d2011-11-29 20:50:10 +0000271 Error error;
272
273 error = m_monitor->Detach();
274 if (error.Success())
275 SetPrivateState(eStateDetached);
276
277 return error;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000278}
279
280Error
281ProcessLinux::DoSignal(int signal)
282{
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000283 Error error;
284
285 if (kill(GetID(), signal))
286 error.SetErrorToErrno();
287
288 return error;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000289}
290
291Error
292ProcessLinux::DoDestroy()
293{
294 Error error;
295
296 if (!HasExited())
297 {
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000298 // Drive the exit event to completion (do not keep the inferior in
299 // limbo).
300 m_exit_now = true;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000301
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000302 if (kill(m_monitor->GetPID(), SIGKILL) && error.Success())
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000303 {
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000304 error.SetErrorToErrno();
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000305 return error;
306 }
307
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000308 SetPrivateState(eStateExited);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000309 }
310
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000311 return error;
312}
313
314void
315ProcessLinux::SendMessage(const ProcessMessage &message)
316{
317 Mutex::Locker lock(m_message_mutex);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000318
319 switch (message.GetKind())
320 {
321 default:
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000322 assert(false && "Unexpected process message!");
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000323 break;
324
Stephen Wilson07fc7a92011-01-19 01:29:39 +0000325 case ProcessMessage::eInvalidMessage:
326 return;
327
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000328 case ProcessMessage::eLimboMessage:
329 m_in_limbo = true;
330 m_exit_status = message.GetExitStatus();
331 if (m_exit_now)
332 {
333 SetPrivateState(eStateExited);
334 m_monitor->Detach();
335 }
336 else
337 SetPrivateState(eStateStopped);
338 break;
339
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000340 case ProcessMessage::eExitMessage:
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000341 m_exit_status = message.GetExitStatus();
342 SetExitStatus(m_exit_status, NULL);
343 break;
344
345 case ProcessMessage::eTraceMessage:
346 case ProcessMessage::eBreakpointMessage:
347 SetPrivateState(eStateStopped);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000348 break;
349
350 case ProcessMessage::eSignalMessage:
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000351 case ProcessMessage::eSignalDeliveredMessage:
352 SetPrivateState(eStateStopped);
353 break;
354
355 case ProcessMessage::eCrashMessage:
356 SetPrivateState(eStateCrashed);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000357 break;
358 }
Stephen Wilson07fc7a92011-01-19 01:29:39 +0000359
360 m_message_queue.push(message);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000361}
362
363void
364ProcessLinux::RefreshStateAfterStop()
365{
Johnny Chen3bf3a9d2011-10-18 18:09:30 +0000366 LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS));
367 if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
368 log->Printf ("ProcessLinux::%s()", __FUNCTION__);
369
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000370 Mutex::Locker lock(m_message_mutex);
371 if (m_message_queue.empty())
372 return;
373
374 ProcessMessage &message = m_message_queue.front();
375
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000376 // Resolve the thread this message corresponds to and pass it along.
Johnny Chen3bf3a9d2011-10-18 18:09:30 +0000377 // FIXME: we're really dealing with the pid here. This should get
378 // fixed when this code is fixed to handle multiple threads.
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000379 lldb::tid_t tid = message.GetTID();
Johnny Chen3bf3a9d2011-10-18 18:09:30 +0000380 if (log)
381 log->Printf ("ProcessLinux::%s() pid = %i", __FUNCTION__, tid);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000382 LinuxThread *thread = static_cast<LinuxThread*>(
383 GetThreadList().FindThreadByID(tid, false).get());
384
Johnny Chen3bf3a9d2011-10-18 18:09:30 +0000385 assert(thread);
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000386 thread->Notify(message);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000387
388 m_message_queue.pop();
389}
390
391bool
392ProcessLinux::IsAlive()
393{
394 StateType state = GetPrivateState();
Greg Clayton48a202d2011-11-29 20:50:10 +0000395 return state != eStateDetached && state != eStateExited && state != eStateInvalid;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000396}
397
398size_t
399ProcessLinux::DoReadMemory(addr_t vm_addr,
400 void *buf, size_t size, Error &error)
401{
Johnny Chen3bf3a9d2011-10-18 18:09:30 +0000402 assert(m_monitor);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000403 return m_monitor->ReadMemory(vm_addr, buf, size, error);
404}
405
406size_t
407ProcessLinux::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
408 Error &error)
409{
Johnny Chen3bf3a9d2011-10-18 18:09:30 +0000410 assert(m_monitor);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000411 return m_monitor->WriteMemory(vm_addr, buf, size, error);
412}
413
414addr_t
415ProcessLinux::DoAllocateMemory(size_t size, uint32_t permissions,
416 Error &error)
417{
Peter Collingbournead115462011-06-03 20:40:44 +0000418 addr_t allocated_addr = LLDB_INVALID_ADDRESS;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000419
Peter Collingbournead115462011-06-03 20:40:44 +0000420 unsigned prot = 0;
421 if (permissions & lldb::ePermissionsReadable)
422 prot |= eMmapProtRead;
423 if (permissions & lldb::ePermissionsWritable)
424 prot |= eMmapProtWrite;
425 if (permissions & lldb::ePermissionsExecutable)
426 prot |= eMmapProtExec;
427
428 if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
429 eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
430 m_addr_to_mmap_size[allocated_addr] = size;
431 error.Clear();
432 } else {
433 allocated_addr = LLDB_INVALID_ADDRESS;
434 error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
435 }
436
437 return allocated_addr;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000438}
439
440Error
Peter Collingbournead115462011-06-03 20:40:44 +0000441ProcessLinux::DoDeallocateMemory(lldb::addr_t addr)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000442{
Peter Collingbournead115462011-06-03 20:40:44 +0000443 Error error;
444 MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
445 if (pos != m_addr_to_mmap_size.end() &&
446 InferiorCallMunmap(this, addr, pos->second))
447 m_addr_to_mmap_size.erase (pos);
448 else
449 error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr);
450
451 return error;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000452}
453
454size_t
455ProcessLinux::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
456{
457 static const uint8_t g_i386_opcode[] = { 0xCC };
458
459 ArchSpec arch = GetTarget().GetArchitecture();
460 const uint8_t *opcode = NULL;
461 size_t opcode_size = 0;
462
Stephen Wilsona1f0b722011-02-24 19:17:09 +0000463 switch (arch.GetCore())
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000464 {
465 default:
466 assert(false && "CPU type not supported!");
467 break;
468
Stephen Wilsona1f0b722011-02-24 19:17:09 +0000469 case ArchSpec::eCore_x86_32_i386:
470 case ArchSpec::eCore_x86_64_x86_64:
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000471 opcode = g_i386_opcode;
472 opcode_size = sizeof(g_i386_opcode);
473 break;
474 }
475
476 bp_site->SetTrapOpcode(opcode, opcode_size);
477 return opcode_size;
478}
479
480Error
481ProcessLinux::EnableBreakpoint(BreakpointSite *bp_site)
482{
483 return EnableSoftwareBreakpoint(bp_site);
484}
485
486Error
487ProcessLinux::DisableBreakpoint(BreakpointSite *bp_site)
488{
489 return DisableSoftwareBreakpoint(bp_site);
490}
491
492uint32_t
493ProcessLinux::UpdateThreadListIfNeeded()
494{
495 // Do not allow recursive updates.
496 return m_thread_list.GetSize(false);
497}
498
Johnny Chenb8f74aa2011-10-10 23:11:50 +0000499uint32_t
500ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
501{
Johnny Chenac51e9f2011-10-11 21:21:57 +0000502 LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
503 if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
Johnny Chen3bf3a9d2011-10-18 18:09:30 +0000504 log->Printf ("ProcessLinux::%s() (pid = %i)", __FUNCTION__, GetID());
Johnny Chenac51e9f2011-10-11 21:21:57 +0000505
Johnny Chen3bf3a9d2011-10-18 18:09:30 +0000506 // Update the process thread list with this new thread.
507 // FIXME: We should be using tid, not pid.
508 assert(m_monitor);
509 ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
510 if (!thread_sp)
511 thread_sp.reset(new LinuxThread(*this, GetID()));
512
513 if (log && log->GetMask().Test(LINUX_LOG_VERBOSE))
514 log->Printf ("ProcessLinux::%s() updated pid = %i", __FUNCTION__, GetID());
515 new_thread_list.AddThread(thread_sp);
516
517 return new_thread_list.GetSize(false);
Johnny Chenb8f74aa2011-10-10 23:11:50 +0000518}
519
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000520ByteOrder
521ProcessLinux::GetByteOrder() const
522{
523 // FIXME: We should be able to extract this value directly. See comment in
524 // ProcessLinux().
525 return m_byte_order;
526}
527
Stephen Wilsond1fbbb42011-03-23 02:14:42 +0000528size_t
529ProcessLinux::PutSTDIN(const char *buf, size_t len, Error &error)
530{
531 ssize_t status;
532 if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)
533 {
534 error.SetErrorToErrno();
535 return 0;
536 }
537 return status;
538}
539
540size_t
541ProcessLinux::GetSTDOUT(char *buf, size_t len, Error &error)
542{
543 ssize_t bytes_read;
544
545 // The terminal file descriptor is always in non-block mode.
546 if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0)
547 {
548 if (errno != EAGAIN)
549 error.SetErrorToErrno();
550 return 0;
551 }
552 return bytes_read;
553}
554
555size_t
556ProcessLinux::GetSTDERR(char *buf, size_t len, Error &error)
557{
558 return GetSTDOUT(buf, len, error);
559}
560
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000561UnixSignals &
562ProcessLinux::GetUnixSignals()
563{
564 return m_linux_signals;
565}
Stephen Wilsond1fbbb42011-03-23 02:14:42 +0000566
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000567//------------------------------------------------------------------------------
568// ProcessInterface protocol.
569
570const char *
571ProcessLinux::GetPluginName()
572{
573 return "process.linux";
574}
575
576const char *
577ProcessLinux::GetShortPluginName()
578{
579 return "process.linux";
580}
581
582uint32_t
583ProcessLinux::GetPluginVersion()
584{
585 return 1;
586}
587
588void
589ProcessLinux::GetPluginCommandHelp(const char *command, Stream *strm)
590{
591}
592
593Error
594ProcessLinux::ExecutePluginCommand(Args &command, Stream *strm)
595{
596 return Error(1, eErrorTypeGeneric);
597}
598
599Log *
600ProcessLinux::EnablePluginLogging(Stream *strm, Args &command)
601{
602 return NULL;
603}
604
605//------------------------------------------------------------------------------
606// Utility functions.
607
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000608bool
609ProcessLinux::HasExited()
610{
611 switch (GetPrivateState())
612 {
613 default:
614 break;
615
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000616 case eStateDetached:
617 case eStateExited:
618 return true;
619 }
620
621 return false;
622}
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000623
624bool
625ProcessLinux::IsStopped()
626{
627 switch (GetPrivateState())
628 {
629 default:
630 break;
631
632 case eStateStopped:
633 case eStateCrashed:
634 case eStateSuspended:
635 return true;
636 }
637
638 return false;
639}