nub_size_t MachThreadList::SetRegisterContext(nub_thread_t tid, const void *buf, size_t buf_len) { MachThreadSP thread_sp(GetThreadByID(tid)); if (thread_sp) return thread_sp->SetRegisterContext(buf, buf_len); return 0; }
void MachThreadList::DumpThreadStoppedReason (nub_thread_t tid) const { MachThreadSP thread_sp (GetThreadByID (tid)); if (thread_sp) thread_sp->GetStopException().DumpStopReason(); }
bool MachThreadList::GetThreadStoppedReason( nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const { MachThreadSP thread_sp(GetThreadByID(tid)); if (thread_sp) return thread_sp->GetStopException().GetStopInfo(stop_info); return false; }
nub_thread_t MachThreadList::SetCurrentThread(nub_thread_t tid) { MachThreadSP thread_sp(GetThreadByID(tid)); if (thread_sp) { m_current_thread = thread_sp; return tid; } return INVALID_NUB_THREAD; }
ThreadInfo::QoS MachThreadList::GetRequestedQoS(nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index) { MachThreadSP thread_sp(GetThreadByID(tid)); if (thread_sp) return thread_sp->GetRequestedQoS(tsd, dti_qos_class_index); return ThreadInfo::QoS(); }
bool MachThreadList::NotifyException(MachException::Data &exc) { MachThreadSP thread_sp(GetThreadByMachPortNumber(exc.thread_port)); if (thread_sp) { thread_sp->NotifyException(exc); return true; } return false; }
uint32_t MachThreadList::SaveRegisterState (nub_thread_t tid) { MachThreadSP thread_sp (GetThreadByID (tid)); if (thread_sp) return thread_sp->SaveRegisterState (); return 0; }
const char * MachThreadList::GetThreadInfo (nub_thread_t tid) const { MachThreadSP thread_sp (GetThreadByID (tid)); if (thread_sp) return thread_sp->GetBasicInfoAsString(); return NULL; }
nub_state_t MachThreadList::GetState(thread_t tid) { MachThreadSP thread_sp (GetThreadByID (tid)); if (thread_sp) return thread_sp->GetState(); return eStateInvalid; }
const char * MachThreadList::GetName (thread_t tid) { MachThreadSP thread_sp (GetThreadByID (tid)); if (thread_sp) return thread_sp->GetName(); return NULL; }
bool MachThreadList::RestoreRegisterState (nub_thread_t tid, uint32_t save_id) { MachThreadSP thread_sp (GetThreadByID (tid)); if (thread_sp) return thread_sp->RestoreRegisterState (save_id); return 0; }
bool MachThreadList::GetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *reg_value) const { MachThreadSP thread_sp(GetThreadByID(tid)); if (thread_sp) return thread_sp->GetRegisterValue(set, reg, reg_value); return false; }
bool MachThreadList::SetRegisterValue ( nub_thread_t tid, uint32_t reg_set_idx, uint32_t reg_idx, const DNBRegisterValue *reg_value ) const { MachThreadSP thread_sp (GetThreadByID (tid)); if (thread_sp) return thread_sp->SetRegisterValue(reg_set_idx, reg_idx, reg_value); return false; }
nub_addr_t MachThreadList::GetTSDAddressForThread( nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size) { MachThreadSP thread_sp(GetThreadByID(tid)); if (thread_sp) return thread_sp->GetTSDAddressForThread( plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size); return INVALID_NUB_ADDRESS; }
bool MachThreadList::DisableHardwareBreakpoint (const DNBBreakpoint* bp) const { if (bp != NULL) { MachThreadSP thread_sp (GetThreadByID (bp->ThreadID())); if (thread_sp) return thread_sp->DisableHardwareBreakpoint(bp); } return false; }
uint32_t MachThreadList::EnableHardwareBreakpoint (const DNBBreakpoint* bp) const { if (bp != NULL) { MachThreadSP thread_sp (GetThreadByID (bp->ThreadID())); if (thread_sp) return thread_sp->EnableHardwareBreakpoint(bp); } return INVALID_NUB_HW_INDEX; }
void PrintProcessThreadStatus(lldb_private::Stream *strm, lldb::ProcessSP process_sp) { size_t num_thread_infos_dumped = 0; // You can't hold the thread list lock while calling Thread::GetStatus. That very well might run code (e.g. if we need it // to get return values or arguments.) For that to work the process has to be able to acquire it. So instead copy the thread // ID's, and look them up one by one: uint32_t num_threads; std::vector<lldb::tid_t> thread_id_array; //Scope for thread list locker; { lldb_private::Mutex::Locker locker (process_sp->GetThreadList().GetMutex()); lldb_private::ThreadList &curr_thread_list = process_sp->GetThreadList(); num_threads = curr_thread_list.GetSize(); uint32_t idx; thread_id_array.resize(num_threads); for (idx = 0; idx < num_threads; ++idx) thread_id_array[idx] = curr_thread_list.GetThreadAtIndex(idx)->GetID(); } for (uint32_t i = 0; i < num_threads; i++) { lldb::ThreadSP thread_sp(process_sp->GetThreadList().FindThreadByID(thread_id_array[i])); if (thread_sp) { lldb::StopInfoSP stop_info_sp = thread_sp->GetStopInfo(); if (stop_info_sp.get() == NULL || !stop_info_sp->IsValid()) continue; lldb::StackFrameSP top_frame = thread_sp->GetStackFrameAtIndex(0); strm->Printf("Thread #%u stopped",thread_sp->GetIndexID()); if (top_frame) { lldb_private::SymbolContext frame_sc(top_frame->GetSymbolContext (lldb::eSymbolContextLineEntry)); if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.file) strm->Printf(" at %s:%d",frame_sc.line_entry.file.GetCString(),frame_sc.line_entry.line); strm->Printf("\n"); top_frame->GetStatus(*strm,false,true,NULL); } } } }
nub_addr_t MachThreadList::GetDispatchQueueT(nub_thread_t tid) { MachThreadSP thread_sp(GetThreadByID(tid)); if (thread_sp) return thread_sp->GetDispatchQueueT(); return INVALID_NUB_ADDRESS; }
uint32_t MachThreadList::UpdateThreadList(MachProcess *process, bool update, MachThreadList::collection *new_threads) { // locker will keep a mutex locked until it goes out of scope DNBLogThreadedIf (LOG_THREAD, "MachThreadList::UpdateThreadList (pid = %4.4x, update = %u) process stop count = %u", process->ProcessID(), update, process->StopCount()); PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); #if defined (__i386__) || defined (__x86_64__) if (process->StopCount() == 0) { int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process->ProcessID() }; struct kinfo_proc processInfo; size_t bufsize = sizeof(processInfo); bool is_64_bit = false; if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0) { if (processInfo.kp_proc.p_flag & P_LP64) is_64_bit = true; } if (is_64_bit) DNBArchProtocol::SetArchitecture(CPU_TYPE_X86_64); else DNBArchProtocol::SetArchitecture(CPU_TYPE_I386); } #endif if (m_threads.empty() || update) { thread_array_t thread_list = NULL; mach_msg_type_number_t thread_list_count = 0; task_t task = process->Task().TaskPort(); DNBError err(::task_threads (task, &thread_list, &thread_list_count), DNBError::MachKernel); if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) err.LogThreaded("::task_threads ( task = 0x%4.4x, thread_list => %p, thread_list_count => %u )", task, thread_list, thread_list_count); if (err.Error() == KERN_SUCCESS && thread_list_count > 0) { MachThreadList::collection currThreads; size_t idx; // Iterator through the current thread list and see which threads // we already have in our list (keep them), which ones we don't // (add them), and which ones are not around anymore (remove them). for (idx = 0; idx < thread_list_count; ++idx) { const thread_t tid = thread_list[idx]; MachThreadSP thread_sp (GetThreadByID (tid)); if (thread_sp) { // Keep the existing thread class currThreads.push_back(thread_sp); } else { // We don't have this thread, lets add it. thread_sp.reset(new MachThread(process, tid)); // Add the new thread regardless of its is user ready state... // Make sure the thread is ready to be displayed and shown to users // before we add this thread to our list... if (thread_sp->IsUserReady()) { if (new_threads) new_threads->push_back(thread_sp); currThreads.push_back(thread_sp); } } } m_threads.swap(currThreads); m_current_thread.reset(); // Free the vm memory given to us by ::task_threads() vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t)); ::vm_deallocate (::mach_task_self(), (vm_address_t)thread_list, thread_list_size); } } return m_threads.size(); }