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), 3330fdc8d8SChris Lattner m_suspendCount (0), 3430fdc8d8SChris Lattner m_arch (this), 3530fdc8d8SChris Lattner m_regSets () 3630fdc8d8SChris Lattner { 3730fdc8d8SChris Lattner nub_size_t num_reg_sets = 0; 3830fdc8d8SChris Lattner const DNBRegisterSetInfo *regSetInfo = m_arch.GetRegisterSetInfo(&num_reg_sets); 3930fdc8d8SChris Lattner if (num_reg_sets > 0) 4030fdc8d8SChris Lattner m_regSets.assign(regSetInfo, regSetInfo + num_reg_sets); 4130fdc8d8SChris Lattner 421b946bf6SGreg Clayton // Get the thread state so we know if a thread is in a state where we can't 431b946bf6SGreg Clayton // muck with it and also so we get the suspend count correct in case it was 441b946bf6SGreg Clayton // already suspended 451b946bf6SGreg Clayton GetBasicInfo(); 4630fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::MachThread ( process = %p, tid = 0x%4.4x, seq_id = %u )", &m_process, m_tid, m_seq_id); 4730fdc8d8SChris Lattner } 4830fdc8d8SChris Lattner 4930fdc8d8SChris Lattner MachThread::~MachThread() 5030fdc8d8SChris Lattner { 5130fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::~MachThread() for tid = 0x%4.4x (%u)", m_tid, m_seq_id); 5230fdc8d8SChris Lattner } 5330fdc8d8SChris Lattner 5430fdc8d8SChris Lattner 5530fdc8d8SChris Lattner 5630fdc8d8SChris Lattner uint32_t 5730fdc8d8SChris Lattner MachThread::Suspend() 5830fdc8d8SChris Lattner { 5930fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 6030fdc8d8SChris Lattner if (ThreadIDIsValid(m_tid)) 6130fdc8d8SChris Lattner { 6230fdc8d8SChris Lattner DNBError err(::thread_suspend (m_tid), DNBError::MachKernel); 6330fdc8d8SChris Lattner if (err.Success()) 6430fdc8d8SChris Lattner m_suspendCount++; 6530fdc8d8SChris Lattner if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 6630fdc8d8SChris Lattner err.LogThreaded("::thread_suspend (%4.4x)", m_tid); 6730fdc8d8SChris Lattner } 6830fdc8d8SChris Lattner return SuspendCount(); 6930fdc8d8SChris Lattner } 7030fdc8d8SChris Lattner 7130fdc8d8SChris Lattner uint32_t 7230fdc8d8SChris Lattner MachThread::Resume() 7330fdc8d8SChris Lattner { 7430fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 7530fdc8d8SChris Lattner if (ThreadIDIsValid(m_tid)) 7630fdc8d8SChris Lattner { 77*0dd2c627SGreg Clayton RestoreSuspendCount(); 7830fdc8d8SChris Lattner } 7930fdc8d8SChris Lattner return SuspendCount(); 8030fdc8d8SChris Lattner } 8130fdc8d8SChris Lattner 8230fdc8d8SChris Lattner bool 8330fdc8d8SChris Lattner MachThread::RestoreSuspendCount() 8430fdc8d8SChris Lattner { 8530fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 8630fdc8d8SChris Lattner DNBError err; 8730fdc8d8SChris Lattner if (ThreadIDIsValid(m_tid) == false) 8830fdc8d8SChris Lattner return false; 89*0dd2c627SGreg Clayton if (m_suspendCount > 0) 9030fdc8d8SChris Lattner { 91*0dd2c627SGreg Clayton while (m_suspendCount > 0) 9230fdc8d8SChris Lattner { 9330fdc8d8SChris Lattner err = ::thread_resume (m_tid); 9430fdc8d8SChris Lattner if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 9530fdc8d8SChris Lattner err.LogThreaded("::thread_resume (%4.4x)", m_tid); 9630fdc8d8SChris Lattner if (err.Success()) 9730fdc8d8SChris Lattner --m_suspendCount; 98*0dd2c627SGreg Clayton else 99*0dd2c627SGreg Clayton { 100*0dd2c627SGreg Clayton if (GetBasicInfo()) 101*0dd2c627SGreg Clayton m_suspendCount = m_basicInfo.suspend_count; 102*0dd2c627SGreg Clayton else 103*0dd2c627SGreg Clayton m_suspendCount = 0; 104*0dd2c627SGreg Clayton return false; // ??? 10530fdc8d8SChris Lattner } 10630fdc8d8SChris Lattner } 107*0dd2c627SGreg Clayton } 108*0dd2c627SGreg Clayton // We don't currently really support resuming a thread that was externally 109*0dd2c627SGreg Clayton // suspended. If/when we do, we will need to make the code below work and 110*0dd2c627SGreg Clayton // m_suspendCount will need to become signed instead of unsigned. 111*0dd2c627SGreg Clayton // else if (m_suspendCount < 0) 112*0dd2c627SGreg Clayton // { 113*0dd2c627SGreg Clayton // while (m_suspendCount < 0) 114*0dd2c627SGreg Clayton // { 115*0dd2c627SGreg Clayton // err = ::thread_suspend (m_tid); 116*0dd2c627SGreg Clayton // if (err.Success()) 117*0dd2c627SGreg Clayton // ++m_suspendCount; 118*0dd2c627SGreg Clayton // if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 119*0dd2c627SGreg Clayton // err.LogThreaded("::thread_suspend (%4.4x)", m_tid); 120*0dd2c627SGreg Clayton // } 121*0dd2c627SGreg Clayton // } 122*0dd2c627SGreg Clayton return true; 12330fdc8d8SChris Lattner } 12430fdc8d8SChris Lattner 12530fdc8d8SChris Lattner 12630fdc8d8SChris Lattner const char * 12730fdc8d8SChris Lattner MachThread::GetBasicInfoAsString () const 12830fdc8d8SChris Lattner { 12930fdc8d8SChris Lattner static char g_basic_info_string[1024]; 13030fdc8d8SChris Lattner struct thread_basic_info basicInfo; 13130fdc8d8SChris Lattner 13230fdc8d8SChris Lattner if (GetBasicInfo(m_tid, &basicInfo)) 13330fdc8d8SChris Lattner { 13430fdc8d8SChris Lattner 13530fdc8d8SChris Lattner // char run_state_str[32]; 13630fdc8d8SChris Lattner // size_t run_state_str_size = sizeof(run_state_str); 13730fdc8d8SChris Lattner // switch (basicInfo.run_state) 13830fdc8d8SChris Lattner // { 13930fdc8d8SChris Lattner // case TH_STATE_RUNNING: strncpy(run_state_str, "running", run_state_str_size); break; 14030fdc8d8SChris Lattner // case TH_STATE_STOPPED: strncpy(run_state_str, "stopped", run_state_str_size); break; 14130fdc8d8SChris Lattner // case TH_STATE_WAITING: strncpy(run_state_str, "waiting", run_state_str_size); break; 14230fdc8d8SChris Lattner // case TH_STATE_UNINTERRUPTIBLE: strncpy(run_state_str, "uninterruptible", run_state_str_size); break; 14330fdc8d8SChris Lattner // case TH_STATE_HALTED: strncpy(run_state_str, "halted", run_state_str_size); break; 14430fdc8d8SChris Lattner // default: snprintf(run_state_str, run_state_str_size, "%d", basicInfo.run_state); break; // ??? 14530fdc8d8SChris Lattner // } 14630fdc8d8SChris Lattner float user = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f; 14730fdc8d8SChris Lattner float system = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f; 14830fdc8d8SChris Lattner snprintf(g_basic_info_string, sizeof(g_basic_info_string), "Thread 0x%4.4x: user=%f system=%f cpu=%d sleep_time=%d", 14930fdc8d8SChris Lattner InferiorThreadID(), 15030fdc8d8SChris Lattner user, 15130fdc8d8SChris Lattner system, 15230fdc8d8SChris Lattner basicInfo.cpu_usage, 15330fdc8d8SChris Lattner basicInfo.sleep_time); 15430fdc8d8SChris Lattner 15530fdc8d8SChris Lattner return g_basic_info_string; 15630fdc8d8SChris Lattner } 15730fdc8d8SChris Lattner return NULL; 15830fdc8d8SChris Lattner } 15930fdc8d8SChris Lattner 16030fdc8d8SChris Lattner thread_t 16130fdc8d8SChris Lattner MachThread::InferiorThreadID() const 16230fdc8d8SChris Lattner { 16330fdc8d8SChris Lattner mach_msg_type_number_t i; 16430fdc8d8SChris Lattner mach_port_name_array_t names; 16530fdc8d8SChris Lattner mach_port_type_array_t types; 16630fdc8d8SChris Lattner mach_msg_type_number_t ncount, tcount; 16730fdc8d8SChris Lattner thread_t inferior_tid = INVALID_NUB_THREAD; 16830fdc8d8SChris Lattner task_t my_task = ::mach_task_self(); 16930fdc8d8SChris Lattner task_t task = m_process->Task().TaskPort(); 17030fdc8d8SChris Lattner 17130fdc8d8SChris Lattner kern_return_t kret = ::mach_port_names (task, &names, &ncount, &types, &tcount); 17230fdc8d8SChris Lattner if (kret == KERN_SUCCESS) 17330fdc8d8SChris Lattner { 17430fdc8d8SChris Lattner 17530fdc8d8SChris Lattner for (i = 0; i < ncount; i++) 17630fdc8d8SChris Lattner { 17730fdc8d8SChris Lattner mach_port_t my_name; 17830fdc8d8SChris Lattner mach_msg_type_name_t my_type; 17930fdc8d8SChris Lattner 18030fdc8d8SChris Lattner kret = ::mach_port_extract_right (task, names[i], MACH_MSG_TYPE_COPY_SEND, &my_name, &my_type); 18130fdc8d8SChris Lattner if (kret == KERN_SUCCESS) 18230fdc8d8SChris Lattner { 18330fdc8d8SChris Lattner ::mach_port_deallocate (my_task, my_name); 18430fdc8d8SChris Lattner if (my_name == m_tid) 18530fdc8d8SChris Lattner { 18630fdc8d8SChris Lattner inferior_tid = names[i]; 18730fdc8d8SChris Lattner break; 18830fdc8d8SChris Lattner } 18930fdc8d8SChris Lattner } 19030fdc8d8SChris Lattner } 19130fdc8d8SChris Lattner // Free up the names and types 19230fdc8d8SChris Lattner ::vm_deallocate (my_task, (vm_address_t) names, ncount * sizeof (mach_port_name_t)); 19330fdc8d8SChris Lattner ::vm_deallocate (my_task, (vm_address_t) types, tcount * sizeof (mach_port_type_t)); 19430fdc8d8SChris Lattner } 19530fdc8d8SChris Lattner return inferior_tid; 19630fdc8d8SChris Lattner } 19730fdc8d8SChris Lattner 19830fdc8d8SChris Lattner bool 1991b946bf6SGreg Clayton MachThread::IsUserReady() 2001b946bf6SGreg Clayton { 2011b946bf6SGreg Clayton if (m_basicInfo.run_state == 0) 2021b946bf6SGreg Clayton GetBasicInfo (); 2031b946bf6SGreg Clayton 2041b946bf6SGreg Clayton switch (m_basicInfo.run_state) 2051b946bf6SGreg Clayton { 2061b946bf6SGreg Clayton default: 207*0dd2c627SGreg Clayton assert (!"Invalid run_state encountered"); 208*0dd2c627SGreg Clayton 2091b946bf6SGreg Clayton case TH_STATE_UNINTERRUPTIBLE: 2101b946bf6SGreg Clayton break; 2111b946bf6SGreg Clayton 2121b946bf6SGreg Clayton case TH_STATE_RUNNING: 2131b946bf6SGreg Clayton case TH_STATE_STOPPED: 2141b946bf6SGreg Clayton case TH_STATE_WAITING: 2151b946bf6SGreg Clayton case TH_STATE_HALTED: 2161b946bf6SGreg Clayton return true; 2171b946bf6SGreg Clayton } 2181b946bf6SGreg Clayton return false; 2191b946bf6SGreg Clayton } 2201b946bf6SGreg Clayton 2211b946bf6SGreg Clayton struct thread_basic_info * 2221b946bf6SGreg Clayton MachThread::GetBasicInfo () 2231b946bf6SGreg Clayton { 2241b946bf6SGreg Clayton if (MachThread::GetBasicInfo(m_tid, &m_basicInfo)) 2251b946bf6SGreg Clayton return &m_basicInfo; 2261b946bf6SGreg Clayton return NULL; 2271b946bf6SGreg Clayton } 2281b946bf6SGreg Clayton 2291b946bf6SGreg Clayton 2301b946bf6SGreg Clayton bool 23130fdc8d8SChris Lattner MachThread::GetBasicInfo(thread_t thread, struct thread_basic_info *basicInfoPtr) 23230fdc8d8SChris Lattner { 23330fdc8d8SChris Lattner if (ThreadIDIsValid(thread)) 23430fdc8d8SChris Lattner { 23530fdc8d8SChris Lattner unsigned int info_count = THREAD_BASIC_INFO_COUNT; 23630fdc8d8SChris Lattner kern_return_t err = ::thread_info (thread, THREAD_BASIC_INFO, (thread_info_t) basicInfoPtr, &info_count); 23730fdc8d8SChris Lattner if (err == KERN_SUCCESS) 23830fdc8d8SChris Lattner return true; 23930fdc8d8SChris Lattner } 24030fdc8d8SChris Lattner ::memset (basicInfoPtr, 0, sizeof (struct thread_basic_info)); 24130fdc8d8SChris Lattner return false; 24230fdc8d8SChris Lattner } 24330fdc8d8SChris Lattner 24430fdc8d8SChris Lattner 24530fdc8d8SChris Lattner bool 24630fdc8d8SChris Lattner MachThread::ThreadIDIsValid(thread_t thread) 24730fdc8d8SChris Lattner { 24830fdc8d8SChris Lattner return thread != THREAD_NULL; 24930fdc8d8SChris Lattner } 25030fdc8d8SChris Lattner 25130fdc8d8SChris Lattner bool 25230fdc8d8SChris Lattner MachThread::GetRegisterState(int flavor, bool force) 25330fdc8d8SChris Lattner { 25430fdc8d8SChris Lattner return m_arch.GetRegisterState(flavor, force) == KERN_SUCCESS; 25530fdc8d8SChris Lattner } 25630fdc8d8SChris Lattner 25730fdc8d8SChris Lattner bool 25830fdc8d8SChris Lattner MachThread::SetRegisterState(int flavor) 25930fdc8d8SChris Lattner { 26030fdc8d8SChris Lattner return m_arch.SetRegisterState(flavor) == KERN_SUCCESS; 26130fdc8d8SChris Lattner } 26230fdc8d8SChris Lattner 26330fdc8d8SChris Lattner uint64_t 26430fdc8d8SChris Lattner MachThread::GetPC(uint64_t failValue) 26530fdc8d8SChris Lattner { 26630fdc8d8SChris Lattner // Get program counter 26730fdc8d8SChris Lattner return m_arch.GetPC(failValue); 26830fdc8d8SChris Lattner } 26930fdc8d8SChris Lattner 27030fdc8d8SChris Lattner bool 27130fdc8d8SChris Lattner MachThread::SetPC(uint64_t value) 27230fdc8d8SChris Lattner { 27330fdc8d8SChris Lattner // Set program counter 27430fdc8d8SChris Lattner return m_arch.SetPC(value); 27530fdc8d8SChris Lattner } 27630fdc8d8SChris Lattner 27730fdc8d8SChris Lattner uint64_t 27830fdc8d8SChris Lattner MachThread::GetSP(uint64_t failValue) 27930fdc8d8SChris Lattner { 28030fdc8d8SChris Lattner // Get stack pointer 28130fdc8d8SChris Lattner return m_arch.GetSP(failValue); 28230fdc8d8SChris Lattner } 28330fdc8d8SChris Lattner 28430fdc8d8SChris Lattner nub_process_t 28530fdc8d8SChris Lattner MachThread::ProcessID() const 28630fdc8d8SChris Lattner { 28730fdc8d8SChris Lattner if (m_process) 28830fdc8d8SChris Lattner return m_process->ProcessID(); 28930fdc8d8SChris Lattner return INVALID_NUB_PROCESS; 29030fdc8d8SChris Lattner } 29130fdc8d8SChris Lattner 29230fdc8d8SChris Lattner void 29330fdc8d8SChris Lattner MachThread::Dump(uint32_t index) 29430fdc8d8SChris Lattner { 29530fdc8d8SChris Lattner const char * thread_run_state = NULL; 29630fdc8d8SChris Lattner 29730fdc8d8SChris Lattner switch (m_basicInfo.run_state) 29830fdc8d8SChris Lattner { 29930fdc8d8SChris Lattner case TH_STATE_RUNNING: thread_run_state = "running"; break; // 1 thread is running normally 30030fdc8d8SChris Lattner case TH_STATE_STOPPED: thread_run_state = "stopped"; break; // 2 thread is stopped 30130fdc8d8SChris Lattner case TH_STATE_WAITING: thread_run_state = "waiting"; break; // 3 thread is waiting normally 30230fdc8d8SChris Lattner case TH_STATE_UNINTERRUPTIBLE: thread_run_state = "uninter"; break; // 4 thread is in an uninterruptible wait 30330fdc8d8SChris Lattner case TH_STATE_HALTED: thread_run_state = "halted "; break; // 5 thread is halted at a 30430fdc8d8SChris Lattner default: thread_run_state = "???"; break; 30530fdc8d8SChris Lattner } 30630fdc8d8SChris Lattner 30730fdc8d8SChris Lattner DNBLogThreaded("thread[%u] %4.4x (%u): pc: 0x%8.8llx sp: 0x%8.8llx breakID: %d user: %d.%06.6d system: %d.%06.6d cpu: %d policy: %d run_state: %d (%s) flags: %d suspend_count: %d (current %d) sleep_time: %d", 30830fdc8d8SChris Lattner index, 30930fdc8d8SChris Lattner m_tid, 31030fdc8d8SChris Lattner m_seq_id, 31130fdc8d8SChris Lattner GetPC(INVALID_NUB_ADDRESS), 31230fdc8d8SChris Lattner GetSP(INVALID_NUB_ADDRESS), 31330fdc8d8SChris Lattner m_breakID, 31430fdc8d8SChris Lattner m_basicInfo.user_time.seconds, m_basicInfo.user_time.microseconds, 31530fdc8d8SChris Lattner m_basicInfo.system_time.seconds, m_basicInfo.system_time.microseconds, 31630fdc8d8SChris Lattner m_basicInfo.cpu_usage, 31730fdc8d8SChris Lattner m_basicInfo.policy, 31830fdc8d8SChris Lattner m_basicInfo.run_state, 31930fdc8d8SChris Lattner thread_run_state, 32030fdc8d8SChris Lattner m_basicInfo.flags, 32130fdc8d8SChris Lattner m_basicInfo.suspend_count, m_suspendCount, 32230fdc8d8SChris Lattner m_basicInfo.sleep_time); 32330fdc8d8SChris Lattner //DumpRegisterState(0); 32430fdc8d8SChris Lattner } 32530fdc8d8SChris Lattner 32630fdc8d8SChris Lattner void 32730fdc8d8SChris Lattner MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action) 32830fdc8d8SChris Lattner { 32930fdc8d8SChris Lattner if (thread_action->addr != INVALID_NUB_ADDRESS) 33030fdc8d8SChris Lattner SetPC (thread_action->addr); 33130fdc8d8SChris Lattner 33230fdc8d8SChris Lattner SetState (thread_action->state); 33330fdc8d8SChris Lattner switch (thread_action->state) 33430fdc8d8SChris Lattner { 33530fdc8d8SChris Lattner case eStateStopped: 33630fdc8d8SChris Lattner case eStateSuspended: 33730fdc8d8SChris Lattner Suspend(); 33830fdc8d8SChris Lattner break; 33930fdc8d8SChris Lattner 34030fdc8d8SChris Lattner case eStateRunning: 34130fdc8d8SChris Lattner case eStateStepping: 34230fdc8d8SChris Lattner Resume(); 34330fdc8d8SChris Lattner break; 34430fdc8d8SChris Lattner } 34530fdc8d8SChris Lattner m_arch.ThreadWillResume(); 34630fdc8d8SChris Lattner m_stop_exception.Clear(); 34730fdc8d8SChris Lattner } 34830fdc8d8SChris Lattner 34930fdc8d8SChris Lattner bool 35030fdc8d8SChris Lattner MachThread::ShouldStop(bool &step_more) 35130fdc8d8SChris Lattner { 35230fdc8d8SChris Lattner // See if this thread is at a breakpoint? 35330fdc8d8SChris Lattner nub_break_t breakID = CurrentBreakpoint(); 35430fdc8d8SChris Lattner 35530fdc8d8SChris Lattner if (NUB_BREAK_ID_IS_VALID(breakID)) 35630fdc8d8SChris Lattner { 35730fdc8d8SChris Lattner // This thread is sitting at a breakpoint, ask the breakpoint 35830fdc8d8SChris Lattner // if we should be stopping here. 35930fdc8d8SChris Lattner if (Process()->Breakpoints().ShouldStop(ProcessID(), ThreadID(), breakID)) 36030fdc8d8SChris Lattner return true; 36130fdc8d8SChris Lattner else 36230fdc8d8SChris Lattner { 36330fdc8d8SChris Lattner // The breakpoint said we shouldn't stop, but we may have gotten 36430fdc8d8SChris Lattner // a signal or the user may have requested to stop in some other 36530fdc8d8SChris Lattner // way. Stop if we have a valid exception (this thread won't if 36630fdc8d8SChris Lattner // another thread was the reason this process stopped) and that 36730fdc8d8SChris Lattner // exception, is NOT a breakpoint exception (a common case would 36830fdc8d8SChris Lattner // be a SIGINT signal). 36930fdc8d8SChris Lattner if (GetStopException().IsValid() && !GetStopException().IsBreakpoint()) 37030fdc8d8SChris Lattner return true; 37130fdc8d8SChris Lattner } 37230fdc8d8SChris Lattner } 37330fdc8d8SChris Lattner else 37430fdc8d8SChris Lattner { 37530fdc8d8SChris Lattner if (m_arch.StepNotComplete()) 37630fdc8d8SChris Lattner { 37730fdc8d8SChris Lattner step_more = true; 37830fdc8d8SChris Lattner return false; 37930fdc8d8SChris Lattner } 38030fdc8d8SChris Lattner // The thread state is used to let us know what the thread was 38130fdc8d8SChris Lattner // trying to do. MachThread::ThreadWillResume() will set the 38230fdc8d8SChris Lattner // thread state to various values depending if the thread was 38330fdc8d8SChris Lattner // the current thread and if it was to be single stepped, or 38430fdc8d8SChris Lattner // resumed. 38530fdc8d8SChris Lattner if (GetState() == eStateRunning) 38630fdc8d8SChris Lattner { 38730fdc8d8SChris Lattner // If our state is running, then we should continue as we are in 38830fdc8d8SChris Lattner // the process of stepping over a breakpoint. 38930fdc8d8SChris Lattner return false; 39030fdc8d8SChris Lattner } 39130fdc8d8SChris Lattner else 39230fdc8d8SChris Lattner { 39330fdc8d8SChris Lattner // Stop if we have any kind of valid exception for this 39430fdc8d8SChris Lattner // thread. 39530fdc8d8SChris Lattner if (GetStopException().IsValid()) 39630fdc8d8SChris Lattner return true; 39730fdc8d8SChris Lattner } 39830fdc8d8SChris Lattner } 39930fdc8d8SChris Lattner return false; 40030fdc8d8SChris Lattner } 40130fdc8d8SChris Lattner bool 40230fdc8d8SChris Lattner MachThread::IsStepping() 40330fdc8d8SChris Lattner { 40430fdc8d8SChris Lattner // Return true if this thread is currently being stepped. 40530fdc8d8SChris Lattner // MachThread::ThreadWillResume currently determines this by looking if we 40630fdc8d8SChris Lattner // have been asked to single step, or if we are at a breakpoint instruction 40730fdc8d8SChris Lattner // and have been asked to resume. In the latter case we need to disable the 40830fdc8d8SChris Lattner // breakpoint we are at, single step, re-enable and continue. 40930fdc8d8SChris Lattner nub_state_t state = GetState(); 41030fdc8d8SChris Lattner return (state == eStateStepping) || 41130fdc8d8SChris Lattner (state == eStateRunning && NUB_BREAK_ID_IS_VALID(CurrentBreakpoint())); 41230fdc8d8SChris Lattner } 41330fdc8d8SChris Lattner 41430fdc8d8SChris Lattner 41530fdc8d8SChris Lattner bool 41630fdc8d8SChris Lattner MachThread::ThreadDidStop() 41730fdc8d8SChris Lattner { 41830fdc8d8SChris Lattner // This thread has existed prior to resuming under debug nub control, 41930fdc8d8SChris Lattner // and has just been stopped. Do any cleanup that needs to be done 42030fdc8d8SChris Lattner // after running. 42130fdc8d8SChris Lattner 42230fdc8d8SChris Lattner // The thread state and breakpoint will still have the same values 42330fdc8d8SChris Lattner // as they had prior to resuming the thread, so it makes it easy to check 42430fdc8d8SChris Lattner // if we were trying to step a thread, or we tried to resume while being 42530fdc8d8SChris Lattner // at a breakpoint. 42630fdc8d8SChris Lattner 42730fdc8d8SChris Lattner // When this method gets called, the process state is still in the 42830fdc8d8SChris Lattner // state it was in while running so we can act accordingly. 42930fdc8d8SChris Lattner m_arch.ThreadDidStop(); 43030fdc8d8SChris Lattner 43130fdc8d8SChris Lattner 43230fdc8d8SChris Lattner // We may have suspended this thread so the primary thread could step 43330fdc8d8SChris Lattner // without worrying about race conditions, so lets restore our suspend 43430fdc8d8SChris Lattner // count. 43530fdc8d8SChris Lattner RestoreSuspendCount(); 43630fdc8d8SChris Lattner 43730fdc8d8SChris Lattner // Update the basic information for a thread 43830fdc8d8SChris Lattner MachThread::GetBasicInfo(m_tid, &m_basicInfo); 43930fdc8d8SChris Lattner 44030fdc8d8SChris Lattner // See if we were at a breakpoint when we last resumed that we disabled, 44130fdc8d8SChris Lattner // re-enable it. 44230fdc8d8SChris Lattner nub_break_t breakID = CurrentBreakpoint(); 44330fdc8d8SChris Lattner 44430fdc8d8SChris Lattner if (NUB_BREAK_ID_IS_VALID(breakID)) 44530fdc8d8SChris Lattner { 44630fdc8d8SChris Lattner m_process->EnableBreakpoint(breakID); 447*0dd2c627SGreg Clayton if (m_basicInfo.suspend_count > 0) 44830fdc8d8SChris Lattner { 44930fdc8d8SChris Lattner SetState(eStateSuspended); 45030fdc8d8SChris Lattner } 45130fdc8d8SChris Lattner else 45230fdc8d8SChris Lattner { 45330fdc8d8SChris Lattner // If we last were at a breakpoint and we single stepped, our state 45430fdc8d8SChris Lattner // will be "running" to indicate we need to continue after stepping 45530fdc8d8SChris Lattner // over the breakpoint instruction. If we step over a breakpoint 45630fdc8d8SChris Lattner // instruction, we need to stop. 45730fdc8d8SChris Lattner if (GetState() == eStateRunning) 45830fdc8d8SChris Lattner { 45930fdc8d8SChris Lattner // Leave state set to running so we will continue automatically 46030fdc8d8SChris Lattner // from this breakpoint 46130fdc8d8SChris Lattner } 46230fdc8d8SChris Lattner else 46330fdc8d8SChris Lattner { 46430fdc8d8SChris Lattner SetState(eStateStopped); 46530fdc8d8SChris Lattner } 46630fdc8d8SChris Lattner } 46730fdc8d8SChris Lattner } 46830fdc8d8SChris Lattner else 46930fdc8d8SChris Lattner { 470*0dd2c627SGreg Clayton if (m_basicInfo.suspend_count > 0) 47130fdc8d8SChris Lattner { 47230fdc8d8SChris Lattner SetState(eStateSuspended); 47330fdc8d8SChris Lattner } 47430fdc8d8SChris Lattner else 47530fdc8d8SChris Lattner { 47630fdc8d8SChris Lattner SetState(eStateStopped); 47730fdc8d8SChris Lattner } 47830fdc8d8SChris Lattner } 47930fdc8d8SChris Lattner 48030fdc8d8SChris Lattner 48130fdc8d8SChris Lattner SetCurrentBreakpoint(INVALID_NUB_BREAK_ID); 48230fdc8d8SChris Lattner 48330fdc8d8SChris Lattner return true; 48430fdc8d8SChris Lattner } 48530fdc8d8SChris Lattner 48630fdc8d8SChris Lattner bool 48730fdc8d8SChris Lattner MachThread::NotifyException(MachException::Data& exc) 48830fdc8d8SChris Lattner { 48930fdc8d8SChris Lattner if (m_stop_exception.IsValid()) 49030fdc8d8SChris Lattner { 49130fdc8d8SChris Lattner // We may have more than one exception for a thread, but we need to 49230fdc8d8SChris Lattner // only remember the one that we will say is the reason we stopped. 49330fdc8d8SChris Lattner // We may have been single stepping and also gotten a signal exception, 49430fdc8d8SChris Lattner // so just remember the most pertinent one. 49530fdc8d8SChris Lattner if (m_stop_exception.IsBreakpoint()) 49630fdc8d8SChris Lattner m_stop_exception = exc; 49730fdc8d8SChris Lattner } 49830fdc8d8SChris Lattner else 49930fdc8d8SChris Lattner { 50030fdc8d8SChris Lattner m_stop_exception = exc; 50130fdc8d8SChris Lattner } 50230fdc8d8SChris Lattner bool handled = m_arch.NotifyException(exc); 50330fdc8d8SChris Lattner if (!handled) 50430fdc8d8SChris Lattner { 50530fdc8d8SChris Lattner handled = true; 50630fdc8d8SChris Lattner nub_addr_t pc = GetPC(); 50730fdc8d8SChris Lattner nub_break_t breakID = m_process->Breakpoints().FindIDByAddress(pc); 50830fdc8d8SChris Lattner SetCurrentBreakpoint(breakID); 50930fdc8d8SChris Lattner switch (exc.exc_type) 51030fdc8d8SChris Lattner { 51130fdc8d8SChris Lattner case EXC_BAD_ACCESS: 51230fdc8d8SChris Lattner break; 51330fdc8d8SChris Lattner case EXC_BAD_INSTRUCTION: 51430fdc8d8SChris Lattner break; 51530fdc8d8SChris Lattner case EXC_ARITHMETIC: 51630fdc8d8SChris Lattner break; 51730fdc8d8SChris Lattner case EXC_EMULATION: 51830fdc8d8SChris Lattner break; 51930fdc8d8SChris Lattner case EXC_SOFTWARE: 52030fdc8d8SChris Lattner break; 52130fdc8d8SChris Lattner case EXC_BREAKPOINT: 52230fdc8d8SChris Lattner break; 52330fdc8d8SChris Lattner case EXC_SYSCALL: 52430fdc8d8SChris Lattner break; 52530fdc8d8SChris Lattner case EXC_MACH_SYSCALL: 52630fdc8d8SChris Lattner break; 52730fdc8d8SChris Lattner case EXC_RPC_ALERT: 52830fdc8d8SChris Lattner break; 52930fdc8d8SChris Lattner } 53030fdc8d8SChris Lattner } 53130fdc8d8SChris Lattner return handled; 53230fdc8d8SChris Lattner } 53330fdc8d8SChris Lattner 53430fdc8d8SChris Lattner 53530fdc8d8SChris Lattner nub_state_t 53630fdc8d8SChris Lattner MachThread::GetState() 53730fdc8d8SChris Lattner { 53830fdc8d8SChris Lattner // If any other threads access this we will need a mutex for it 53930fdc8d8SChris Lattner PTHREAD_MUTEX_LOCKER (locker, m_state_mutex); 54030fdc8d8SChris Lattner return m_state; 54130fdc8d8SChris Lattner } 54230fdc8d8SChris Lattner 54330fdc8d8SChris Lattner void 54430fdc8d8SChris Lattner MachThread::SetState(nub_state_t state) 54530fdc8d8SChris Lattner { 54630fdc8d8SChris Lattner PTHREAD_MUTEX_LOCKER (locker, m_state_mutex); 54730fdc8d8SChris Lattner m_state = state; 54830fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD, "MachThread::SetState ( %s ) for tid = 0x%4.4x", DNBStateAsString(state), m_tid); 54930fdc8d8SChris Lattner } 55030fdc8d8SChris Lattner 55130fdc8d8SChris Lattner uint32_t 55230fdc8d8SChris Lattner MachThread::GetNumRegistersInSet(int regSet) const 55330fdc8d8SChris Lattner { 55430fdc8d8SChris Lattner if (regSet < m_regSets.size()) 55530fdc8d8SChris Lattner return m_regSets[regSet].num_registers; 55630fdc8d8SChris Lattner return 0; 55730fdc8d8SChris Lattner } 55830fdc8d8SChris Lattner 55930fdc8d8SChris Lattner const char * 56030fdc8d8SChris Lattner MachThread::GetRegisterSetName(int regSet) const 56130fdc8d8SChris Lattner { 56230fdc8d8SChris Lattner if (regSet < m_regSets.size()) 56330fdc8d8SChris Lattner return m_regSets[regSet].name; 56430fdc8d8SChris Lattner return NULL; 56530fdc8d8SChris Lattner } 56630fdc8d8SChris Lattner 56730fdc8d8SChris Lattner const DNBRegisterInfo * 56830fdc8d8SChris Lattner MachThread::GetRegisterInfo(int regSet, int regIndex) const 56930fdc8d8SChris Lattner { 57030fdc8d8SChris Lattner if (regSet < m_regSets.size()) 57130fdc8d8SChris Lattner if (regIndex < m_regSets[regSet].num_registers) 57230fdc8d8SChris Lattner return &m_regSets[regSet].registers[regIndex]; 57330fdc8d8SChris Lattner return NULL; 57430fdc8d8SChris Lattner } 57530fdc8d8SChris Lattner void 57630fdc8d8SChris Lattner MachThread::DumpRegisterState(int regSet) 57730fdc8d8SChris Lattner { 57830fdc8d8SChris Lattner if (regSet == REGISTER_SET_ALL) 57930fdc8d8SChris Lattner { 58030fdc8d8SChris Lattner for (regSet = 1; regSet < m_regSets.size(); regSet++) 58130fdc8d8SChris Lattner DumpRegisterState(regSet); 58230fdc8d8SChris Lattner } 58330fdc8d8SChris Lattner else 58430fdc8d8SChris Lattner { 58530fdc8d8SChris Lattner if (m_arch.RegisterSetStateIsValid(regSet)) 58630fdc8d8SChris Lattner { 58730fdc8d8SChris Lattner const size_t numRegisters = GetNumRegistersInSet(regSet); 58830fdc8d8SChris Lattner size_t regIndex = 0; 58930fdc8d8SChris Lattner DNBRegisterValueClass reg; 59030fdc8d8SChris Lattner for (regIndex = 0; regIndex < numRegisters; ++regIndex) 59130fdc8d8SChris Lattner { 59230fdc8d8SChris Lattner if (m_arch.GetRegisterValue(regSet, regIndex, ®)) 59330fdc8d8SChris Lattner { 59430fdc8d8SChris Lattner reg.Dump(NULL, NULL); 59530fdc8d8SChris Lattner } 59630fdc8d8SChris Lattner } 59730fdc8d8SChris Lattner } 59830fdc8d8SChris Lattner else 59930fdc8d8SChris Lattner { 60030fdc8d8SChris Lattner DNBLog("%s: registers are not currently valid.", GetRegisterSetName(regSet)); 60130fdc8d8SChris Lattner } 60230fdc8d8SChris Lattner } 60330fdc8d8SChris Lattner } 60430fdc8d8SChris Lattner 60530fdc8d8SChris Lattner const DNBRegisterSetInfo * 60630fdc8d8SChris Lattner MachThread::GetRegisterSetInfo(nub_size_t *num_reg_sets ) const 60730fdc8d8SChris Lattner { 60830fdc8d8SChris Lattner *num_reg_sets = m_regSets.size(); 60930fdc8d8SChris Lattner return &m_regSets[0]; 61030fdc8d8SChris Lattner } 61130fdc8d8SChris Lattner 61230fdc8d8SChris Lattner bool 61330fdc8d8SChris Lattner MachThread::GetRegisterValue ( uint32_t set, uint32_t reg, DNBRegisterValue *value ) 61430fdc8d8SChris Lattner { 61530fdc8d8SChris Lattner return m_arch.GetRegisterValue(set, reg, value); 61630fdc8d8SChris Lattner } 61730fdc8d8SChris Lattner 61830fdc8d8SChris Lattner bool 61930fdc8d8SChris Lattner MachThread::SetRegisterValue ( uint32_t set, uint32_t reg, const DNBRegisterValue *value ) 62030fdc8d8SChris Lattner { 62130fdc8d8SChris Lattner return m_arch.SetRegisterValue(set, reg, value); 62230fdc8d8SChris Lattner } 62330fdc8d8SChris Lattner 62430fdc8d8SChris Lattner nub_size_t 62530fdc8d8SChris Lattner MachThread::GetRegisterContext (void *buf, nub_size_t buf_len) 62630fdc8d8SChris Lattner { 62730fdc8d8SChris Lattner return m_arch.GetRegisterContext(buf, buf_len); 62830fdc8d8SChris Lattner } 62930fdc8d8SChris Lattner 63030fdc8d8SChris Lattner nub_size_t 63130fdc8d8SChris Lattner MachThread::SetRegisterContext (const void *buf, nub_size_t buf_len) 63230fdc8d8SChris Lattner { 63330fdc8d8SChris Lattner return m_arch.SetRegisterContext(buf, buf_len); 63430fdc8d8SChris Lattner } 63530fdc8d8SChris Lattner 63630fdc8d8SChris Lattner uint32_t 63730fdc8d8SChris Lattner MachThread::EnableHardwareBreakpoint (const DNBBreakpoint *bp) 63830fdc8d8SChris Lattner { 63930fdc8d8SChris Lattner if (bp != NULL && bp->IsBreakpoint()) 64030fdc8d8SChris Lattner return m_arch.EnableHardwareBreakpoint(bp->Address(), bp->ByteSize()); 64130fdc8d8SChris Lattner return INVALID_NUB_HW_INDEX; 64230fdc8d8SChris Lattner } 64330fdc8d8SChris Lattner 64430fdc8d8SChris Lattner uint32_t 64530fdc8d8SChris Lattner MachThread::EnableHardwareWatchpoint (const DNBBreakpoint *wp) 64630fdc8d8SChris Lattner { 64730fdc8d8SChris Lattner if (wp != NULL && wp->IsWatchpoint()) 64830fdc8d8SChris Lattner return m_arch.EnableHardwareWatchpoint(wp->Address(), wp->ByteSize(), wp->WatchpointRead(), wp->WatchpointWrite()); 64930fdc8d8SChris Lattner return INVALID_NUB_HW_INDEX; 65030fdc8d8SChris Lattner } 65130fdc8d8SChris Lattner 65230fdc8d8SChris Lattner bool 65330fdc8d8SChris Lattner MachThread::DisableHardwareBreakpoint (const DNBBreakpoint *bp) 65430fdc8d8SChris Lattner { 65530fdc8d8SChris Lattner if (bp != NULL && bp->IsHardware()) 65630fdc8d8SChris Lattner return m_arch.DisableHardwareBreakpoint(bp->GetHardwareIndex()); 65730fdc8d8SChris Lattner return false; 65830fdc8d8SChris Lattner } 65930fdc8d8SChris Lattner 66030fdc8d8SChris Lattner bool 66130fdc8d8SChris Lattner MachThread::DisableHardwareWatchpoint (const DNBBreakpoint *wp) 66230fdc8d8SChris Lattner { 66330fdc8d8SChris Lattner if (wp != NULL && wp->IsHardware()) 66430fdc8d8SChris Lattner return m_arch.DisableHardwareWatchpoint(wp->GetHardwareIndex()); 66530fdc8d8SChris Lattner return false; 66630fdc8d8SChris Lattner } 66730fdc8d8SChris Lattner 66830fdc8d8SChris Lattner 66930fdc8d8SChris Lattner void 67030fdc8d8SChris Lattner MachThread::NotifyBreakpointChanged (const DNBBreakpoint *bp) 67130fdc8d8SChris Lattner { 67230fdc8d8SChris Lattner nub_break_t breakID = bp->GetID(); 67330fdc8d8SChris Lattner if (bp->IsEnabled()) 67430fdc8d8SChris Lattner { 67530fdc8d8SChris Lattner if (bp->Address() == GetPC()) 67630fdc8d8SChris Lattner { 67730fdc8d8SChris Lattner SetCurrentBreakpoint(breakID); 67830fdc8d8SChris Lattner } 67930fdc8d8SChris Lattner } 68030fdc8d8SChris Lattner else 68130fdc8d8SChris Lattner { 68230fdc8d8SChris Lattner if (CurrentBreakpoint() == breakID) 68330fdc8d8SChris Lattner { 68430fdc8d8SChris Lattner SetCurrentBreakpoint(INVALID_NUB_BREAK_ID); 68530fdc8d8SChris Lattner } 68630fdc8d8SChris Lattner } 68730fdc8d8SChris Lattner } 68830fdc8d8SChris Lattner 68930fdc8d8SChris Lattner bool 69030fdc8d8SChris Lattner MachThread::GetIdentifierInfo () 69130fdc8d8SChris Lattner { 69230fdc8d8SChris Lattner #ifdef THREAD_IDENTIFIER_INFO_COUNT 69330fdc8d8SChris Lattner if (m_ident_info.thread_id == 0) 69430fdc8d8SChris Lattner { 69530fdc8d8SChris Lattner mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; 69630fdc8d8SChris Lattner return ::thread_info (ThreadID(), THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count) == KERN_SUCCESS; 69730fdc8d8SChris Lattner } 69830fdc8d8SChris Lattner #endif 69930fdc8d8SChris Lattner 70030fdc8d8SChris Lattner return false; 70130fdc8d8SChris Lattner } 70230fdc8d8SChris Lattner 70330fdc8d8SChris Lattner 70430fdc8d8SChris Lattner const char * 70530fdc8d8SChris Lattner MachThread::GetName () 70630fdc8d8SChris Lattner { 70730fdc8d8SChris Lattner if (GetIdentifierInfo ()) 70830fdc8d8SChris Lattner { 70930fdc8d8SChris Lattner int len = ::proc_pidinfo (m_process->ProcessID(), PROC_PIDTHREADINFO, m_ident_info.thread_handle, &m_proc_threadinfo, sizeof (m_proc_threadinfo)); 71030fdc8d8SChris Lattner 71130fdc8d8SChris Lattner if (len && m_proc_threadinfo.pth_name[0]) 71230fdc8d8SChris Lattner return m_proc_threadinfo.pth_name; 71330fdc8d8SChris Lattner } 71430fdc8d8SChris Lattner return NULL; 71530fdc8d8SChris Lattner } 71630fdc8d8SChris Lattner 71730fdc8d8SChris Lattner 71830fdc8d8SChris Lattner // 71930fdc8d8SChris Lattner //const char * 72030fdc8d8SChris Lattner //MachThread::GetDispatchQueueName() 72130fdc8d8SChris Lattner //{ 72230fdc8d8SChris Lattner // if (GetIdentifierInfo ()) 72330fdc8d8SChris Lattner // { 72430fdc8d8SChris Lattner // if (m_ident_info.dispatch_qaddr == 0) 72530fdc8d8SChris Lattner // return NULL; 72630fdc8d8SChris Lattner // 72730fdc8d8SChris Lattner // uint8_t memory_buffer[8]; 72830fdc8d8SChris Lattner // DNBDataRef data(memory_buffer, sizeof(memory_buffer), false); 72930fdc8d8SChris Lattner // ModuleSP module_sp(GetProcess()->GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib"))); 73030fdc8d8SChris Lattner // if (module_sp.get() == NULL) 73130fdc8d8SChris Lattner // return NULL; 73230fdc8d8SChris Lattner // 73330fdc8d8SChris Lattner // lldb::addr_t dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS; 73430fdc8d8SChris Lattner // const Symbol *dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (ConstString("dispatch_queue_offsets"), eSymbolTypeData); 73530fdc8d8SChris Lattner // if (dispatch_queue_offsets_symbol) 73630fdc8d8SChris Lattner // dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetValue().GetLoadAddress(GetProcess()); 73730fdc8d8SChris Lattner // 73830fdc8d8SChris Lattner // if (dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS) 73930fdc8d8SChris Lattner // return NULL; 74030fdc8d8SChris Lattner // 74130fdc8d8SChris Lattner // // Excerpt from src/queue_private.h 74230fdc8d8SChris Lattner // struct dispatch_queue_offsets_s 74330fdc8d8SChris Lattner // { 74430fdc8d8SChris Lattner // uint16_t dqo_version; 74530fdc8d8SChris Lattner // uint16_t dqo_label; 74630fdc8d8SChris Lattner // uint16_t dqo_label_size; 74730fdc8d8SChris Lattner // } dispatch_queue_offsets; 74830fdc8d8SChris Lattner // 74930fdc8d8SChris Lattner // 75030fdc8d8SChris Lattner // if (GetProcess()->ReadMemory (dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets)) == sizeof(dispatch_queue_offsets)) 75130fdc8d8SChris Lattner // { 75230fdc8d8SChris Lattner // uint32_t data_offset = 0; 75330fdc8d8SChris Lattner // if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t))) 75430fdc8d8SChris Lattner // { 75530fdc8d8SChris Lattner // if (GetProcess()->ReadMemory (m_ident_info.dispatch_qaddr, &memory_buffer, data.GetAddressByteSize()) == data.GetAddressByteSize()) 75630fdc8d8SChris Lattner // { 75730fdc8d8SChris Lattner // data_offset = 0; 75830fdc8d8SChris Lattner // lldb::addr_t queue_addr = data.GetAddress(&data_offset); 75930fdc8d8SChris Lattner // lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label; 76030fdc8d8SChris Lattner // const size_t chunk_size = 32; 76130fdc8d8SChris Lattner // uint32_t label_pos = 0; 76230fdc8d8SChris Lattner // m_dispatch_queue_name.resize(chunk_size, '\0'); 76330fdc8d8SChris Lattner // while (1) 76430fdc8d8SChris Lattner // { 76530fdc8d8SChris Lattner // size_t bytes_read = GetProcess()->ReadMemory (label_addr + label_pos, &m_dispatch_queue_name[label_pos], chunk_size); 76630fdc8d8SChris Lattner // 76730fdc8d8SChris Lattner // if (bytes_read <= 0) 76830fdc8d8SChris Lattner // break; 76930fdc8d8SChris Lattner // 77030fdc8d8SChris Lattner // if (m_dispatch_queue_name.find('\0', label_pos) != std::string::npos) 77130fdc8d8SChris Lattner // break; 77230fdc8d8SChris Lattner // label_pos += bytes_read; 77330fdc8d8SChris Lattner // } 77430fdc8d8SChris Lattner // m_dispatch_queue_name.erase(m_dispatch_queue_name.find('\0')); 77530fdc8d8SChris Lattner // } 77630fdc8d8SChris Lattner // } 77730fdc8d8SChris Lattner // } 77830fdc8d8SChris Lattner // } 77930fdc8d8SChris Lattner // 78030fdc8d8SChris Lattner // if (m_dispatch_queue_name.empty()) 78130fdc8d8SChris Lattner // return NULL; 78230fdc8d8SChris Lattner // return m_dispatch_queue_name.c_str(); 78330fdc8d8SChris Lattner //} 784