ProcessPOSIX.cpp revision 263368
1//===-- ProcessPOSIX.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 "lldb/lldb-python.h"
11
12// C Includes
13#include <errno.h>
14
15// C++ Includes
16// Other libraries and framework includes
17#include "lldb/Breakpoint/Watchpoint.h"
18#include "lldb/Core/Module.h"
19#include "lldb/Core/PluginManager.h"
20#include "lldb/Core/State.h"
21#include "lldb/Host/FileSpec.h"
22#include "lldb/Host/Host.h"
23#include "lldb/Symbol/ObjectFile.h"
24#include "lldb/Target/DynamicLoader.h"
25#include "lldb/Target/Platform.h"
26#include "lldb/Target/Target.h"
27
28#include "ProcessPOSIX.h"
29#include "ProcessPOSIXLog.h"
30#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
31#include "ProcessMonitor.h"
32#include "POSIXThread.h"
33
34using namespace lldb;
35using namespace lldb_private;
36
37//------------------------------------------------------------------------------
38// Static functions.
39#if 0
40Process*
41ProcessPOSIX::CreateInstance(Target& target, Listener &listener)
42{
43    return new ProcessPOSIX(target, listener);
44}
45
46
47void
48ProcessPOSIX::Initialize()
49{
50    static bool g_initialized = false;
51
52    if (!g_initialized)
53    {
54        g_initialized = true;
55        PluginManager::RegisterPlugin(GetPluginNameStatic(),
56                                      GetPluginDescriptionStatic(),
57                                      CreateInstance);
58
59        Log::Callbacks log_callbacks = {
60            ProcessPOSIXLog::DisableLog,
61            ProcessPOSIXLog::EnableLog,
62            ProcessPOSIXLog::ListLogCategories
63        };
64
65        Log::RegisterLogChannel (ProcessPOSIX::GetPluginNameStatic(), log_callbacks);
66    }
67}
68#endif
69
70//------------------------------------------------------------------------------
71// Constructors and destructors.
72
73ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener)
74    : Process(target, listener),
75      m_byte_order(lldb::endian::InlHostByteOrder()),
76      m_monitor(NULL),
77      m_module(NULL),
78      m_message_mutex (Mutex::eMutexTypeRecursive),
79      m_exit_now(false),
80      m_seen_initial_stop()
81{
82    // FIXME: Putting this code in the ctor and saving the byte order in a
83    // member variable is a hack to avoid const qual issues in GetByteOrder.
84	lldb::ModuleSP module = GetTarget().GetExecutableModule();
85	if (module && module->GetObjectFile())
86		m_byte_order = module->GetObjectFile()->GetByteOrder();
87}
88
89ProcessPOSIX::~ProcessPOSIX()
90{
91    delete m_monitor;
92}
93
94//------------------------------------------------------------------------------
95// Process protocol.
96void
97ProcessPOSIX::Finalize()
98{
99  Process::Finalize();
100
101  if (m_monitor)
102    m_monitor->StopMonitor();
103}
104
105bool
106ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name)
107{
108    // For now we are just making sure the file exists for a given module
109    ModuleSP exe_module_sp(target.GetExecutableModule());
110    if (exe_module_sp.get())
111        return exe_module_sp->GetFileSpec().Exists();
112    // If there is no executable module, we return true since we might be preparing to attach.
113    return true;
114}
115
116Error
117ProcessPOSIX::DoAttachToProcessWithID(lldb::pid_t pid)
118{
119    Error error;
120    assert(m_monitor == NULL);
121
122    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
123    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
124        log->Printf ("ProcessPOSIX::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID());
125
126    m_monitor = new ProcessMonitor(this, pid, error);
127
128    if (!error.Success())
129        return error;
130
131    PlatformSP platform_sp (m_target.GetPlatform ());
132    assert (platform_sp.get());
133    if (!platform_sp)
134        return error;  // FIXME: Detatch?
135
136    // Find out what we can about this process
137    ProcessInstanceInfo process_info;
138    platform_sp->GetProcessInfo (pid, process_info);
139
140    // Resolve the executable module
141    ModuleSP exe_module_sp;
142    FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
143    error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(),
144                                           m_target.GetArchitecture(),
145                                           exe_module_sp,
146                                           executable_search_paths.GetSize() ? &executable_search_paths : NULL);
147    if (!error.Success())
148        return error;
149
150    // Fix the target architecture if necessary
151    const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
152    if (module_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(module_arch))
153        m_target.SetArchitecture(module_arch);
154
155    // Initialize the target module list
156    m_target.SetExecutableModule (exe_module_sp, true);
157
158    SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
159
160    SetID(pid);
161
162    return error;
163}
164
165Error
166ProcessPOSIX::DoAttachToProcessWithID (lldb::pid_t pid,  const ProcessAttachInfo &attach_info)
167{
168    return DoAttachToProcessWithID(pid);
169}
170
171Error
172ProcessPOSIX::WillLaunch(Module* module)
173{
174    Error error;
175    return error;
176}
177
178const char *
179ProcessPOSIX::GetFilePath(
180    const lldb_private::ProcessLaunchInfo::FileAction *file_action,
181    const char *default_path)
182{
183    const char *pts_name = "/dev/pts/";
184    const char *path = NULL;
185
186    if (file_action)
187    {
188        if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
189            path = file_action->GetPath();
190            // By default the stdio paths passed in will be pseudo-terminal
191            // (/dev/pts). If so, convert to using a different default path
192            // instead to redirect I/O to the debugger console. This should
193            //  also handle user overrides to /dev/null or a different file.
194            if (::strncmp(path, pts_name, ::strlen(pts_name)) == 0)
195                path = default_path;
196    }
197
198    return path;
199}
200
201Error
202ProcessPOSIX::DoLaunch (Module *module,
203                       const ProcessLaunchInfo &launch_info)
204{
205    Error error;
206    assert(m_monitor == NULL);
207
208    const char* working_dir = launch_info.GetWorkingDirectory();
209    if (working_dir) {
210      FileSpec WorkingDir(working_dir, true);
211      if (!WorkingDir || WorkingDir.GetFileType() != FileSpec::eFileTypeDirectory)
212      {
213          error.SetErrorStringWithFormat("No such file or directory: %s", working_dir);
214          return error;
215      }
216    }
217
218    SetPrivateState(eStateLaunching);
219
220    const lldb_private::ProcessLaunchInfo::FileAction *file_action;
221
222    // Default of NULL will mean to use existing open file descriptors
223    const char *stdin_path = NULL;
224    const char *stdout_path = NULL;
225    const char *stderr_path = NULL;
226
227    file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
228    stdin_path = GetFilePath(file_action, stdin_path);
229
230    file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
231    stdout_path = GetFilePath(file_action, stdout_path);
232
233    file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
234    stderr_path = GetFilePath(file_action, stderr_path);
235
236    m_monitor = new ProcessMonitor (this,
237                                    module,
238                                    launch_info.GetArguments().GetConstArgumentVector(),
239                                    launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
240                                    stdin_path,
241                                    stdout_path,
242                                    stderr_path,
243                                    working_dir,
244                                    error);
245
246    m_module = module;
247
248    if (!error.Success())
249        return error;
250
251    SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
252
253    SetID(m_monitor->GetPID());
254    return error;
255}
256
257void
258ProcessPOSIX::DidLaunch()
259{
260}
261
262addr_t
263ProcessPOSIX::GetImageInfoAddress()
264{
265    Target *target = &GetTarget();
266    ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
267    Address addr = obj_file->GetImageInfoAddress(target);
268
269    if (addr.IsValid())
270        return addr.GetLoadAddress(target);
271    return LLDB_INVALID_ADDRESS;
272}
273
274Error
275ProcessPOSIX::DoHalt(bool &caused_stop)
276{
277    Error error;
278
279    if (IsStopped())
280    {
281        caused_stop = false;
282    }
283    else if (kill(GetID(), SIGSTOP))
284    {
285        caused_stop = false;
286        error.SetErrorToErrno();
287    }
288    else
289    {
290        caused_stop = true;
291    }
292    return error;
293}
294
295Error
296ProcessPOSIX::DoSignal(int signal)
297{
298    Error error;
299
300    if (kill(GetID(), signal))
301        error.SetErrorToErrno();
302
303    return error;
304}
305
306Error
307ProcessPOSIX::DoDestroy()
308{
309    Error error;
310
311    if (!HasExited())
312    {
313        // Drive the exit event to completion (do not keep the inferior in
314        // limbo).
315        m_exit_now = true;
316
317        if ((m_monitor == NULL || kill(m_monitor->GetPID(), SIGKILL)) && error.Success())
318        {
319            error.SetErrorToErrno();
320            return error;
321        }
322
323        SetPrivateState(eStateExited);
324    }
325
326    return error;
327}
328
329void
330ProcessPOSIX::DoDidExec()
331{
332    Target *target = &GetTarget();
333    if (target)
334    {
335        PlatformSP platform_sp (target->GetPlatform());
336        assert (platform_sp.get());
337        if (platform_sp)
338        {
339            ProcessInstanceInfo process_info;
340            platform_sp->GetProcessInfo(GetID(), process_info);
341            ModuleSP exe_module_sp;
342            FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
343            Error error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(),
344                                                   target->GetArchitecture(),
345                                                   exe_module_sp,
346                                                   executable_search_paths.GetSize() ? &executable_search_paths : NULL);
347            if (!error.Success())
348                return;
349            target->SetExecutableModule(exe_module_sp, true);
350        }
351    }
352}
353
354void
355ProcessPOSIX::StopAllThreads(lldb::tid_t stop_tid)
356{
357    // FIXME: Will this work the same way on FreeBSD and Linux?
358}
359
360bool
361ProcessPOSIX::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid)
362{
363    bool added_to_set = false;
364    ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid);
365    if (it == m_seen_initial_stop.end())
366    {
367        m_seen_initial_stop.insert(stop_tid);
368        added_to_set = true;
369    }
370    return added_to_set;
371}
372
373bool
374ProcessPOSIX::WaitingForInitialStop(lldb::tid_t stop_tid)
375{
376    return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
377}
378
379POSIXThread *
380ProcessPOSIX::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid)
381{
382    return new POSIXThread(process, tid);
383}
384
385void
386ProcessPOSIX::RefreshStateAfterStop()
387{
388    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
389    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
390        log->Printf ("ProcessPOSIX::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());
391
392    Mutex::Locker lock(m_message_mutex);
393
394    // This method used to only handle one message.  Changing it to loop allows
395    // it to handle the case where we hit a breakpoint while handling a different
396    // breakpoint.
397    while (!m_message_queue.empty())
398    {
399        ProcessMessage &message = m_message_queue.front();
400
401        // Resolve the thread this message corresponds to and pass it along.
402        lldb::tid_t tid = message.GetTID();
403        if (log)
404            log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
405
406        if (message.GetKind() == ProcessMessage::eNewThreadMessage)
407        {
408            if (log)
409                log->Printf ("ProcessPOSIX::%s() adding thread, tid = %" PRIi64, __FUNCTION__, message.GetChildTID());
410            lldb::tid_t child_tid = message.GetChildTID();
411            ThreadSP thread_sp;
412            thread_sp.reset(CreateNewPOSIXThread(*this, child_tid));
413
414            Mutex::Locker lock(m_thread_list.GetMutex());
415
416            m_thread_list.AddThread(thread_sp);
417        }
418
419        m_thread_list.RefreshStateAfterStop();
420
421        POSIXThread *thread = static_cast<POSIXThread*>(
422            GetThreadList().FindThreadByID(tid, false).get());
423        if (thread)
424            thread->Notify(message);
425
426        if (message.GetKind() == ProcessMessage::eExitMessage)
427        {
428            // FIXME: We should tell the user about this, but the limbo message is probably better for that.
429            if (log)
430                log->Printf ("ProcessPOSIX::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);
431
432            Mutex::Locker lock(m_thread_list.GetMutex());
433
434            ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
435            thread_sp.reset();
436            m_seen_initial_stop.erase(tid);
437        }
438
439        m_message_queue.pop();
440    }
441}
442
443bool
444ProcessPOSIX::IsAlive()
445{
446    StateType state = GetPrivateState();
447    return state != eStateDetached
448        && state != eStateExited
449        && state != eStateInvalid
450        && state != eStateUnloaded;
451}
452
453size_t
454ProcessPOSIX::DoReadMemory(addr_t vm_addr,
455                           void *buf, size_t size, Error &error)
456{
457    assert(m_monitor);
458    return m_monitor->ReadMemory(vm_addr, buf, size, error);
459}
460
461size_t
462ProcessPOSIX::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
463                            Error &error)
464{
465    assert(m_monitor);
466    return m_monitor->WriteMemory(vm_addr, buf, size, error);
467}
468
469addr_t
470ProcessPOSIX::DoAllocateMemory(size_t size, uint32_t permissions,
471                               Error &error)
472{
473    addr_t allocated_addr = LLDB_INVALID_ADDRESS;
474
475    unsigned prot = 0;
476    if (permissions & lldb::ePermissionsReadable)
477        prot |= eMmapProtRead;
478    if (permissions & lldb::ePermissionsWritable)
479        prot |= eMmapProtWrite;
480    if (permissions & lldb::ePermissionsExecutable)
481        prot |= eMmapProtExec;
482
483    if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
484                         eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
485        m_addr_to_mmap_size[allocated_addr] = size;
486        error.Clear();
487    } else {
488        allocated_addr = LLDB_INVALID_ADDRESS;
489        error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
490    }
491
492    return allocated_addr;
493}
494
495Error
496ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr)
497{
498    Error error;
499    MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
500    if (pos != m_addr_to_mmap_size.end() &&
501        InferiorCallMunmap(this, addr, pos->second))
502        m_addr_to_mmap_size.erase (pos);
503    else
504        error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
505
506    return error;
507}
508
509addr_t
510ProcessPOSIX::ResolveIndirectFunction(const Address *address, Error &error)
511{
512    addr_t function_addr = LLDB_INVALID_ADDRESS;
513    if (address == NULL) {
514        error.SetErrorStringWithFormat("unable to determine direct function call for NULL address");
515    } else if (!InferiorCall(this, address, function_addr)) {
516        function_addr = LLDB_INVALID_ADDRESS;
517        error.SetErrorStringWithFormat("unable to determine direct function call for indirect function %s",
518                                       address->CalculateSymbolContextSymbol()->GetName().AsCString());
519    }
520    return function_addr;
521}
522
523size_t
524ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
525{
526    static const uint8_t g_i386_opcode[] = { 0xCC };
527
528    ArchSpec arch = GetTarget().GetArchitecture();
529    const uint8_t *opcode = NULL;
530    size_t opcode_size = 0;
531
532    switch (arch.GetCore())
533    {
534    default:
535        assert(false && "CPU type not supported!");
536        break;
537
538    case ArchSpec::eCore_x86_32_i386:
539    case ArchSpec::eCore_x86_64_x86_64:
540        opcode = g_i386_opcode;
541        opcode_size = sizeof(g_i386_opcode);
542        break;
543    }
544
545    bp_site->SetTrapOpcode(opcode, opcode_size);
546    return opcode_size;
547}
548
549Error
550ProcessPOSIX::EnableBreakpointSite(BreakpointSite *bp_site)
551{
552    return EnableSoftwareBreakpoint(bp_site);
553}
554
555Error
556ProcessPOSIX::DisableBreakpointSite(BreakpointSite *bp_site)
557{
558    return DisableSoftwareBreakpoint(bp_site);
559}
560
561Error
562ProcessPOSIX::EnableWatchpoint(Watchpoint *wp, bool notify)
563{
564    Error error;
565    if (wp)
566    {
567        user_id_t watchID = wp->GetID();
568        addr_t addr = wp->GetLoadAddress();
569        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
570        if (log)
571            log->Printf ("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64 ")",
572                         watchID);
573        if (wp->IsEnabled())
574        {
575            if (log)
576                log->Printf("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64
577                            ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
578                            watchID, (uint64_t)addr);
579            return error;
580        }
581
582        // Try to find a vacant watchpoint slot in the inferiors' main thread
583        uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
584        Mutex::Locker lock(m_thread_list.GetMutex());
585        POSIXThread *thread = static_cast<POSIXThread*>(
586                               m_thread_list.GetThreadAtIndex(0, false).get());
587
588        if (thread)
589            wp_hw_index = thread->FindVacantWatchpointIndex();
590
591        if (wp_hw_index == LLDB_INVALID_INDEX32)
592        {
593            error.SetErrorString("Setting hardware watchpoint failed.");
594        }
595        else
596        {
597            wp->SetHardwareIndex(wp_hw_index);
598            bool wp_enabled = true;
599            uint32_t thread_count = m_thread_list.GetSize(false);
600            for (uint32_t i = 0; i < thread_count; ++i)
601            {
602                thread = static_cast<POSIXThread*>(
603                         m_thread_list.GetThreadAtIndex(i, false).get());
604                if (thread)
605                    wp_enabled &= thread->EnableHardwareWatchpoint(wp);
606                else
607                    wp_enabled = false;
608            }
609            if (wp_enabled)
610            {
611                wp->SetEnabled(true, notify);
612                return error;
613            }
614            else
615            {
616                // Watchpoint enabling failed on at least one
617                // of the threads so roll back all of them
618                DisableWatchpoint(wp, false);
619                error.SetErrorString("Setting hardware watchpoint failed");
620            }
621        }
622    }
623    else
624        error.SetErrorString("Watchpoint argument was NULL.");
625    return error;
626}
627
628Error
629ProcessPOSIX::DisableWatchpoint(Watchpoint *wp, bool notify)
630{
631    Error error;
632    if (wp)
633    {
634        user_id_t watchID = wp->GetID();
635        addr_t addr = wp->GetLoadAddress();
636        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
637        if (log)
638            log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64 ")",
639                        watchID);
640        if (!wp->IsEnabled())
641        {
642            if (log)
643                log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64
644                            ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
645                            watchID, (uint64_t)addr);
646            // This is needed (for now) to keep watchpoints disabled correctly
647            wp->SetEnabled(false, notify);
648            return error;
649        }
650
651        if (wp->IsHardware())
652        {
653            bool wp_disabled = true;
654            Mutex::Locker lock(m_thread_list.GetMutex());
655            uint32_t thread_count = m_thread_list.GetSize(false);
656            for (uint32_t i = 0; i < thread_count; ++i)
657            {
658                POSIXThread *thread = static_cast<POSIXThread*>(
659                                      m_thread_list.GetThreadAtIndex(i, false).get());
660                if (thread)
661                    wp_disabled &= thread->DisableHardwareWatchpoint(wp);
662                else
663                    wp_disabled = false;
664            }
665            if (wp_disabled)
666            {
667                wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
668                wp->SetEnabled(false, notify);
669                return error;
670            }
671            else
672                error.SetErrorString("Disabling hardware watchpoint failed");
673        }
674    }
675    else
676        error.SetErrorString("Watchpoint argument was NULL.");
677    return error;
678}
679
680Error
681ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num)
682{
683    Error error;
684    Mutex::Locker lock(m_thread_list.GetMutex());
685    POSIXThread *thread = static_cast<POSIXThread*>(
686                          m_thread_list.GetThreadAtIndex(0, false).get());
687    if (thread)
688        num = thread->NumSupportedHardwareWatchpoints();
689    else
690        error.SetErrorString("Process does not exist.");
691    return error;
692}
693
694Error
695ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num, bool &after)
696{
697    Error error = GetWatchpointSupportInfo(num);
698    // Watchpoints trigger and halt the inferior after
699    // the corresponding instruction has been executed.
700    after = true;
701    return error;
702}
703
704uint32_t
705ProcessPOSIX::UpdateThreadListIfNeeded()
706{
707    Mutex::Locker lock(m_thread_list.GetMutex());
708    // Do not allow recursive updates.
709    return m_thread_list.GetSize(false);
710}
711
712bool
713ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
714{
715    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
716    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
717        log->Printf ("ProcessPOSIX::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID());
718
719    bool has_updated = false;
720    // Update the process thread list with this new thread.
721    // FIXME: We should be using tid, not pid.
722    assert(m_monitor);
723    ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
724    if (!thread_sp) {
725        thread_sp.reset(CreateNewPOSIXThread(*this, GetID()));
726        has_updated = true;
727    }
728
729    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
730        log->Printf ("ProcessPOSIX::%s() updated pid = %" PRIi64, __FUNCTION__, GetID());
731    new_thread_list.AddThread(thread_sp);
732
733    return has_updated; // the list has been updated
734}
735
736ByteOrder
737ProcessPOSIX::GetByteOrder() const
738{
739    // FIXME: We should be able to extract this value directly.  See comment in
740    // ProcessPOSIX().
741    return m_byte_order;
742}
743
744size_t
745ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error)
746{
747    ssize_t status;
748    if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)
749    {
750        error.SetErrorToErrno();
751        return 0;
752    }
753    return status;
754}
755
756UnixSignals &
757ProcessPOSIX::GetUnixSignals()
758{
759    return m_signals;
760}
761
762//------------------------------------------------------------------------------
763// Utility functions.
764
765bool
766ProcessPOSIX::HasExited()
767{
768    switch (GetPrivateState())
769    {
770    default:
771        break;
772
773    case eStateDetached:
774    case eStateExited:
775        return true;
776    }
777
778    return false;
779}
780
781bool
782ProcessPOSIX::IsStopped()
783{
784    switch (GetPrivateState())
785    {
786    default:
787        break;
788
789    case eStateStopped:
790    case eStateCrashed:
791    case eStateSuspended:
792        return true;
793    }
794
795    return false;
796}
797
798bool
799ProcessPOSIX::IsAThreadRunning()
800{
801    bool is_running = false;
802    Mutex::Locker lock(m_thread_list.GetMutex());
803    uint32_t thread_count = m_thread_list.GetSize(false);
804    for (uint32_t i = 0; i < thread_count; ++i)
805    {
806        POSIXThread *thread = static_cast<POSIXThread*>(
807            m_thread_list.GetThreadAtIndex(i, false).get());
808        StateType thread_state = thread->GetState();
809        if (thread_state == eStateRunning || thread_state == eStateStepping)
810        {
811            is_running = true;
812            break;
813        }
814    }
815    return is_running;
816}
817