130fdc8d8SChris Lattner //===-- MachThread.cpp ------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner // 1030fdc8d8SChris Lattner // Created by Greg Clayton on 6/19/07. 1130fdc8d8SChris Lattner // 1230fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 1330fdc8d8SChris Lattner 1430fdc8d8SChris Lattner #include "MachThread.h" 1530fdc8d8SChris Lattner #include "MachProcess.h" 1630fdc8d8SChris Lattner #include "DNBLog.h" 1730fdc8d8SChris Lattner #include "DNB.h" 1830fdc8d8SChris Lattner 1930fdc8d8SChris Lattner static uint32_t 2030fdc8d8SChris Lattner GetSequenceID() 2130fdc8d8SChris Lattner { 2230fdc8d8SChris Lattner static uint32_t g_nextID = 0; 2330fdc8d8SChris Lattner return ++g_nextID; 2430fdc8d8SChris Lattner } 2530fdc8d8SChris Lattner 2630fdc8d8SChris Lattner MachThread::MachThread (MachProcess *process, thread_t thread) : 2730fdc8d8SChris Lattner m_process (process), 2830fdc8d8SChris Lattner m_tid (thread), 2930fdc8d8SChris Lattner m_seq_id (GetSequenceID()), 3030fdc8d8SChris Lattner m_state (eStateUnloaded), 3130fdc8d8SChris Lattner m_state_mutex (PTHREAD_MUTEX_RECURSIVE), 3230fdc8d8SChris Lattner m_breakID (INVALID_NUB_BREAK_ID), 33cdc7322bSGreg Clayton m_suspendCount (0), 343af9ea56SGreg Clayton m_arch_ap (DNBArchProtocol::Create (this)), 35cdc7322bSGreg Clayton m_reg_sets (m_arch_ap->GetRegisterSetInfo (&n_num_reg_sets)) 3630fdc8d8SChris Lattner { 371b946bf6SGreg Clayton // Get the thread state so we know if a thread is in a state where we can't 381b946bf6SGreg Clayton // muck with it and also so we get the suspend count correct in case it was 391b946bf6SGreg Clayton // already suspended 40cdc7322bSGreg Clayton GetBasicInfo(); 4130fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::MachThread ( process = %p, tid = 0x%4.4x, seq_id = %u )", &m_process, m_tid, m_seq_id); 4230fdc8d8SChris Lattner } 4330fdc8d8SChris Lattner 4430fdc8d8SChris Lattner MachThread::~MachThread() 4530fdc8d8SChris Lattner { 4630fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::~MachThread() for tid = 0x%4.4x (%u)", m_tid, m_seq_id); 4730fdc8d8SChris Lattner } 4830fdc8d8SChris Lattner 4930fdc8d8SChris Lattner 5030fdc8d8SChris Lattner 51*9411ddb6SJim Ingham void 5230fdc8d8SChris Lattner MachThread::Suspend() 5330fdc8d8SChris Lattner { 5430fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 5530fdc8d8SChris Lattner if (ThreadIDIsValid(m_tid)) 5630fdc8d8SChris Lattner { 5730fdc8d8SChris Lattner DNBError err(::thread_suspend (m_tid), DNBError::MachKernel); 5830fdc8d8SChris Lattner if (err.Success()) 59cdc7322bSGreg Clayton m_suspendCount++; 6030fdc8d8SChris Lattner if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 6130fdc8d8SChris Lattner err.LogThreaded("::thread_suspend (%4.4x)", m_tid); 6230fdc8d8SChris Lattner } 6330fdc8d8SChris Lattner } 6430fdc8d8SChris Lattner 65*9411ddb6SJim Ingham void 66*9411ddb6SJim Ingham MachThread::Resume(bool others_stopped) 6730fdc8d8SChris Lattner { 6830fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 6930fdc8d8SChris Lattner if (ThreadIDIsValid(m_tid)) 7030fdc8d8SChris Lattner { 71*9411ddb6SJim Ingham SetSuspendCountBeforeResume(others_stopped); 7230fdc8d8SChris Lattner } 7330fdc8d8SChris Lattner } 7430fdc8d8SChris Lattner 7530fdc8d8SChris Lattner bool 76*9411ddb6SJim Ingham MachThread::SetSuspendCountBeforeResume(bool others_stopped) 7730fdc8d8SChris Lattner { 78cdc7322bSGreg Clayton DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 7930fdc8d8SChris Lattner DNBError err; 8030fdc8d8SChris Lattner if (ThreadIDIsValid(m_tid) == false) 8130fdc8d8SChris Lattner return false; 82*9411ddb6SJim Ingham 83*9411ddb6SJim Ingham size_t times_to_resume; 84*9411ddb6SJim Ingham 85*9411ddb6SJim Ingham if (others_stopped) 86*9411ddb6SJim Ingham { 87*9411ddb6SJim Ingham times_to_resume = GetBasicInfo()->suspend_count; 88*9411ddb6SJim Ingham m_suspendCount = - (times_to_resume - m_suspendCount); 89*9411ddb6SJim Ingham } 90*9411ddb6SJim Ingham else 91*9411ddb6SJim Ingham { 92*9411ddb6SJim Ingham times_to_resume = m_suspendCount; 93*9411ddb6SJim Ingham m_suspendCount = 0; 94*9411ddb6SJim Ingham } 95*9411ddb6SJim Ingham 96*9411ddb6SJim Ingham if (times_to_resume > 0) 97*9411ddb6SJim Ingham { 98*9411ddb6SJim Ingham while (times_to_resume > 0) 99*9411ddb6SJim Ingham { 100*9411ddb6SJim Ingham err = ::thread_resume (m_tid); 101*9411ddb6SJim Ingham if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 102*9411ddb6SJim Ingham err.LogThreaded("::thread_resume (%4.4x)", m_tid); 103*9411ddb6SJim Ingham if (err.Success()) 104*9411ddb6SJim Ingham --times_to_resume; 105*9411ddb6SJim Ingham else 106*9411ddb6SJim Ingham { 107*9411ddb6SJim Ingham if (GetBasicInfo()) 108*9411ddb6SJim Ingham times_to_resume = m_basicInfo.suspend_count; 109*9411ddb6SJim Ingham else 110*9411ddb6SJim Ingham times_to_resume = 0; 111*9411ddb6SJim Ingham return false; // ??? 112*9411ddb6SJim Ingham } 113*9411ddb6SJim Ingham } 114*9411ddb6SJim Ingham } 115*9411ddb6SJim Ingham return true; 116*9411ddb6SJim Ingham } 117*9411ddb6SJim Ingham 118*9411ddb6SJim Ingham bool 119*9411ddb6SJim Ingham MachThread::RestoreSuspendCountAfterStop () 120*9411ddb6SJim Ingham { 121*9411ddb6SJim Ingham DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 122*9411ddb6SJim Ingham DNBError err; 123*9411ddb6SJim Ingham if (ThreadIDIsValid(m_tid) == false) 124*9411ddb6SJim Ingham return false; 125*9411ddb6SJim Ingham 126cdc7322bSGreg Clayton if (m_suspendCount > 0) 12730fdc8d8SChris Lattner { 128cdc7322bSGreg Clayton while (m_suspendCount > 0) 12930fdc8d8SChris Lattner { 13030fdc8d8SChris Lattner err = ::thread_resume (m_tid); 13130fdc8d8SChris Lattner if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 132cdc7322bSGreg Clayton err.LogThreaded("::thread_resume (%4.4x)", m_tid); 13330fdc8d8SChris Lattner if (err.Success()) 134cdc7322bSGreg Clayton --m_suspendCount; 1350dd2c627SGreg Clayton else 1360dd2c627SGreg Clayton { 137cdc7322bSGreg Clayton if (GetBasicInfo()) 138cdc7322bSGreg Clayton m_suspendCount = m_basicInfo.suspend_count; 1390dd2c627SGreg Clayton else 140cdc7322bSGreg Clayton m_suspendCount = 0; 1410dd2c627SGreg Clayton return false; // ??? 14230fdc8d8SChris Lattner } 14330fdc8d8SChris Lattner } 1440dd2c627SGreg Clayton } 145*9411ddb6SJim Ingham else if (m_suspendCount < 0) 146*9411ddb6SJim Ingham { 147*9411ddb6SJim Ingham while (m_suspendCount < 0) 148*9411ddb6SJim Ingham { 149*9411ddb6SJim Ingham err = ::thread_suspend (m_tid); 150*9411ddb6SJim Ingham if (err.Success()) 151*9411ddb6SJim Ingham ++m_suspendCount; 152*9411ddb6SJim Ingham if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 153*9411ddb6SJim Ingham err.LogThreaded("::thread_suspend (%4.4x)", m_tid); 154*9411ddb6SJim Ingham } 155*9411ddb6SJim Ingham } 1560dd2c627SGreg Clayton return true; 15730fdc8d8SChris Lattner } 15830fdc8d8SChris Lattner 15930fdc8d8SChris Lattner 16030fdc8d8SChris Lattner const char * 16130fdc8d8SChris Lattner MachThread::GetBasicInfoAsString () const 16230fdc8d8SChris Lattner { 16330fdc8d8SChris Lattner static char g_basic_info_string[1024]; 16430fdc8d8SChris Lattner struct thread_basic_info basicInfo; 16530fdc8d8SChris Lattner 16630fdc8d8SChris Lattner if (GetBasicInfo(m_tid, &basicInfo)) 16730fdc8d8SChris Lattner { 16830fdc8d8SChris Lattner 16930fdc8d8SChris Lattner // char run_state_str[32]; 17030fdc8d8SChris Lattner // size_t run_state_str_size = sizeof(run_state_str); 17130fdc8d8SChris Lattner // switch (basicInfo.run_state) 17230fdc8d8SChris Lattner // { 17330fdc8d8SChris Lattner // case TH_STATE_RUNNING: strncpy(run_state_str, "running", run_state_str_size); break; 17430fdc8d8SChris Lattner // case TH_STATE_STOPPED: strncpy(run_state_str, "stopped", run_state_str_size); break; 17530fdc8d8SChris Lattner // case TH_STATE_WAITING: strncpy(run_state_str, "waiting", run_state_str_size); break; 17630fdc8d8SChris Lattner // case TH_STATE_UNINTERRUPTIBLE: strncpy(run_state_str, "uninterruptible", run_state_str_size); break; 17730fdc8d8SChris Lattner // case TH_STATE_HALTED: strncpy(run_state_str, "halted", run_state_str_size); break; 17830fdc8d8SChris Lattner // default: snprintf(run_state_str, run_state_str_size, "%d", basicInfo.run_state); break; // ??? 17930fdc8d8SChris Lattner // } 18030fdc8d8SChris Lattner float user = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f; 18130fdc8d8SChris Lattner float system = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f; 18230fdc8d8SChris Lattner snprintf(g_basic_info_string, sizeof(g_basic_info_string), "Thread 0x%4.4x: user=%f system=%f cpu=%d sleep_time=%d", 18330fdc8d8SChris Lattner InferiorThreadID(), 18430fdc8d8SChris Lattner user, 18530fdc8d8SChris Lattner system, 18630fdc8d8SChris Lattner basicInfo.cpu_usage, 18730fdc8d8SChris Lattner basicInfo.sleep_time); 18830fdc8d8SChris Lattner 18930fdc8d8SChris Lattner return g_basic_info_string; 19030fdc8d8SChris Lattner } 19130fdc8d8SChris Lattner return NULL; 19230fdc8d8SChris Lattner } 19330fdc8d8SChris Lattner 19430fdc8d8SChris Lattner thread_t 19530fdc8d8SChris Lattner MachThread::InferiorThreadID() const 19630fdc8d8SChris Lattner { 19730fdc8d8SChris Lattner mach_msg_type_number_t i; 19830fdc8d8SChris Lattner mach_port_name_array_t names; 19930fdc8d8SChris Lattner mach_port_type_array_t types; 20030fdc8d8SChris Lattner mach_msg_type_number_t ncount, tcount; 20130fdc8d8SChris Lattner thread_t inferior_tid = INVALID_NUB_THREAD; 20230fdc8d8SChris Lattner task_t my_task = ::mach_task_self(); 20330fdc8d8SChris Lattner task_t task = m_process->Task().TaskPort(); 20430fdc8d8SChris Lattner 20530fdc8d8SChris Lattner kern_return_t kret = ::mach_port_names (task, &names, &ncount, &types, &tcount); 20630fdc8d8SChris Lattner if (kret == KERN_SUCCESS) 20730fdc8d8SChris Lattner { 20830fdc8d8SChris Lattner 20930fdc8d8SChris Lattner for (i = 0; i < ncount; i++) 21030fdc8d8SChris Lattner { 21130fdc8d8SChris Lattner mach_port_t my_name; 21230fdc8d8SChris Lattner mach_msg_type_name_t my_type; 21330fdc8d8SChris Lattner 21430fdc8d8SChris Lattner kret = ::mach_port_extract_right (task, names[i], MACH_MSG_TYPE_COPY_SEND, &my_name, &my_type); 21530fdc8d8SChris Lattner if (kret == KERN_SUCCESS) 21630fdc8d8SChris Lattner { 21730fdc8d8SChris Lattner ::mach_port_deallocate (my_task, my_name); 21830fdc8d8SChris Lattner if (my_name == m_tid) 21930fdc8d8SChris Lattner { 22030fdc8d8SChris Lattner inferior_tid = names[i]; 22130fdc8d8SChris Lattner break; 22230fdc8d8SChris Lattner } 22330fdc8d8SChris Lattner } 22430fdc8d8SChris Lattner } 22530fdc8d8SChris Lattner // Free up the names and types 22630fdc8d8SChris Lattner ::vm_deallocate (my_task, (vm_address_t) names, ncount * sizeof (mach_port_name_t)); 22730fdc8d8SChris Lattner ::vm_deallocate (my_task, (vm_address_t) types, tcount * sizeof (mach_port_type_t)); 22830fdc8d8SChris Lattner } 22930fdc8d8SChris Lattner return inferior_tid; 23030fdc8d8SChris Lattner } 23130fdc8d8SChris Lattner 23230fdc8d8SChris Lattner bool 2331b946bf6SGreg Clayton MachThread::IsUserReady() 2341b946bf6SGreg Clayton { 235cdc7322bSGreg Clayton if (m_basicInfo.run_state == 0) 236cdc7322bSGreg Clayton GetBasicInfo (); 2371b946bf6SGreg Clayton 238cdc7322bSGreg Clayton switch (m_basicInfo.run_state) 2391b946bf6SGreg Clayton { 2401b946bf6SGreg Clayton default: 2411b946bf6SGreg Clayton case TH_STATE_UNINTERRUPTIBLE: 2421b946bf6SGreg Clayton break; 2431b946bf6SGreg Clayton 2441b946bf6SGreg Clayton case TH_STATE_RUNNING: 2451b946bf6SGreg Clayton case TH_STATE_STOPPED: 2461b946bf6SGreg Clayton case TH_STATE_WAITING: 2471b946bf6SGreg Clayton case TH_STATE_HALTED: 2481b946bf6SGreg Clayton return true; 2491b946bf6SGreg Clayton } 2501b946bf6SGreg Clayton return false; 2511b946bf6SGreg Clayton } 2521b946bf6SGreg Clayton 2531b946bf6SGreg Clayton struct thread_basic_info * 254cdc7322bSGreg Clayton MachThread::GetBasicInfo () 2551b946bf6SGreg Clayton { 256cdc7322bSGreg Clayton if (MachThread::GetBasicInfo(m_tid, &m_basicInfo)) 257cdc7322bSGreg Clayton return &m_basicInfo; 2581b946bf6SGreg Clayton return NULL; 2591b946bf6SGreg Clayton } 2601b946bf6SGreg Clayton 2611b946bf6SGreg Clayton 2621b946bf6SGreg Clayton bool 26330fdc8d8SChris Lattner MachThread::GetBasicInfo(thread_t thread, struct thread_basic_info *basicInfoPtr) 26430fdc8d8SChris Lattner { 26530fdc8d8SChris Lattner if (ThreadIDIsValid(thread)) 26630fdc8d8SChris Lattner { 26730fdc8d8SChris Lattner unsigned int info_count = THREAD_BASIC_INFO_COUNT; 26830fdc8d8SChris Lattner kern_return_t err = ::thread_info (thread, THREAD_BASIC_INFO, (thread_info_t) basicInfoPtr, &info_count); 26930fdc8d8SChris Lattner if (err == KERN_SUCCESS) 27030fdc8d8SChris Lattner return true; 27130fdc8d8SChris Lattner } 27230fdc8d8SChris Lattner ::memset (basicInfoPtr, 0, sizeof (struct thread_basic_info)); 27330fdc8d8SChris Lattner return false; 27430fdc8d8SChris Lattner } 27530fdc8d8SChris Lattner 27630fdc8d8SChris Lattner 27730fdc8d8SChris Lattner bool 27830fdc8d8SChris Lattner MachThread::ThreadIDIsValid(thread_t thread) 27930fdc8d8SChris Lattner { 28030fdc8d8SChris Lattner return thread != THREAD_NULL; 28130fdc8d8SChris Lattner } 28230fdc8d8SChris Lattner 28330fdc8d8SChris Lattner bool 28430fdc8d8SChris Lattner MachThread::GetRegisterState(int flavor, bool force) 28530fdc8d8SChris Lattner { 2863af9ea56SGreg Clayton return m_arch_ap->GetRegisterState(flavor, force) == KERN_SUCCESS; 28730fdc8d8SChris Lattner } 28830fdc8d8SChris Lattner 28930fdc8d8SChris Lattner bool 29030fdc8d8SChris Lattner MachThread::SetRegisterState(int flavor) 29130fdc8d8SChris Lattner { 2923af9ea56SGreg Clayton return m_arch_ap->SetRegisterState(flavor) == KERN_SUCCESS; 29330fdc8d8SChris Lattner } 29430fdc8d8SChris Lattner 29530fdc8d8SChris Lattner uint64_t 29630fdc8d8SChris Lattner MachThread::GetPC(uint64_t failValue) 29730fdc8d8SChris Lattner { 29830fdc8d8SChris Lattner // Get program counter 2993af9ea56SGreg Clayton return m_arch_ap->GetPC(failValue); 30030fdc8d8SChris Lattner } 30130fdc8d8SChris Lattner 30230fdc8d8SChris Lattner bool 30330fdc8d8SChris Lattner MachThread::SetPC(uint64_t value) 30430fdc8d8SChris Lattner { 30530fdc8d8SChris Lattner // Set program counter 3063af9ea56SGreg Clayton return m_arch_ap->SetPC(value); 30730fdc8d8SChris Lattner } 30830fdc8d8SChris Lattner 30930fdc8d8SChris Lattner uint64_t 31030fdc8d8SChris Lattner MachThread::GetSP(uint64_t failValue) 31130fdc8d8SChris Lattner { 31230fdc8d8SChris Lattner // Get stack pointer 3133af9ea56SGreg Clayton return m_arch_ap->GetSP(failValue); 31430fdc8d8SChris Lattner } 31530fdc8d8SChris Lattner 31630fdc8d8SChris Lattner nub_process_t 31730fdc8d8SChris Lattner MachThread::ProcessID() const 31830fdc8d8SChris Lattner { 31930fdc8d8SChris Lattner if (m_process) 32030fdc8d8SChris Lattner return m_process->ProcessID(); 32130fdc8d8SChris Lattner return INVALID_NUB_PROCESS; 32230fdc8d8SChris Lattner } 32330fdc8d8SChris Lattner 32430fdc8d8SChris Lattner void 32530fdc8d8SChris Lattner MachThread::Dump(uint32_t index) 32630fdc8d8SChris Lattner { 32730fdc8d8SChris Lattner const char * thread_run_state = NULL; 32830fdc8d8SChris Lattner 329cdc7322bSGreg Clayton switch (m_basicInfo.run_state) 33030fdc8d8SChris Lattner { 33130fdc8d8SChris Lattner case TH_STATE_RUNNING: thread_run_state = "running"; break; // 1 thread is running normally 33230fdc8d8SChris Lattner case TH_STATE_STOPPED: thread_run_state = "stopped"; break; // 2 thread is stopped 33330fdc8d8SChris Lattner case TH_STATE_WAITING: thread_run_state = "waiting"; break; // 3 thread is waiting normally 33430fdc8d8SChris Lattner case TH_STATE_UNINTERRUPTIBLE: thread_run_state = "uninter"; break; // 4 thread is in an uninterruptible wait 33530fdc8d8SChris Lattner case TH_STATE_HALTED: thread_run_state = "halted "; break; // 5 thread is halted at a 33630fdc8d8SChris Lattner default: thread_run_state = "???"; break; 33730fdc8d8SChris Lattner } 33830fdc8d8SChris Lattner 339e2d4f0d7SGreg Clayton DNBLogThreaded("[%3u] #%3u tid: 0x%4.4x, pc: 0x%16.16llx, sp: 0x%16.16llx, breakID: %3d, user: %d.%06.6d, system: %d.%06.6d, cpu: %2d, policy: %2d, run_state: %2d (%s), flags: %2d, suspend_count: %2d (current %2d), sleep_time: %d", 34030fdc8d8SChris Lattner index, 34130fdc8d8SChris Lattner m_seq_id, 342e2d4f0d7SGreg Clayton m_tid, 34330fdc8d8SChris Lattner GetPC(INVALID_NUB_ADDRESS), 34430fdc8d8SChris Lattner GetSP(INVALID_NUB_ADDRESS), 34530fdc8d8SChris Lattner m_breakID, 346cdc7322bSGreg Clayton m_basicInfo.user_time.seconds, m_basicInfo.user_time.microseconds, 347cdc7322bSGreg Clayton m_basicInfo.system_time.seconds, m_basicInfo.system_time.microseconds, 348cdc7322bSGreg Clayton m_basicInfo.cpu_usage, 349cdc7322bSGreg Clayton m_basicInfo.policy, 350cdc7322bSGreg Clayton m_basicInfo.run_state, 35130fdc8d8SChris Lattner thread_run_state, 352cdc7322bSGreg Clayton m_basicInfo.flags, 353cdc7322bSGreg Clayton m_basicInfo.suspend_count, m_suspendCount, 354cdc7322bSGreg Clayton m_basicInfo.sleep_time); 35530fdc8d8SChris Lattner //DumpRegisterState(0); 35630fdc8d8SChris Lattner } 35730fdc8d8SChris Lattner 35830fdc8d8SChris Lattner void 359*9411ddb6SJim Ingham MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action, bool others_stopped) 36030fdc8d8SChris Lattner { 36130fdc8d8SChris Lattner if (thread_action->addr != INVALID_NUB_ADDRESS) 36230fdc8d8SChris Lattner SetPC (thread_action->addr); 363cdc7322bSGreg Clayton 36430fdc8d8SChris Lattner SetState (thread_action->state); 36530fdc8d8SChris Lattner switch (thread_action->state) 36630fdc8d8SChris Lattner { 36730fdc8d8SChris Lattner case eStateStopped: 36830fdc8d8SChris Lattner case eStateSuspended: 369*9411ddb6SJim Ingham assert (others_stopped == false); 37030fdc8d8SChris Lattner Suspend(); 37130fdc8d8SChris Lattner break; 37230fdc8d8SChris Lattner 37330fdc8d8SChris Lattner case eStateRunning: 374b1e11121SJim Ingham case eStateStepping: 375*9411ddb6SJim Ingham Resume(others_stopped); 376b1e11121SJim Ingham break; 377effe5c95SGreg Clayton default: 378effe5c95SGreg Clayton break; 37930fdc8d8SChris Lattner } 3803af9ea56SGreg Clayton m_arch_ap->ThreadWillResume(); 38130fdc8d8SChris Lattner m_stop_exception.Clear(); 38230fdc8d8SChris Lattner } 38330fdc8d8SChris Lattner 384c4e411ffSGreg Clayton nub_break_t 385c4e411ffSGreg Clayton MachThread::CurrentBreakpoint() 386c4e411ffSGreg Clayton { 387c4e411ffSGreg Clayton return m_process->Breakpoints().FindIDByAddress(GetPC()); 388c4e411ffSGreg Clayton } 389c4e411ffSGreg Clayton 39030fdc8d8SChris Lattner bool 39130fdc8d8SChris Lattner MachThread::ShouldStop(bool &step_more) 39230fdc8d8SChris Lattner { 39330fdc8d8SChris Lattner // See if this thread is at a breakpoint? 39430fdc8d8SChris Lattner nub_break_t breakID = CurrentBreakpoint(); 39530fdc8d8SChris Lattner 39630fdc8d8SChris Lattner if (NUB_BREAK_ID_IS_VALID(breakID)) 39730fdc8d8SChris Lattner { 39830fdc8d8SChris Lattner // This thread is sitting at a breakpoint, ask the breakpoint 39930fdc8d8SChris Lattner // if we should be stopping here. 40030fdc8d8SChris Lattner if (Process()->Breakpoints().ShouldStop(ProcessID(), ThreadID(), breakID)) 40130fdc8d8SChris Lattner return true; 40230fdc8d8SChris Lattner else 40330fdc8d8SChris Lattner { 40430fdc8d8SChris Lattner // The breakpoint said we shouldn't stop, but we may have gotten 40530fdc8d8SChris Lattner // a signal or the user may have requested to stop in some other 40630fdc8d8SChris Lattner // way. Stop if we have a valid exception (this thread won't if 40730fdc8d8SChris Lattner // another thread was the reason this process stopped) and that 40830fdc8d8SChris Lattner // exception, is NOT a breakpoint exception (a common case would 40930fdc8d8SChris Lattner // be a SIGINT signal). 41030fdc8d8SChris Lattner if (GetStopException().IsValid() && !GetStopException().IsBreakpoint()) 41130fdc8d8SChris Lattner return true; 41230fdc8d8SChris Lattner } 41330fdc8d8SChris Lattner } 41430fdc8d8SChris Lattner else 41530fdc8d8SChris Lattner { 4163af9ea56SGreg Clayton if (m_arch_ap->StepNotComplete()) 41730fdc8d8SChris Lattner { 41830fdc8d8SChris Lattner step_more = true; 41930fdc8d8SChris Lattner return false; 42030fdc8d8SChris Lattner } 42130fdc8d8SChris Lattner // The thread state is used to let us know what the thread was 42230fdc8d8SChris Lattner // trying to do. MachThread::ThreadWillResume() will set the 42330fdc8d8SChris Lattner // thread state to various values depending if the thread was 42430fdc8d8SChris Lattner // the current thread and if it was to be single stepped, or 42530fdc8d8SChris Lattner // resumed. 42630fdc8d8SChris Lattner if (GetState() == eStateRunning) 42730fdc8d8SChris Lattner { 42830fdc8d8SChris Lattner // If our state is running, then we should continue as we are in 42930fdc8d8SChris Lattner // the process of stepping over a breakpoint. 43030fdc8d8SChris Lattner return false; 43130fdc8d8SChris Lattner } 43230fdc8d8SChris Lattner else 43330fdc8d8SChris Lattner { 43430fdc8d8SChris Lattner // Stop if we have any kind of valid exception for this 43530fdc8d8SChris Lattner // thread. 43630fdc8d8SChris Lattner if (GetStopException().IsValid()) 43730fdc8d8SChris Lattner return true; 43830fdc8d8SChris Lattner } 43930fdc8d8SChris Lattner } 44030fdc8d8SChris Lattner return false; 44130fdc8d8SChris Lattner } 44230fdc8d8SChris Lattner bool 44330fdc8d8SChris Lattner MachThread::IsStepping() 44430fdc8d8SChris Lattner { 445c4e411ffSGreg Clayton #if ENABLE_AUTO_STEPPING_OVER_BP 44630fdc8d8SChris Lattner // Return true if this thread is currently being stepped. 44730fdc8d8SChris Lattner // MachThread::ThreadWillResume currently determines this by looking if we 44830fdc8d8SChris Lattner // have been asked to single step, or if we are at a breakpoint instruction 44930fdc8d8SChris Lattner // and have been asked to resume. In the latter case we need to disable the 45030fdc8d8SChris Lattner // breakpoint we are at, single step, re-enable and continue. 45130fdc8d8SChris Lattner nub_state_t state = GetState(); 452c4e411ffSGreg Clayton return ((state == eStateStepping) || 453c4e411ffSGreg Clayton (state == eStateRunning && NUB_BREAK_ID_IS_VALID(CurrentBreakpoint()))); 454c4e411ffSGreg Clayton #else 455c4e411ffSGreg Clayton return GetState() == eStateStepping; 456c4e411ffSGreg Clayton #endif 45730fdc8d8SChris Lattner } 45830fdc8d8SChris Lattner 45930fdc8d8SChris Lattner 46030fdc8d8SChris Lattner bool 46130fdc8d8SChris Lattner MachThread::ThreadDidStop() 46230fdc8d8SChris Lattner { 46330fdc8d8SChris Lattner // This thread has existed prior to resuming under debug nub control, 46430fdc8d8SChris Lattner // and has just been stopped. Do any cleanup that needs to be done 46530fdc8d8SChris Lattner // after running. 46630fdc8d8SChris Lattner 46730fdc8d8SChris Lattner // The thread state and breakpoint will still have the same values 46830fdc8d8SChris Lattner // as they had prior to resuming the thread, so it makes it easy to check 46930fdc8d8SChris Lattner // if we were trying to step a thread, or we tried to resume while being 47030fdc8d8SChris Lattner // at a breakpoint. 47130fdc8d8SChris Lattner 47230fdc8d8SChris Lattner // When this method gets called, the process state is still in the 47330fdc8d8SChris Lattner // state it was in while running so we can act accordingly. 4743af9ea56SGreg Clayton m_arch_ap->ThreadDidStop(); 47530fdc8d8SChris Lattner 47630fdc8d8SChris Lattner 47730fdc8d8SChris Lattner // We may have suspended this thread so the primary thread could step 47830fdc8d8SChris Lattner // without worrying about race conditions, so lets restore our suspend 47930fdc8d8SChris Lattner // count. 480*9411ddb6SJim Ingham RestoreSuspendCountAfterStop(); 48130fdc8d8SChris Lattner 48230fdc8d8SChris Lattner // Update the basic information for a thread 483cdc7322bSGreg Clayton MachThread::GetBasicInfo(m_tid, &m_basicInfo); 48430fdc8d8SChris Lattner 485c4e411ffSGreg Clayton #if ENABLE_AUTO_STEPPING_OVER_BP 48630fdc8d8SChris Lattner // See if we were at a breakpoint when we last resumed that we disabled, 48730fdc8d8SChris Lattner // re-enable it. 48830fdc8d8SChris Lattner nub_break_t breakID = CurrentBreakpoint(); 48930fdc8d8SChris Lattner 49030fdc8d8SChris Lattner if (NUB_BREAK_ID_IS_VALID(breakID)) 49130fdc8d8SChris Lattner { 49230fdc8d8SChris Lattner m_process->EnableBreakpoint(breakID); 493cdc7322bSGreg Clayton if (m_basicInfo.suspend_count > 0) 49430fdc8d8SChris Lattner { 49530fdc8d8SChris Lattner SetState(eStateSuspended); 49630fdc8d8SChris Lattner } 49730fdc8d8SChris Lattner else 49830fdc8d8SChris Lattner { 49930fdc8d8SChris Lattner // If we last were at a breakpoint and we single stepped, our state 50030fdc8d8SChris Lattner // will be "running" to indicate we need to continue after stepping 50130fdc8d8SChris Lattner // over the breakpoint instruction. If we step over a breakpoint 50230fdc8d8SChris Lattner // instruction, we need to stop. 50330fdc8d8SChris Lattner if (GetState() == eStateRunning) 50430fdc8d8SChris Lattner { 50530fdc8d8SChris Lattner // Leave state set to running so we will continue automatically 50630fdc8d8SChris Lattner // from this breakpoint 50730fdc8d8SChris Lattner } 50830fdc8d8SChris Lattner else 50930fdc8d8SChris Lattner { 51030fdc8d8SChris Lattner SetState(eStateStopped); 51130fdc8d8SChris Lattner } 51230fdc8d8SChris Lattner } 51330fdc8d8SChris Lattner } 51430fdc8d8SChris Lattner else 51530fdc8d8SChris Lattner { 516cdc7322bSGreg Clayton if (m_basicInfo.suspend_count > 0) 51730fdc8d8SChris Lattner { 51830fdc8d8SChris Lattner SetState(eStateSuspended); 51930fdc8d8SChris Lattner } 52030fdc8d8SChris Lattner else 52130fdc8d8SChris Lattner { 52230fdc8d8SChris Lattner SetState(eStateStopped); 52330fdc8d8SChris Lattner } 52430fdc8d8SChris Lattner } 525c4e411ffSGreg Clayton #else 526cdc7322bSGreg Clayton if (m_basicInfo.suspend_count > 0) 527c4e411ffSGreg Clayton SetState(eStateSuspended); 528c4e411ffSGreg Clayton else 529c4e411ffSGreg Clayton SetState(eStateStopped); 530c4e411ffSGreg Clayton #endif 53130fdc8d8SChris Lattner return true; 53230fdc8d8SChris Lattner } 53330fdc8d8SChris Lattner 53430fdc8d8SChris Lattner bool 53530fdc8d8SChris Lattner MachThread::NotifyException(MachException::Data& exc) 53630fdc8d8SChris Lattner { 53730fdc8d8SChris Lattner if (m_stop_exception.IsValid()) 53830fdc8d8SChris Lattner { 53930fdc8d8SChris Lattner // We may have more than one exception for a thread, but we need to 54030fdc8d8SChris Lattner // only remember the one that we will say is the reason we stopped. 54130fdc8d8SChris Lattner // We may have been single stepping and also gotten a signal exception, 54230fdc8d8SChris Lattner // so just remember the most pertinent one. 54330fdc8d8SChris Lattner if (m_stop_exception.IsBreakpoint()) 54430fdc8d8SChris Lattner m_stop_exception = exc; 54530fdc8d8SChris Lattner } 54630fdc8d8SChris Lattner else 54730fdc8d8SChris Lattner { 54830fdc8d8SChris Lattner m_stop_exception = exc; 54930fdc8d8SChris Lattner } 5503af9ea56SGreg Clayton bool handled = m_arch_ap->NotifyException(exc); 55130fdc8d8SChris Lattner if (!handled) 55230fdc8d8SChris Lattner { 55330fdc8d8SChris Lattner handled = true; 554c4e411ffSGreg Clayton // switch (exc.exc_type) 555c4e411ffSGreg Clayton // { 556c4e411ffSGreg Clayton // case EXC_BAD_ACCESS: 557c4e411ffSGreg Clayton // break; 558c4e411ffSGreg Clayton // case EXC_BAD_INSTRUCTION: 559c4e411ffSGreg Clayton // break; 560c4e411ffSGreg Clayton // case EXC_ARITHMETIC: 561c4e411ffSGreg Clayton // break; 562c4e411ffSGreg Clayton // case EXC_EMULATION: 563c4e411ffSGreg Clayton // break; 564c4e411ffSGreg Clayton // case EXC_SOFTWARE: 565c4e411ffSGreg Clayton // break; 566c4e411ffSGreg Clayton // case EXC_BREAKPOINT: 567c4e411ffSGreg Clayton // break; 568c4e411ffSGreg Clayton // case EXC_SYSCALL: 569c4e411ffSGreg Clayton // break; 570c4e411ffSGreg Clayton // case EXC_MACH_SYSCALL: 571c4e411ffSGreg Clayton // break; 572c4e411ffSGreg Clayton // case EXC_RPC_ALERT: 573c4e411ffSGreg Clayton // break; 574c4e411ffSGreg Clayton // } 57530fdc8d8SChris Lattner } 57630fdc8d8SChris Lattner return handled; 57730fdc8d8SChris Lattner } 57830fdc8d8SChris Lattner 57930fdc8d8SChris Lattner 58030fdc8d8SChris Lattner nub_state_t 58130fdc8d8SChris Lattner MachThread::GetState() 58230fdc8d8SChris Lattner { 58330fdc8d8SChris Lattner // If any other threads access this we will need a mutex for it 58430fdc8d8SChris Lattner PTHREAD_MUTEX_LOCKER (locker, m_state_mutex); 58530fdc8d8SChris Lattner return m_state; 58630fdc8d8SChris Lattner } 58730fdc8d8SChris Lattner 58830fdc8d8SChris Lattner void 58930fdc8d8SChris Lattner MachThread::SetState(nub_state_t state) 59030fdc8d8SChris Lattner { 59130fdc8d8SChris Lattner PTHREAD_MUTEX_LOCKER (locker, m_state_mutex); 59230fdc8d8SChris Lattner m_state = state; 59330fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD, "MachThread::SetState ( %s ) for tid = 0x%4.4x", DNBStateAsString(state), m_tid); 59430fdc8d8SChris Lattner } 59530fdc8d8SChris Lattner 59630fdc8d8SChris Lattner uint32_t 59730fdc8d8SChris Lattner MachThread::GetNumRegistersInSet(int regSet) const 59830fdc8d8SChris Lattner { 5993af9ea56SGreg Clayton if (regSet < n_num_reg_sets) 6003af9ea56SGreg Clayton return m_reg_sets[regSet].num_registers; 60130fdc8d8SChris Lattner return 0; 60230fdc8d8SChris Lattner } 60330fdc8d8SChris Lattner 60430fdc8d8SChris Lattner const char * 60530fdc8d8SChris Lattner MachThread::GetRegisterSetName(int regSet) const 60630fdc8d8SChris Lattner { 6073af9ea56SGreg Clayton if (regSet < n_num_reg_sets) 6083af9ea56SGreg Clayton return m_reg_sets[regSet].name; 60930fdc8d8SChris Lattner return NULL; 61030fdc8d8SChris Lattner } 61130fdc8d8SChris Lattner 61230fdc8d8SChris Lattner const DNBRegisterInfo * 61330fdc8d8SChris Lattner MachThread::GetRegisterInfo(int regSet, int regIndex) const 61430fdc8d8SChris Lattner { 6153af9ea56SGreg Clayton if (regSet < n_num_reg_sets) 6163af9ea56SGreg Clayton if (regIndex < m_reg_sets[regSet].num_registers) 6173af9ea56SGreg Clayton return &m_reg_sets[regSet].registers[regIndex]; 61830fdc8d8SChris Lattner return NULL; 61930fdc8d8SChris Lattner } 62030fdc8d8SChris Lattner void 62130fdc8d8SChris Lattner MachThread::DumpRegisterState(int regSet) 62230fdc8d8SChris Lattner { 62330fdc8d8SChris Lattner if (regSet == REGISTER_SET_ALL) 62430fdc8d8SChris Lattner { 6253af9ea56SGreg Clayton for (regSet = 1; regSet < n_num_reg_sets; regSet++) 62630fdc8d8SChris Lattner DumpRegisterState(regSet); 62730fdc8d8SChris Lattner } 62830fdc8d8SChris Lattner else 62930fdc8d8SChris Lattner { 6303af9ea56SGreg Clayton if (m_arch_ap->RegisterSetStateIsValid(regSet)) 63130fdc8d8SChris Lattner { 63230fdc8d8SChris Lattner const size_t numRegisters = GetNumRegistersInSet(regSet); 63330fdc8d8SChris Lattner size_t regIndex = 0; 63430fdc8d8SChris Lattner DNBRegisterValueClass reg; 63530fdc8d8SChris Lattner for (regIndex = 0; regIndex < numRegisters; ++regIndex) 63630fdc8d8SChris Lattner { 6373af9ea56SGreg Clayton if (m_arch_ap->GetRegisterValue(regSet, regIndex, ®)) 63830fdc8d8SChris Lattner { 63930fdc8d8SChris Lattner reg.Dump(NULL, NULL); 64030fdc8d8SChris Lattner } 64130fdc8d8SChris Lattner } 64230fdc8d8SChris Lattner } 64330fdc8d8SChris Lattner else 64430fdc8d8SChris Lattner { 64530fdc8d8SChris Lattner DNBLog("%s: registers are not currently valid.", GetRegisterSetName(regSet)); 64630fdc8d8SChris Lattner } 64730fdc8d8SChris Lattner } 64830fdc8d8SChris Lattner } 64930fdc8d8SChris Lattner 65030fdc8d8SChris Lattner const DNBRegisterSetInfo * 65130fdc8d8SChris Lattner MachThread::GetRegisterSetInfo(nub_size_t *num_reg_sets ) const 65230fdc8d8SChris Lattner { 6533af9ea56SGreg Clayton *num_reg_sets = n_num_reg_sets; 6543af9ea56SGreg Clayton return &m_reg_sets[0]; 65530fdc8d8SChris Lattner } 65630fdc8d8SChris Lattner 65730fdc8d8SChris Lattner bool 65830fdc8d8SChris Lattner MachThread::GetRegisterValue ( uint32_t set, uint32_t reg, DNBRegisterValue *value ) 65930fdc8d8SChris Lattner { 6603af9ea56SGreg Clayton return m_arch_ap->GetRegisterValue(set, reg, value); 66130fdc8d8SChris Lattner } 66230fdc8d8SChris Lattner 66330fdc8d8SChris Lattner bool 66430fdc8d8SChris Lattner MachThread::SetRegisterValue ( uint32_t set, uint32_t reg, const DNBRegisterValue *value ) 66530fdc8d8SChris Lattner { 6663af9ea56SGreg Clayton return m_arch_ap->SetRegisterValue(set, reg, value); 66730fdc8d8SChris Lattner } 66830fdc8d8SChris Lattner 66930fdc8d8SChris Lattner nub_size_t 67030fdc8d8SChris Lattner MachThread::GetRegisterContext (void *buf, nub_size_t buf_len) 67130fdc8d8SChris Lattner { 6723af9ea56SGreg Clayton return m_arch_ap->GetRegisterContext(buf, buf_len); 67330fdc8d8SChris Lattner } 67430fdc8d8SChris Lattner 67530fdc8d8SChris Lattner nub_size_t 67630fdc8d8SChris Lattner MachThread::SetRegisterContext (const void *buf, nub_size_t buf_len) 67730fdc8d8SChris Lattner { 6783af9ea56SGreg Clayton return m_arch_ap->SetRegisterContext(buf, buf_len); 67930fdc8d8SChris Lattner } 68030fdc8d8SChris Lattner 68130fdc8d8SChris Lattner uint32_t 68230fdc8d8SChris Lattner MachThread::EnableHardwareBreakpoint (const DNBBreakpoint *bp) 68330fdc8d8SChris Lattner { 68430fdc8d8SChris Lattner if (bp != NULL && bp->IsBreakpoint()) 6853af9ea56SGreg Clayton return m_arch_ap->EnableHardwareBreakpoint(bp->Address(), bp->ByteSize()); 68630fdc8d8SChris Lattner return INVALID_NUB_HW_INDEX; 68730fdc8d8SChris Lattner } 68830fdc8d8SChris Lattner 68930fdc8d8SChris Lattner uint32_t 69030fdc8d8SChris Lattner MachThread::EnableHardwareWatchpoint (const DNBBreakpoint *wp) 69130fdc8d8SChris Lattner { 69230fdc8d8SChris Lattner if (wp != NULL && wp->IsWatchpoint()) 6933af9ea56SGreg Clayton return m_arch_ap->EnableHardwareWatchpoint(wp->Address(), wp->ByteSize(), wp->WatchpointRead(), wp->WatchpointWrite()); 69430fdc8d8SChris Lattner return INVALID_NUB_HW_INDEX; 69530fdc8d8SChris Lattner } 69630fdc8d8SChris Lattner 69730fdc8d8SChris Lattner bool 69830fdc8d8SChris Lattner MachThread::DisableHardwareBreakpoint (const DNBBreakpoint *bp) 69930fdc8d8SChris Lattner { 70030fdc8d8SChris Lattner if (bp != NULL && bp->IsHardware()) 7013af9ea56SGreg Clayton return m_arch_ap->DisableHardwareBreakpoint(bp->GetHardwareIndex()); 70230fdc8d8SChris Lattner return false; 70330fdc8d8SChris Lattner } 70430fdc8d8SChris Lattner 70530fdc8d8SChris Lattner bool 70630fdc8d8SChris Lattner MachThread::DisableHardwareWatchpoint (const DNBBreakpoint *wp) 70730fdc8d8SChris Lattner { 70830fdc8d8SChris Lattner if (wp != NULL && wp->IsHardware()) 7093af9ea56SGreg Clayton return m_arch_ap->DisableHardwareWatchpoint(wp->GetHardwareIndex()); 71030fdc8d8SChris Lattner return false; 71130fdc8d8SChris Lattner } 71230fdc8d8SChris Lattner 71330fdc8d8SChris Lattner bool 71430fdc8d8SChris Lattner MachThread::GetIdentifierInfo () 71530fdc8d8SChris Lattner { 71630fdc8d8SChris Lattner #ifdef THREAD_IDENTIFIER_INFO_COUNT 717f2c6ccf0SJim Ingham // Don't try to get the thread info once and cache it for the life of the thread. It changes over time, for instance 718f2c6ccf0SJim Ingham // if the thread name changes, then the thread_handle also changes... So you have to refetch it every time. 71930fdc8d8SChris Lattner mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; 720f2c6ccf0SJim Ingham kern_return_t kret = ::thread_info (ThreadID(), THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count); 721f2c6ccf0SJim Ingham return kret == KERN_SUCCESS; 72230fdc8d8SChris Lattner #endif 72330fdc8d8SChris Lattner 72430fdc8d8SChris Lattner return false; 72530fdc8d8SChris Lattner } 72630fdc8d8SChris Lattner 72730fdc8d8SChris Lattner 72830fdc8d8SChris Lattner const char * 72930fdc8d8SChris Lattner MachThread::GetName () 73030fdc8d8SChris Lattner { 73130fdc8d8SChris Lattner if (GetIdentifierInfo ()) 73230fdc8d8SChris Lattner { 73330fdc8d8SChris Lattner int len = ::proc_pidinfo (m_process->ProcessID(), PROC_PIDTHREADINFO, m_ident_info.thread_handle, &m_proc_threadinfo, sizeof (m_proc_threadinfo)); 73430fdc8d8SChris Lattner 73530fdc8d8SChris Lattner if (len && m_proc_threadinfo.pth_name[0]) 73630fdc8d8SChris Lattner return m_proc_threadinfo.pth_name; 73730fdc8d8SChris Lattner } 73830fdc8d8SChris Lattner return NULL; 73930fdc8d8SChris Lattner } 74030fdc8d8SChris Lattner 741