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), 33*b1e11121SJim Ingham m_suspend_count (0), 343af9ea56SGreg Clayton m_arch_ap (DNBArchProtocol::Create (this)), 35*b1e11121SJim Ingham m_reg_sets (m_arch_ap->GetRegisterSetInfo (&n_num_reg_sets)), 36*b1e11121SJim Ingham m_basic_info_valid (false) 3730fdc8d8SChris Lattner { 381b946bf6SGreg Clayton // Get the thread state so we know if a thread is in a state where we can't 391b946bf6SGreg Clayton // muck with it and also so we get the suspend count correct in case it was 401b946bf6SGreg Clayton // already suspended 41*b1e11121SJim Ingham GetBasicInfo(true); 4230fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::MachThread ( process = %p, tid = 0x%4.4x, seq_id = %u )", &m_process, m_tid, m_seq_id); 4330fdc8d8SChris Lattner } 4430fdc8d8SChris Lattner 4530fdc8d8SChris Lattner MachThread::~MachThread() 4630fdc8d8SChris Lattner { 4730fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::~MachThread() for tid = 0x%4.4x (%u)", m_tid, m_seq_id); 4830fdc8d8SChris Lattner } 4930fdc8d8SChris Lattner 5030fdc8d8SChris Lattner 5130fdc8d8SChris Lattner 52*b1e11121SJim Ingham int32_t 5330fdc8d8SChris Lattner MachThread::Suspend() 5430fdc8d8SChris Lattner { 5530fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 5630fdc8d8SChris Lattner if (ThreadIDIsValid(m_tid)) 5730fdc8d8SChris Lattner { 5830fdc8d8SChris Lattner DNBError err(::thread_suspend (m_tid), DNBError::MachKernel); 5930fdc8d8SChris Lattner if (err.Success()) 60*b1e11121SJim Ingham m_suspend_count++; 6130fdc8d8SChris Lattner if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 6230fdc8d8SChris Lattner err.LogThreaded("::thread_suspend (%4.4x)", m_tid); 6330fdc8d8SChris Lattner } 64*b1e11121SJim Ingham return m_suspend_count; 6530fdc8d8SChris Lattner } 6630fdc8d8SChris Lattner 67*b1e11121SJim Ingham int32_t 68*b1e11121SJim Ingham MachThread::ForceResume () 69*b1e11121SJim Ingham { 70*b1e11121SJim Ingham // We need to resume this all the way to 0. 71*b1e11121SJim Ingham DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 72*b1e11121SJim Ingham // Okay, now m_basic_info has the full suspend count. So I'll just 73*b1e11121SJim Ingham // keep decrementing the suspend count till that is zero, and at the same time 74*b1e11121SJim Ingham // decrement m_suspend_count. If that goes below zero, then the next time we 75*b1e11121SJim Ingham // call RestoreSuspendCount, we'll have to suspend it back to 0. 76*b1e11121SJim Ingham uint32_t num_suspends = m_basic_info.suspend_count + m_suspend_count; 77*b1e11121SJim Ingham DNBError err; 78*b1e11121SJim Ingham while (num_suspends > 0) 79*b1e11121SJim Ingham { 80*b1e11121SJim Ingham if (m_suspend_count < 0) 81*b1e11121SJim Ingham DNBLogThreadedIf(LOG_THREAD, "MachThread::%s ( ) (tid = %4.4x) setting suspend count negative = %d", __FUNCTION__, 82*b1e11121SJim Ingham m_tid, m_suspend_count); 83*b1e11121SJim Ingham err = ::thread_resume (m_tid); 84*b1e11121SJim Ingham if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 85*b1e11121SJim Ingham err.LogThreaded("ForceResume ::thread_resume (%4.4x)", m_tid); 86*b1e11121SJim Ingham if (err.Success()) 87*b1e11121SJim Ingham { 88*b1e11121SJim Ingham --m_suspend_count; 89*b1e11121SJim Ingham --num_suspends; 90*b1e11121SJim Ingham } 91*b1e11121SJim Ingham else 92*b1e11121SJim Ingham { 93*b1e11121SJim Ingham break; 94*b1e11121SJim Ingham } 95*b1e11121SJim Ingham } 96*b1e11121SJim Ingham return m_suspend_count; 97*b1e11121SJim Ingham 98*b1e11121SJim Ingham } 99*b1e11121SJim Ingham 100*b1e11121SJim Ingham int32_t 10130fdc8d8SChris Lattner MachThread::Resume() 10230fdc8d8SChris Lattner { 10330fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 10430fdc8d8SChris Lattner if (ThreadIDIsValid(m_tid)) 10530fdc8d8SChris Lattner { 1060dd2c627SGreg Clayton RestoreSuspendCount(); 10730fdc8d8SChris Lattner } 108*b1e11121SJim Ingham return m_suspend_count; 10930fdc8d8SChris Lattner } 11030fdc8d8SChris Lattner 11130fdc8d8SChris Lattner bool 11230fdc8d8SChris Lattner MachThread::RestoreSuspendCount() 11330fdc8d8SChris Lattner { 114*b1e11121SJim Ingham DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( ) (tid = %4.4x) our suspend count = %d", __FUNCTION__, 115*b1e11121SJim Ingham m_tid, m_suspend_count); 11630fdc8d8SChris Lattner DNBError err; 11730fdc8d8SChris Lattner if (ThreadIDIsValid(m_tid) == false) 11830fdc8d8SChris Lattner return false; 119*b1e11121SJim Ingham if (m_suspend_count > 0) 12030fdc8d8SChris Lattner { 121*b1e11121SJim Ingham while (m_suspend_count > 0) 12230fdc8d8SChris Lattner { 12330fdc8d8SChris Lattner err = ::thread_resume (m_tid); 12430fdc8d8SChris Lattner if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 125*b1e11121SJim Ingham err.LogThreaded("RestoreSuspendCount ::thread_resume (%4.4x)", m_tid); 12630fdc8d8SChris Lattner if (err.Success()) 127*b1e11121SJim Ingham --m_suspend_count; 1280dd2c627SGreg Clayton else 1290dd2c627SGreg Clayton { 130*b1e11121SJim Ingham if (GetBasicInfo(true)) 131*b1e11121SJim Ingham m_suspend_count = m_basic_info.suspend_count; 1320dd2c627SGreg Clayton else 133*b1e11121SJim Ingham m_suspend_count = 0; 1340dd2c627SGreg Clayton return false; // ??? 13530fdc8d8SChris Lattner } 13630fdc8d8SChris Lattner } 1370dd2c627SGreg Clayton } 138*b1e11121SJim Ingham else if (m_suspend_count < 0) 139*b1e11121SJim Ingham { 140*b1e11121SJim Ingham DNBLogThreadedIf(LOG_THREAD, "MachThread::%s ( ) (tid = %4.4x) negative suspend count = %d", __FUNCTION__, 141*b1e11121SJim Ingham m_tid, m_suspend_count); 142*b1e11121SJim Ingham while (m_suspend_count < 0) 143*b1e11121SJim Ingham { 144*b1e11121SJim Ingham err = ::thread_suspend (m_tid); 145*b1e11121SJim Ingham if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 146*b1e11121SJim Ingham err.LogThreaded("RestoreSuspendCount ::thread_suspend (%4.4x)", m_tid); 147*b1e11121SJim Ingham 148*b1e11121SJim Ingham if (err.Success()) 149*b1e11121SJim Ingham ++m_suspend_count; 150*b1e11121SJim Ingham else 151*b1e11121SJim Ingham { 152*b1e11121SJim Ingham if (GetBasicInfo(true)) 153*b1e11121SJim Ingham m_suspend_count = m_basic_info.suspend_count; 154*b1e11121SJim Ingham else 155*b1e11121SJim Ingham m_suspend_count = 0; 156*b1e11121SJim Ingham return false; // ??? 157*b1e11121SJim Ingham } 158*b1e11121SJim Ingham 159*b1e11121SJim Ingham } 160*b1e11121SJim Ingham } 1610dd2c627SGreg Clayton return true; 16230fdc8d8SChris Lattner } 16330fdc8d8SChris Lattner 16430fdc8d8SChris Lattner 16530fdc8d8SChris Lattner const char * 16630fdc8d8SChris Lattner MachThread::GetBasicInfoAsString () const 16730fdc8d8SChris Lattner { 16830fdc8d8SChris Lattner static char g_basic_info_string[1024]; 16930fdc8d8SChris Lattner struct thread_basic_info basicInfo; 17030fdc8d8SChris Lattner 17130fdc8d8SChris Lattner if (GetBasicInfo(m_tid, &basicInfo)) 17230fdc8d8SChris Lattner { 17330fdc8d8SChris Lattner 17430fdc8d8SChris Lattner // char run_state_str[32]; 17530fdc8d8SChris Lattner // size_t run_state_str_size = sizeof(run_state_str); 17630fdc8d8SChris Lattner // switch (basicInfo.run_state) 17730fdc8d8SChris Lattner // { 17830fdc8d8SChris Lattner // case TH_STATE_RUNNING: strncpy(run_state_str, "running", run_state_str_size); break; 17930fdc8d8SChris Lattner // case TH_STATE_STOPPED: strncpy(run_state_str, "stopped", run_state_str_size); break; 18030fdc8d8SChris Lattner // case TH_STATE_WAITING: strncpy(run_state_str, "waiting", run_state_str_size); break; 18130fdc8d8SChris Lattner // case TH_STATE_UNINTERRUPTIBLE: strncpy(run_state_str, "uninterruptible", run_state_str_size); break; 18230fdc8d8SChris Lattner // case TH_STATE_HALTED: strncpy(run_state_str, "halted", run_state_str_size); break; 18330fdc8d8SChris Lattner // default: snprintf(run_state_str, run_state_str_size, "%d", basicInfo.run_state); break; // ??? 18430fdc8d8SChris Lattner // } 18530fdc8d8SChris Lattner float user = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f; 18630fdc8d8SChris Lattner float system = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f; 18730fdc8d8SChris Lattner snprintf(g_basic_info_string, sizeof(g_basic_info_string), "Thread 0x%4.4x: user=%f system=%f cpu=%d sleep_time=%d", 18830fdc8d8SChris Lattner InferiorThreadID(), 18930fdc8d8SChris Lattner user, 19030fdc8d8SChris Lattner system, 19130fdc8d8SChris Lattner basicInfo.cpu_usage, 19230fdc8d8SChris Lattner basicInfo.sleep_time); 19330fdc8d8SChris Lattner 19430fdc8d8SChris Lattner return g_basic_info_string; 19530fdc8d8SChris Lattner } 19630fdc8d8SChris Lattner return NULL; 19730fdc8d8SChris Lattner } 19830fdc8d8SChris Lattner 19930fdc8d8SChris Lattner thread_t 20030fdc8d8SChris Lattner MachThread::InferiorThreadID() const 20130fdc8d8SChris Lattner { 20230fdc8d8SChris Lattner mach_msg_type_number_t i; 20330fdc8d8SChris Lattner mach_port_name_array_t names; 20430fdc8d8SChris Lattner mach_port_type_array_t types; 20530fdc8d8SChris Lattner mach_msg_type_number_t ncount, tcount; 20630fdc8d8SChris Lattner thread_t inferior_tid = INVALID_NUB_THREAD; 20730fdc8d8SChris Lattner task_t my_task = ::mach_task_self(); 20830fdc8d8SChris Lattner task_t task = m_process->Task().TaskPort(); 20930fdc8d8SChris Lattner 21030fdc8d8SChris Lattner kern_return_t kret = ::mach_port_names (task, &names, &ncount, &types, &tcount); 21130fdc8d8SChris Lattner if (kret == KERN_SUCCESS) 21230fdc8d8SChris Lattner { 21330fdc8d8SChris Lattner 21430fdc8d8SChris Lattner for (i = 0; i < ncount; i++) 21530fdc8d8SChris Lattner { 21630fdc8d8SChris Lattner mach_port_t my_name; 21730fdc8d8SChris Lattner mach_msg_type_name_t my_type; 21830fdc8d8SChris Lattner 21930fdc8d8SChris Lattner kret = ::mach_port_extract_right (task, names[i], MACH_MSG_TYPE_COPY_SEND, &my_name, &my_type); 22030fdc8d8SChris Lattner if (kret == KERN_SUCCESS) 22130fdc8d8SChris Lattner { 22230fdc8d8SChris Lattner ::mach_port_deallocate (my_task, my_name); 22330fdc8d8SChris Lattner if (my_name == m_tid) 22430fdc8d8SChris Lattner { 22530fdc8d8SChris Lattner inferior_tid = names[i]; 22630fdc8d8SChris Lattner break; 22730fdc8d8SChris Lattner } 22830fdc8d8SChris Lattner } 22930fdc8d8SChris Lattner } 23030fdc8d8SChris Lattner // Free up the names and types 23130fdc8d8SChris Lattner ::vm_deallocate (my_task, (vm_address_t) names, ncount * sizeof (mach_port_name_t)); 23230fdc8d8SChris Lattner ::vm_deallocate (my_task, (vm_address_t) types, tcount * sizeof (mach_port_type_t)); 23330fdc8d8SChris Lattner } 23430fdc8d8SChris Lattner return inferior_tid; 23530fdc8d8SChris Lattner } 23630fdc8d8SChris Lattner 23730fdc8d8SChris Lattner bool 2381b946bf6SGreg Clayton MachThread::IsUserReady() 2391b946bf6SGreg Clayton { 240*b1e11121SJim Ingham GetBasicInfo (false); 2411b946bf6SGreg Clayton 242*b1e11121SJim Ingham switch (m_basic_info.run_state) 2431b946bf6SGreg Clayton { 2441b946bf6SGreg Clayton default: 2451b946bf6SGreg Clayton case TH_STATE_UNINTERRUPTIBLE: 2461b946bf6SGreg Clayton break; 2471b946bf6SGreg Clayton 2481b946bf6SGreg Clayton case TH_STATE_RUNNING: 2491b946bf6SGreg Clayton case TH_STATE_STOPPED: 2501b946bf6SGreg Clayton case TH_STATE_WAITING: 2511b946bf6SGreg Clayton case TH_STATE_HALTED: 2521b946bf6SGreg Clayton return true; 2531b946bf6SGreg Clayton } 2541b946bf6SGreg Clayton return false; 2551b946bf6SGreg Clayton } 2561b946bf6SGreg Clayton 2571b946bf6SGreg Clayton struct thread_basic_info * 258*b1e11121SJim Ingham MachThread::GetBasicInfo (bool force) 2591b946bf6SGreg Clayton { 260*b1e11121SJim Ingham if (!force && m_basic_info_valid) 261*b1e11121SJim Ingham return &m_basic_info; 262*b1e11121SJim Ingham 263*b1e11121SJim Ingham if (MachThread::GetBasicInfo(m_tid, &m_basic_info)) 264*b1e11121SJim Ingham { 265*b1e11121SJim Ingham m_basic_info_valid = true; 266*b1e11121SJim Ingham return &m_basic_info; 267*b1e11121SJim Ingham } 2681b946bf6SGreg Clayton return NULL; 2691b946bf6SGreg Clayton } 2701b946bf6SGreg Clayton 2711b946bf6SGreg Clayton 2721b946bf6SGreg Clayton bool 27330fdc8d8SChris Lattner MachThread::GetBasicInfo(thread_t thread, struct thread_basic_info *basicInfoPtr) 27430fdc8d8SChris Lattner { 27530fdc8d8SChris Lattner if (ThreadIDIsValid(thread)) 27630fdc8d8SChris Lattner { 27730fdc8d8SChris Lattner unsigned int info_count = THREAD_BASIC_INFO_COUNT; 27830fdc8d8SChris Lattner kern_return_t err = ::thread_info (thread, THREAD_BASIC_INFO, (thread_info_t) basicInfoPtr, &info_count); 27930fdc8d8SChris Lattner if (err == KERN_SUCCESS) 28030fdc8d8SChris Lattner return true; 28130fdc8d8SChris Lattner } 28230fdc8d8SChris Lattner ::memset (basicInfoPtr, 0, sizeof (struct thread_basic_info)); 28330fdc8d8SChris Lattner return false; 28430fdc8d8SChris Lattner } 28530fdc8d8SChris Lattner 28630fdc8d8SChris Lattner 28730fdc8d8SChris Lattner bool 28830fdc8d8SChris Lattner MachThread::ThreadIDIsValid(thread_t thread) 28930fdc8d8SChris Lattner { 29030fdc8d8SChris Lattner return thread != THREAD_NULL; 29130fdc8d8SChris Lattner } 29230fdc8d8SChris Lattner 29330fdc8d8SChris Lattner bool 29430fdc8d8SChris Lattner MachThread::GetRegisterState(int flavor, bool force) 29530fdc8d8SChris Lattner { 2963af9ea56SGreg Clayton return m_arch_ap->GetRegisterState(flavor, force) == KERN_SUCCESS; 29730fdc8d8SChris Lattner } 29830fdc8d8SChris Lattner 29930fdc8d8SChris Lattner bool 30030fdc8d8SChris Lattner MachThread::SetRegisterState(int flavor) 30130fdc8d8SChris Lattner { 3023af9ea56SGreg Clayton return m_arch_ap->SetRegisterState(flavor) == KERN_SUCCESS; 30330fdc8d8SChris Lattner } 30430fdc8d8SChris Lattner 30530fdc8d8SChris Lattner uint64_t 30630fdc8d8SChris Lattner MachThread::GetPC(uint64_t failValue) 30730fdc8d8SChris Lattner { 30830fdc8d8SChris Lattner // Get program counter 3093af9ea56SGreg Clayton return m_arch_ap->GetPC(failValue); 31030fdc8d8SChris Lattner } 31130fdc8d8SChris Lattner 31230fdc8d8SChris Lattner bool 31330fdc8d8SChris Lattner MachThread::SetPC(uint64_t value) 31430fdc8d8SChris Lattner { 31530fdc8d8SChris Lattner // Set program counter 3163af9ea56SGreg Clayton return m_arch_ap->SetPC(value); 31730fdc8d8SChris Lattner } 31830fdc8d8SChris Lattner 31930fdc8d8SChris Lattner uint64_t 32030fdc8d8SChris Lattner MachThread::GetSP(uint64_t failValue) 32130fdc8d8SChris Lattner { 32230fdc8d8SChris Lattner // Get stack pointer 3233af9ea56SGreg Clayton return m_arch_ap->GetSP(failValue); 32430fdc8d8SChris Lattner } 32530fdc8d8SChris Lattner 32630fdc8d8SChris Lattner nub_process_t 32730fdc8d8SChris Lattner MachThread::ProcessID() const 32830fdc8d8SChris Lattner { 32930fdc8d8SChris Lattner if (m_process) 33030fdc8d8SChris Lattner return m_process->ProcessID(); 33130fdc8d8SChris Lattner return INVALID_NUB_PROCESS; 33230fdc8d8SChris Lattner } 33330fdc8d8SChris Lattner 33430fdc8d8SChris Lattner void 33530fdc8d8SChris Lattner MachThread::Dump(uint32_t index) 33630fdc8d8SChris Lattner { 33730fdc8d8SChris Lattner const char * thread_run_state = NULL; 33830fdc8d8SChris Lattner 339*b1e11121SJim Ingham switch (m_basic_info.run_state) 34030fdc8d8SChris Lattner { 34130fdc8d8SChris Lattner case TH_STATE_RUNNING: thread_run_state = "running"; break; // 1 thread is running normally 34230fdc8d8SChris Lattner case TH_STATE_STOPPED: thread_run_state = "stopped"; break; // 2 thread is stopped 34330fdc8d8SChris Lattner case TH_STATE_WAITING: thread_run_state = "waiting"; break; // 3 thread is waiting normally 34430fdc8d8SChris Lattner case TH_STATE_UNINTERRUPTIBLE: thread_run_state = "uninter"; break; // 4 thread is in an uninterruptible wait 34530fdc8d8SChris Lattner case TH_STATE_HALTED: thread_run_state = "halted "; break; // 5 thread is halted at a 34630fdc8d8SChris Lattner default: thread_run_state = "???"; break; 34730fdc8d8SChris Lattner } 34830fdc8d8SChris Lattner 349e2d4f0d7SGreg 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", 35030fdc8d8SChris Lattner index, 35130fdc8d8SChris Lattner m_seq_id, 352e2d4f0d7SGreg Clayton m_tid, 35330fdc8d8SChris Lattner GetPC(INVALID_NUB_ADDRESS), 35430fdc8d8SChris Lattner GetSP(INVALID_NUB_ADDRESS), 35530fdc8d8SChris Lattner m_breakID, 356*b1e11121SJim Ingham m_basic_info.user_time.seconds, m_basic_info.user_time.microseconds, 357*b1e11121SJim Ingham m_basic_info.system_time.seconds, m_basic_info.system_time.microseconds, 358*b1e11121SJim Ingham m_basic_info.cpu_usage, 359*b1e11121SJim Ingham m_basic_info.policy, 360*b1e11121SJim Ingham m_basic_info.run_state, 36130fdc8d8SChris Lattner thread_run_state, 362*b1e11121SJim Ingham m_basic_info.flags, 363*b1e11121SJim Ingham m_basic_info.suspend_count, m_suspend_count, 364*b1e11121SJim Ingham m_basic_info.sleep_time); 36530fdc8d8SChris Lattner //DumpRegisterState(0); 36630fdc8d8SChris Lattner } 36730fdc8d8SChris Lattner 36830fdc8d8SChris Lattner void 36930fdc8d8SChris Lattner MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action) 37030fdc8d8SChris Lattner { 37130fdc8d8SChris Lattner if (thread_action->addr != INVALID_NUB_ADDRESS) 37230fdc8d8SChris Lattner SetPC (thread_action->addr); 373*b1e11121SJim Ingham // DidStop restores the state to it's natural state, and sets 374*b1e11121SJim Ingham // m_suspend_count to 0 in the process, and then here is the only 375*b1e11121SJim Ingham // place that we should be suspending or resuming (and thus changing 376*b1e11121SJim Ingham // that state. 377*b1e11121SJim Ingham assert (m_suspend_count == 0); 37830fdc8d8SChris Lattner SetState (thread_action->state); 37930fdc8d8SChris Lattner switch (thread_action->state) 38030fdc8d8SChris Lattner { 38130fdc8d8SChris Lattner case eStateStopped: 38230fdc8d8SChris Lattner case eStateSuspended: 38330fdc8d8SChris Lattner Suspend(); 38430fdc8d8SChris Lattner break; 38530fdc8d8SChris Lattner 38630fdc8d8SChris Lattner case eStateRunning: 38730fdc8d8SChris Lattner Resume(); 38830fdc8d8SChris Lattner break; 389*b1e11121SJim Ingham case eStateStepping: 390*b1e11121SJim Ingham ForceResume(); 391*b1e11121SJim Ingham break; 39230fdc8d8SChris Lattner } 3933af9ea56SGreg Clayton m_arch_ap->ThreadWillResume(); 39430fdc8d8SChris Lattner m_stop_exception.Clear(); 39530fdc8d8SChris Lattner } 39630fdc8d8SChris Lattner 397c4e411ffSGreg Clayton nub_break_t 398c4e411ffSGreg Clayton MachThread::CurrentBreakpoint() 399c4e411ffSGreg Clayton { 400c4e411ffSGreg Clayton return m_process->Breakpoints().FindIDByAddress(GetPC()); 401c4e411ffSGreg Clayton } 402c4e411ffSGreg Clayton 40330fdc8d8SChris Lattner bool 40430fdc8d8SChris Lattner MachThread::ShouldStop(bool &step_more) 40530fdc8d8SChris Lattner { 40630fdc8d8SChris Lattner // See if this thread is at a breakpoint? 40730fdc8d8SChris Lattner nub_break_t breakID = CurrentBreakpoint(); 40830fdc8d8SChris Lattner 40930fdc8d8SChris Lattner if (NUB_BREAK_ID_IS_VALID(breakID)) 41030fdc8d8SChris Lattner { 41130fdc8d8SChris Lattner // This thread is sitting at a breakpoint, ask the breakpoint 41230fdc8d8SChris Lattner // if we should be stopping here. 41330fdc8d8SChris Lattner if (Process()->Breakpoints().ShouldStop(ProcessID(), ThreadID(), breakID)) 41430fdc8d8SChris Lattner return true; 41530fdc8d8SChris Lattner else 41630fdc8d8SChris Lattner { 41730fdc8d8SChris Lattner // The breakpoint said we shouldn't stop, but we may have gotten 41830fdc8d8SChris Lattner // a signal or the user may have requested to stop in some other 41930fdc8d8SChris Lattner // way. Stop if we have a valid exception (this thread won't if 42030fdc8d8SChris Lattner // another thread was the reason this process stopped) and that 42130fdc8d8SChris Lattner // exception, is NOT a breakpoint exception (a common case would 42230fdc8d8SChris Lattner // be a SIGINT signal). 42330fdc8d8SChris Lattner if (GetStopException().IsValid() && !GetStopException().IsBreakpoint()) 42430fdc8d8SChris Lattner return true; 42530fdc8d8SChris Lattner } 42630fdc8d8SChris Lattner } 42730fdc8d8SChris Lattner else 42830fdc8d8SChris Lattner { 4293af9ea56SGreg Clayton if (m_arch_ap->StepNotComplete()) 43030fdc8d8SChris Lattner { 43130fdc8d8SChris Lattner step_more = true; 43230fdc8d8SChris Lattner return false; 43330fdc8d8SChris Lattner } 43430fdc8d8SChris Lattner // The thread state is used to let us know what the thread was 43530fdc8d8SChris Lattner // trying to do. MachThread::ThreadWillResume() will set the 43630fdc8d8SChris Lattner // thread state to various values depending if the thread was 43730fdc8d8SChris Lattner // the current thread and if it was to be single stepped, or 43830fdc8d8SChris Lattner // resumed. 43930fdc8d8SChris Lattner if (GetState() == eStateRunning) 44030fdc8d8SChris Lattner { 44130fdc8d8SChris Lattner // If our state is running, then we should continue as we are in 44230fdc8d8SChris Lattner // the process of stepping over a breakpoint. 44330fdc8d8SChris Lattner return false; 44430fdc8d8SChris Lattner } 44530fdc8d8SChris Lattner else 44630fdc8d8SChris Lattner { 44730fdc8d8SChris Lattner // Stop if we have any kind of valid exception for this 44830fdc8d8SChris Lattner // thread. 44930fdc8d8SChris Lattner if (GetStopException().IsValid()) 45030fdc8d8SChris Lattner return true; 45130fdc8d8SChris Lattner } 45230fdc8d8SChris Lattner } 45330fdc8d8SChris Lattner return false; 45430fdc8d8SChris Lattner } 45530fdc8d8SChris Lattner bool 45630fdc8d8SChris Lattner MachThread::IsStepping() 45730fdc8d8SChris Lattner { 458c4e411ffSGreg Clayton #if ENABLE_AUTO_STEPPING_OVER_BP 45930fdc8d8SChris Lattner // Return true if this thread is currently being stepped. 46030fdc8d8SChris Lattner // MachThread::ThreadWillResume currently determines this by looking if we 46130fdc8d8SChris Lattner // have been asked to single step, or if we are at a breakpoint instruction 46230fdc8d8SChris Lattner // and have been asked to resume. In the latter case we need to disable the 46330fdc8d8SChris Lattner // breakpoint we are at, single step, re-enable and continue. 46430fdc8d8SChris Lattner nub_state_t state = GetState(); 465c4e411ffSGreg Clayton return ((state == eStateStepping) || 466c4e411ffSGreg Clayton (state == eStateRunning && NUB_BREAK_ID_IS_VALID(CurrentBreakpoint()))); 467c4e411ffSGreg Clayton #else 468c4e411ffSGreg Clayton return GetState() == eStateStepping; 469c4e411ffSGreg Clayton #endif 47030fdc8d8SChris Lattner } 47130fdc8d8SChris Lattner 47230fdc8d8SChris Lattner 47330fdc8d8SChris Lattner bool 47430fdc8d8SChris Lattner MachThread::ThreadDidStop() 47530fdc8d8SChris Lattner { 47630fdc8d8SChris Lattner // This thread has existed prior to resuming under debug nub control, 47730fdc8d8SChris Lattner // and has just been stopped. Do any cleanup that needs to be done 47830fdc8d8SChris Lattner // after running. 47930fdc8d8SChris Lattner 48030fdc8d8SChris Lattner // The thread state and breakpoint will still have the same values 48130fdc8d8SChris Lattner // as they had prior to resuming the thread, so it makes it easy to check 48230fdc8d8SChris Lattner // if we were trying to step a thread, or we tried to resume while being 48330fdc8d8SChris Lattner // at a breakpoint. 48430fdc8d8SChris Lattner 48530fdc8d8SChris Lattner // When this method gets called, the process state is still in the 48630fdc8d8SChris Lattner // state it was in while running so we can act accordingly. 4873af9ea56SGreg Clayton m_arch_ap->ThreadDidStop(); 48830fdc8d8SChris Lattner 48930fdc8d8SChris Lattner 49030fdc8d8SChris Lattner // We may have suspended this thread so the primary thread could step 49130fdc8d8SChris Lattner // without worrying about race conditions, so lets restore our suspend 49230fdc8d8SChris Lattner // count. 49330fdc8d8SChris Lattner RestoreSuspendCount(); 49430fdc8d8SChris Lattner 49530fdc8d8SChris Lattner // Update the basic information for a thread 496*b1e11121SJim Ingham GetBasicInfo (true); 49730fdc8d8SChris Lattner 498c4e411ffSGreg Clayton #if ENABLE_AUTO_STEPPING_OVER_BP 49930fdc8d8SChris Lattner // See if we were at a breakpoint when we last resumed that we disabled, 50030fdc8d8SChris Lattner // re-enable it. 50130fdc8d8SChris Lattner nub_break_t breakID = CurrentBreakpoint(); 50230fdc8d8SChris Lattner 50330fdc8d8SChris Lattner if (NUB_BREAK_ID_IS_VALID(breakID)) 50430fdc8d8SChris Lattner { 50530fdc8d8SChris Lattner m_process->EnableBreakpoint(breakID); 506*b1e11121SJim Ingham if (m_basic_info.suspend_count > 0) 50730fdc8d8SChris Lattner { 50830fdc8d8SChris Lattner SetState(eStateSuspended); 50930fdc8d8SChris Lattner } 51030fdc8d8SChris Lattner else 51130fdc8d8SChris Lattner { 51230fdc8d8SChris Lattner // If we last were at a breakpoint and we single stepped, our state 51330fdc8d8SChris Lattner // will be "running" to indicate we need to continue after stepping 51430fdc8d8SChris Lattner // over the breakpoint instruction. If we step over a breakpoint 51530fdc8d8SChris Lattner // instruction, we need to stop. 51630fdc8d8SChris Lattner if (GetState() == eStateRunning) 51730fdc8d8SChris Lattner { 51830fdc8d8SChris Lattner // Leave state set to running so we will continue automatically 51930fdc8d8SChris Lattner // from this breakpoint 52030fdc8d8SChris Lattner } 52130fdc8d8SChris Lattner else 52230fdc8d8SChris Lattner { 52330fdc8d8SChris Lattner SetState(eStateStopped); 52430fdc8d8SChris Lattner } 52530fdc8d8SChris Lattner } 52630fdc8d8SChris Lattner } 52730fdc8d8SChris Lattner else 52830fdc8d8SChris Lattner { 529*b1e11121SJim Ingham if (m_basic_info.suspend_count > 0) 53030fdc8d8SChris Lattner { 53130fdc8d8SChris Lattner SetState(eStateSuspended); 53230fdc8d8SChris Lattner } 53330fdc8d8SChris Lattner else 53430fdc8d8SChris Lattner { 53530fdc8d8SChris Lattner SetState(eStateStopped); 53630fdc8d8SChris Lattner } 53730fdc8d8SChris Lattner } 538c4e411ffSGreg Clayton #else 539*b1e11121SJim Ingham if (m_basic_info.suspend_count > 0) 540c4e411ffSGreg Clayton SetState(eStateSuspended); 541c4e411ffSGreg Clayton else 542c4e411ffSGreg Clayton SetState(eStateStopped); 543c4e411ffSGreg Clayton #endif 54430fdc8d8SChris Lattner return true; 54530fdc8d8SChris Lattner } 54630fdc8d8SChris Lattner 54730fdc8d8SChris Lattner bool 54830fdc8d8SChris Lattner MachThread::NotifyException(MachException::Data& exc) 54930fdc8d8SChris Lattner { 55030fdc8d8SChris Lattner if (m_stop_exception.IsValid()) 55130fdc8d8SChris Lattner { 55230fdc8d8SChris Lattner // We may have more than one exception for a thread, but we need to 55330fdc8d8SChris Lattner // only remember the one that we will say is the reason we stopped. 55430fdc8d8SChris Lattner // We may have been single stepping and also gotten a signal exception, 55530fdc8d8SChris Lattner // so just remember the most pertinent one. 55630fdc8d8SChris Lattner if (m_stop_exception.IsBreakpoint()) 55730fdc8d8SChris Lattner m_stop_exception = exc; 55830fdc8d8SChris Lattner } 55930fdc8d8SChris Lattner else 56030fdc8d8SChris Lattner { 56130fdc8d8SChris Lattner m_stop_exception = exc; 56230fdc8d8SChris Lattner } 5633af9ea56SGreg Clayton bool handled = m_arch_ap->NotifyException(exc); 56430fdc8d8SChris Lattner if (!handled) 56530fdc8d8SChris Lattner { 56630fdc8d8SChris Lattner handled = true; 567c4e411ffSGreg Clayton // switch (exc.exc_type) 568c4e411ffSGreg Clayton // { 569c4e411ffSGreg Clayton // case EXC_BAD_ACCESS: 570c4e411ffSGreg Clayton // break; 571c4e411ffSGreg Clayton // case EXC_BAD_INSTRUCTION: 572c4e411ffSGreg Clayton // break; 573c4e411ffSGreg Clayton // case EXC_ARITHMETIC: 574c4e411ffSGreg Clayton // break; 575c4e411ffSGreg Clayton // case EXC_EMULATION: 576c4e411ffSGreg Clayton // break; 577c4e411ffSGreg Clayton // case EXC_SOFTWARE: 578c4e411ffSGreg Clayton // break; 579c4e411ffSGreg Clayton // case EXC_BREAKPOINT: 580c4e411ffSGreg Clayton // break; 581c4e411ffSGreg Clayton // case EXC_SYSCALL: 582c4e411ffSGreg Clayton // break; 583c4e411ffSGreg Clayton // case EXC_MACH_SYSCALL: 584c4e411ffSGreg Clayton // break; 585c4e411ffSGreg Clayton // case EXC_RPC_ALERT: 586c4e411ffSGreg Clayton // break; 587c4e411ffSGreg Clayton // } 58830fdc8d8SChris Lattner } 58930fdc8d8SChris Lattner return handled; 59030fdc8d8SChris Lattner } 59130fdc8d8SChris Lattner 59230fdc8d8SChris Lattner 59330fdc8d8SChris Lattner nub_state_t 59430fdc8d8SChris Lattner MachThread::GetState() 59530fdc8d8SChris Lattner { 59630fdc8d8SChris Lattner // If any other threads access this we will need a mutex for it 59730fdc8d8SChris Lattner PTHREAD_MUTEX_LOCKER (locker, m_state_mutex); 59830fdc8d8SChris Lattner return m_state; 59930fdc8d8SChris Lattner } 60030fdc8d8SChris Lattner 60130fdc8d8SChris Lattner void 60230fdc8d8SChris Lattner MachThread::SetState(nub_state_t state) 60330fdc8d8SChris Lattner { 60430fdc8d8SChris Lattner PTHREAD_MUTEX_LOCKER (locker, m_state_mutex); 60530fdc8d8SChris Lattner m_state = state; 60630fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD, "MachThread::SetState ( %s ) for tid = 0x%4.4x", DNBStateAsString(state), m_tid); 60730fdc8d8SChris Lattner } 60830fdc8d8SChris Lattner 60930fdc8d8SChris Lattner uint32_t 61030fdc8d8SChris Lattner MachThread::GetNumRegistersInSet(int regSet) const 61130fdc8d8SChris Lattner { 6123af9ea56SGreg Clayton if (regSet < n_num_reg_sets) 6133af9ea56SGreg Clayton return m_reg_sets[regSet].num_registers; 61430fdc8d8SChris Lattner return 0; 61530fdc8d8SChris Lattner } 61630fdc8d8SChris Lattner 61730fdc8d8SChris Lattner const char * 61830fdc8d8SChris Lattner MachThread::GetRegisterSetName(int regSet) const 61930fdc8d8SChris Lattner { 6203af9ea56SGreg Clayton if (regSet < n_num_reg_sets) 6213af9ea56SGreg Clayton return m_reg_sets[regSet].name; 62230fdc8d8SChris Lattner return NULL; 62330fdc8d8SChris Lattner } 62430fdc8d8SChris Lattner 62530fdc8d8SChris Lattner const DNBRegisterInfo * 62630fdc8d8SChris Lattner MachThread::GetRegisterInfo(int regSet, int regIndex) const 62730fdc8d8SChris Lattner { 6283af9ea56SGreg Clayton if (regSet < n_num_reg_sets) 6293af9ea56SGreg Clayton if (regIndex < m_reg_sets[regSet].num_registers) 6303af9ea56SGreg Clayton return &m_reg_sets[regSet].registers[regIndex]; 63130fdc8d8SChris Lattner return NULL; 63230fdc8d8SChris Lattner } 63330fdc8d8SChris Lattner void 63430fdc8d8SChris Lattner MachThread::DumpRegisterState(int regSet) 63530fdc8d8SChris Lattner { 63630fdc8d8SChris Lattner if (regSet == REGISTER_SET_ALL) 63730fdc8d8SChris Lattner { 6383af9ea56SGreg Clayton for (regSet = 1; regSet < n_num_reg_sets; regSet++) 63930fdc8d8SChris Lattner DumpRegisterState(regSet); 64030fdc8d8SChris Lattner } 64130fdc8d8SChris Lattner else 64230fdc8d8SChris Lattner { 6433af9ea56SGreg Clayton if (m_arch_ap->RegisterSetStateIsValid(regSet)) 64430fdc8d8SChris Lattner { 64530fdc8d8SChris Lattner const size_t numRegisters = GetNumRegistersInSet(regSet); 64630fdc8d8SChris Lattner size_t regIndex = 0; 64730fdc8d8SChris Lattner DNBRegisterValueClass reg; 64830fdc8d8SChris Lattner for (regIndex = 0; regIndex < numRegisters; ++regIndex) 64930fdc8d8SChris Lattner { 6503af9ea56SGreg Clayton if (m_arch_ap->GetRegisterValue(regSet, regIndex, ®)) 65130fdc8d8SChris Lattner { 65230fdc8d8SChris Lattner reg.Dump(NULL, NULL); 65330fdc8d8SChris Lattner } 65430fdc8d8SChris Lattner } 65530fdc8d8SChris Lattner } 65630fdc8d8SChris Lattner else 65730fdc8d8SChris Lattner { 65830fdc8d8SChris Lattner DNBLog("%s: registers are not currently valid.", GetRegisterSetName(regSet)); 65930fdc8d8SChris Lattner } 66030fdc8d8SChris Lattner } 66130fdc8d8SChris Lattner } 66230fdc8d8SChris Lattner 66330fdc8d8SChris Lattner const DNBRegisterSetInfo * 66430fdc8d8SChris Lattner MachThread::GetRegisterSetInfo(nub_size_t *num_reg_sets ) const 66530fdc8d8SChris Lattner { 6663af9ea56SGreg Clayton *num_reg_sets = n_num_reg_sets; 6673af9ea56SGreg Clayton return &m_reg_sets[0]; 66830fdc8d8SChris Lattner } 66930fdc8d8SChris Lattner 67030fdc8d8SChris Lattner bool 67130fdc8d8SChris Lattner MachThread::GetRegisterValue ( uint32_t set, uint32_t reg, DNBRegisterValue *value ) 67230fdc8d8SChris Lattner { 6733af9ea56SGreg Clayton return m_arch_ap->GetRegisterValue(set, reg, value); 67430fdc8d8SChris Lattner } 67530fdc8d8SChris Lattner 67630fdc8d8SChris Lattner bool 67730fdc8d8SChris Lattner MachThread::SetRegisterValue ( uint32_t set, uint32_t reg, const DNBRegisterValue *value ) 67830fdc8d8SChris Lattner { 6793af9ea56SGreg Clayton return m_arch_ap->SetRegisterValue(set, reg, value); 68030fdc8d8SChris Lattner } 68130fdc8d8SChris Lattner 68230fdc8d8SChris Lattner nub_size_t 68330fdc8d8SChris Lattner MachThread::GetRegisterContext (void *buf, nub_size_t buf_len) 68430fdc8d8SChris Lattner { 6853af9ea56SGreg Clayton return m_arch_ap->GetRegisterContext(buf, buf_len); 68630fdc8d8SChris Lattner } 68730fdc8d8SChris Lattner 68830fdc8d8SChris Lattner nub_size_t 68930fdc8d8SChris Lattner MachThread::SetRegisterContext (const void *buf, nub_size_t buf_len) 69030fdc8d8SChris Lattner { 6913af9ea56SGreg Clayton return m_arch_ap->SetRegisterContext(buf, buf_len); 69230fdc8d8SChris Lattner } 69330fdc8d8SChris Lattner 69430fdc8d8SChris Lattner uint32_t 69530fdc8d8SChris Lattner MachThread::EnableHardwareBreakpoint (const DNBBreakpoint *bp) 69630fdc8d8SChris Lattner { 69730fdc8d8SChris Lattner if (bp != NULL && bp->IsBreakpoint()) 6983af9ea56SGreg Clayton return m_arch_ap->EnableHardwareBreakpoint(bp->Address(), bp->ByteSize()); 69930fdc8d8SChris Lattner return INVALID_NUB_HW_INDEX; 70030fdc8d8SChris Lattner } 70130fdc8d8SChris Lattner 70230fdc8d8SChris Lattner uint32_t 70330fdc8d8SChris Lattner MachThread::EnableHardwareWatchpoint (const DNBBreakpoint *wp) 70430fdc8d8SChris Lattner { 70530fdc8d8SChris Lattner if (wp != NULL && wp->IsWatchpoint()) 7063af9ea56SGreg Clayton return m_arch_ap->EnableHardwareWatchpoint(wp->Address(), wp->ByteSize(), wp->WatchpointRead(), wp->WatchpointWrite()); 70730fdc8d8SChris Lattner return INVALID_NUB_HW_INDEX; 70830fdc8d8SChris Lattner } 70930fdc8d8SChris Lattner 71030fdc8d8SChris Lattner bool 71130fdc8d8SChris Lattner MachThread::DisableHardwareBreakpoint (const DNBBreakpoint *bp) 71230fdc8d8SChris Lattner { 71330fdc8d8SChris Lattner if (bp != NULL && bp->IsHardware()) 7143af9ea56SGreg Clayton return m_arch_ap->DisableHardwareBreakpoint(bp->GetHardwareIndex()); 71530fdc8d8SChris Lattner return false; 71630fdc8d8SChris Lattner } 71730fdc8d8SChris Lattner 71830fdc8d8SChris Lattner bool 71930fdc8d8SChris Lattner MachThread::DisableHardwareWatchpoint (const DNBBreakpoint *wp) 72030fdc8d8SChris Lattner { 72130fdc8d8SChris Lattner if (wp != NULL && wp->IsHardware()) 7223af9ea56SGreg Clayton return m_arch_ap->DisableHardwareWatchpoint(wp->GetHardwareIndex()); 72330fdc8d8SChris Lattner return false; 72430fdc8d8SChris Lattner } 72530fdc8d8SChris Lattner 72630fdc8d8SChris Lattner bool 72730fdc8d8SChris Lattner MachThread::GetIdentifierInfo () 72830fdc8d8SChris Lattner { 72930fdc8d8SChris Lattner #ifdef THREAD_IDENTIFIER_INFO_COUNT 73030fdc8d8SChris Lattner if (m_ident_info.thread_id == 0) 73130fdc8d8SChris Lattner { 73230fdc8d8SChris Lattner mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; 73330fdc8d8SChris Lattner return ::thread_info (ThreadID(), THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count) == KERN_SUCCESS; 73430fdc8d8SChris Lattner } 73530fdc8d8SChris Lattner #endif 73630fdc8d8SChris Lattner 73730fdc8d8SChris Lattner return false; 73830fdc8d8SChris Lattner } 73930fdc8d8SChris Lattner 74030fdc8d8SChris Lattner 74130fdc8d8SChris Lattner const char * 74230fdc8d8SChris Lattner MachThread::GetName () 74330fdc8d8SChris Lattner { 74430fdc8d8SChris Lattner if (GetIdentifierInfo ()) 74530fdc8d8SChris Lattner { 74630fdc8d8SChris Lattner int len = ::proc_pidinfo (m_process->ProcessID(), PROC_PIDTHREADINFO, m_ident_info.thread_handle, &m_proc_threadinfo, sizeof (m_proc_threadinfo)); 74730fdc8d8SChris Lattner 74830fdc8d8SChris Lattner if (len && m_proc_threadinfo.pth_name[0]) 74930fdc8d8SChris Lattner return m_proc_threadinfo.pth_name; 75030fdc8d8SChris Lattner } 75130fdc8d8SChris Lattner return NULL; 75230fdc8d8SChris Lattner } 75330fdc8d8SChris Lattner 75430fdc8d8SChris Lattner 75530fdc8d8SChris Lattner // 75630fdc8d8SChris Lattner //const char * 75730fdc8d8SChris Lattner //MachThread::GetDispatchQueueName() 75830fdc8d8SChris Lattner //{ 75930fdc8d8SChris Lattner // if (GetIdentifierInfo ()) 76030fdc8d8SChris Lattner // { 76130fdc8d8SChris Lattner // if (m_ident_info.dispatch_qaddr == 0) 76230fdc8d8SChris Lattner // return NULL; 76330fdc8d8SChris Lattner // 76430fdc8d8SChris Lattner // uint8_t memory_buffer[8]; 76530fdc8d8SChris Lattner // DNBDataRef data(memory_buffer, sizeof(memory_buffer), false); 76630fdc8d8SChris Lattner // ModuleSP module_sp(GetProcess()->GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib"))); 76730fdc8d8SChris Lattner // if (module_sp.get() == NULL) 76830fdc8d8SChris Lattner // return NULL; 76930fdc8d8SChris Lattner // 77030fdc8d8SChris Lattner // lldb::addr_t dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS; 77130fdc8d8SChris Lattner // const Symbol *dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (ConstString("dispatch_queue_offsets"), eSymbolTypeData); 77230fdc8d8SChris Lattner // if (dispatch_queue_offsets_symbol) 77330fdc8d8SChris Lattner // dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetValue().GetLoadAddress(GetProcess()); 77430fdc8d8SChris Lattner // 77530fdc8d8SChris Lattner // if (dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS) 77630fdc8d8SChris Lattner // return NULL; 77730fdc8d8SChris Lattner // 77830fdc8d8SChris Lattner // // Excerpt from src/queue_private.h 77930fdc8d8SChris Lattner // struct dispatch_queue_offsets_s 78030fdc8d8SChris Lattner // { 78130fdc8d8SChris Lattner // uint16_t dqo_version; 78230fdc8d8SChris Lattner // uint16_t dqo_label; 78330fdc8d8SChris Lattner // uint16_t dqo_label_size; 78430fdc8d8SChris Lattner // } dispatch_queue_offsets; 78530fdc8d8SChris Lattner // 78630fdc8d8SChris Lattner // 78730fdc8d8SChris Lattner // if (GetProcess()->ReadMemory (dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets)) == sizeof(dispatch_queue_offsets)) 78830fdc8d8SChris Lattner // { 78930fdc8d8SChris Lattner // uint32_t data_offset = 0; 79030fdc8d8SChris Lattner // if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t))) 79130fdc8d8SChris Lattner // { 79230fdc8d8SChris Lattner // if (GetProcess()->ReadMemory (m_ident_info.dispatch_qaddr, &memory_buffer, data.GetAddressByteSize()) == data.GetAddressByteSize()) 79330fdc8d8SChris Lattner // { 79430fdc8d8SChris Lattner // data_offset = 0; 79530fdc8d8SChris Lattner // lldb::addr_t queue_addr = data.GetAddress(&data_offset); 79630fdc8d8SChris Lattner // lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label; 79730fdc8d8SChris Lattner // const size_t chunk_size = 32; 79830fdc8d8SChris Lattner // uint32_t label_pos = 0; 79930fdc8d8SChris Lattner // m_dispatch_queue_name.resize(chunk_size, '\0'); 80030fdc8d8SChris Lattner // while (1) 80130fdc8d8SChris Lattner // { 80230fdc8d8SChris Lattner // size_t bytes_read = GetProcess()->ReadMemory (label_addr + label_pos, &m_dispatch_queue_name[label_pos], chunk_size); 80330fdc8d8SChris Lattner // 80430fdc8d8SChris Lattner // if (bytes_read <= 0) 80530fdc8d8SChris Lattner // break; 80630fdc8d8SChris Lattner // 80730fdc8d8SChris Lattner // if (m_dispatch_queue_name.find('\0', label_pos) != std::string::npos) 80830fdc8d8SChris Lattner // break; 80930fdc8d8SChris Lattner // label_pos += bytes_read; 81030fdc8d8SChris Lattner // } 81130fdc8d8SChris Lattner // m_dispatch_queue_name.erase(m_dispatch_queue_name.find('\0')); 81230fdc8d8SChris Lattner // } 81330fdc8d8SChris Lattner // } 81430fdc8d8SChris Lattner // } 81530fdc8d8SChris Lattner // } 81630fdc8d8SChris Lattner // 81730fdc8d8SChris Lattner // if (m_dispatch_queue_name.empty()) 81830fdc8d8SChris Lattner // return NULL; 81930fdc8d8SChris Lattner // return m_dispatch_queue_name.c_str(); 82030fdc8d8SChris Lattner //} 821