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