1*30fdc8d8SChris Lattner //===-- MachThread.cpp ------------------------------------------*- C++ -*-===// 2*30fdc8d8SChris Lattner // 3*30fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 4*30fdc8d8SChris Lattner // 5*30fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 6*30fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 7*30fdc8d8SChris Lattner // 8*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 9*30fdc8d8SChris Lattner // 10*30fdc8d8SChris Lattner // Created by Greg Clayton on 6/19/07. 11*30fdc8d8SChris Lattner // 12*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 13*30fdc8d8SChris Lattner 14*30fdc8d8SChris Lattner #include "MachThread.h" 15*30fdc8d8SChris Lattner #include "MachProcess.h" 16*30fdc8d8SChris Lattner #include "DNBLog.h" 17*30fdc8d8SChris Lattner #include "DNB.h" 18*30fdc8d8SChris Lattner 19*30fdc8d8SChris Lattner static uint32_t 20*30fdc8d8SChris Lattner GetSequenceID() 21*30fdc8d8SChris Lattner { 22*30fdc8d8SChris Lattner static uint32_t g_nextID = 0; 23*30fdc8d8SChris Lattner return ++g_nextID; 24*30fdc8d8SChris Lattner } 25*30fdc8d8SChris Lattner 26*30fdc8d8SChris Lattner MachThread::MachThread (MachProcess *process, thread_t thread) : 27*30fdc8d8SChris Lattner m_process(process), 28*30fdc8d8SChris Lattner m_tid(thread), 29*30fdc8d8SChris Lattner m_seq_id(GetSequenceID()), 30*30fdc8d8SChris Lattner m_state(eStateUnloaded), 31*30fdc8d8SChris Lattner m_state_mutex(PTHREAD_MUTEX_RECURSIVE), 32*30fdc8d8SChris Lattner m_breakID(INVALID_NUB_BREAK_ID), 33*30fdc8d8SChris Lattner m_suspendCount(0), 34*30fdc8d8SChris Lattner m_arch(this), 35*30fdc8d8SChris Lattner m_regSets() 36*30fdc8d8SChris Lattner { 37*30fdc8d8SChris Lattner nub_size_t num_reg_sets = 0; 38*30fdc8d8SChris Lattner const DNBRegisterSetInfo *regSetInfo = m_arch.GetRegisterSetInfo(&num_reg_sets); 39*30fdc8d8SChris Lattner if (num_reg_sets > 0) 40*30fdc8d8SChris Lattner m_regSets.assign(regSetInfo, regSetInfo + num_reg_sets); 41*30fdc8d8SChris Lattner 42*30fdc8d8SChris Lattner ::memset (&m_basicInfo, 0, sizeof (m_basicInfo)); 43*30fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::MachThread ( process = %p, tid = 0x%4.4x, seq_id = %u )", &m_process, m_tid, m_seq_id); 44*30fdc8d8SChris Lattner } 45*30fdc8d8SChris Lattner 46*30fdc8d8SChris Lattner MachThread::~MachThread() 47*30fdc8d8SChris Lattner { 48*30fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::~MachThread() for tid = 0x%4.4x (%u)", m_tid, m_seq_id); 49*30fdc8d8SChris Lattner } 50*30fdc8d8SChris Lattner 51*30fdc8d8SChris Lattner 52*30fdc8d8SChris Lattner 53*30fdc8d8SChris Lattner uint32_t 54*30fdc8d8SChris Lattner MachThread::Suspend() 55*30fdc8d8SChris Lattner { 56*30fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 57*30fdc8d8SChris Lattner if (ThreadIDIsValid(m_tid)) 58*30fdc8d8SChris Lattner { 59*30fdc8d8SChris Lattner DNBError err(::thread_suspend (m_tid), DNBError::MachKernel); 60*30fdc8d8SChris Lattner if (err.Success()) 61*30fdc8d8SChris Lattner m_suspendCount++; 62*30fdc8d8SChris Lattner if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 63*30fdc8d8SChris Lattner err.LogThreaded("::thread_suspend (%4.4x)", m_tid); 64*30fdc8d8SChris Lattner } 65*30fdc8d8SChris Lattner return SuspendCount(); 66*30fdc8d8SChris Lattner } 67*30fdc8d8SChris Lattner 68*30fdc8d8SChris Lattner uint32_t 69*30fdc8d8SChris Lattner MachThread::Resume() 70*30fdc8d8SChris Lattner { 71*30fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 72*30fdc8d8SChris Lattner if (ThreadIDIsValid(m_tid)) 73*30fdc8d8SChris Lattner { 74*30fdc8d8SChris Lattner while (m_suspendCount > 0) 75*30fdc8d8SChris Lattner { 76*30fdc8d8SChris Lattner DNBError err(::thread_resume (m_tid), DNBError::MachKernel); 77*30fdc8d8SChris Lattner if (err.Success()) 78*30fdc8d8SChris Lattner m_suspendCount--; 79*30fdc8d8SChris Lattner if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 80*30fdc8d8SChris Lattner err.LogThreaded("::thread_resume (%4.4x)", m_tid); 81*30fdc8d8SChris Lattner } 82*30fdc8d8SChris Lattner } 83*30fdc8d8SChris Lattner return SuspendCount(); 84*30fdc8d8SChris Lattner } 85*30fdc8d8SChris Lattner 86*30fdc8d8SChris Lattner bool 87*30fdc8d8SChris Lattner MachThread::RestoreSuspendCount() 88*30fdc8d8SChris Lattner { 89*30fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); 90*30fdc8d8SChris Lattner DNBError err; 91*30fdc8d8SChris Lattner if (ThreadIDIsValid(m_tid) == false) 92*30fdc8d8SChris Lattner return false; 93*30fdc8d8SChris Lattner else if (m_suspendCount > m_basicInfo.suspend_count) 94*30fdc8d8SChris Lattner { 95*30fdc8d8SChris Lattner while (m_suspendCount > m_basicInfo.suspend_count) 96*30fdc8d8SChris Lattner { 97*30fdc8d8SChris Lattner err = ::thread_resume (m_tid); 98*30fdc8d8SChris Lattner if (err.Success()) 99*30fdc8d8SChris Lattner --m_suspendCount; 100*30fdc8d8SChris Lattner if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 101*30fdc8d8SChris Lattner err.LogThreaded("::thread_resume (%4.4x)", m_tid); 102*30fdc8d8SChris Lattner } 103*30fdc8d8SChris Lattner } 104*30fdc8d8SChris Lattner else if (m_suspendCount < m_basicInfo.suspend_count) 105*30fdc8d8SChris Lattner { 106*30fdc8d8SChris Lattner while (m_suspendCount < m_basicInfo.suspend_count) 107*30fdc8d8SChris Lattner { 108*30fdc8d8SChris Lattner err = ::thread_suspend (m_tid); 109*30fdc8d8SChris Lattner if (err.Success()) 110*30fdc8d8SChris Lattner --m_suspendCount; 111*30fdc8d8SChris Lattner if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) 112*30fdc8d8SChris Lattner err.LogThreaded("::thread_suspend (%4.4x)", m_tid); 113*30fdc8d8SChris Lattner } 114*30fdc8d8SChris Lattner } 115*30fdc8d8SChris Lattner return m_suspendCount == m_basicInfo.suspend_count; 116*30fdc8d8SChris Lattner } 117*30fdc8d8SChris Lattner 118*30fdc8d8SChris Lattner 119*30fdc8d8SChris Lattner const char * 120*30fdc8d8SChris Lattner MachThread::GetBasicInfoAsString () const 121*30fdc8d8SChris Lattner { 122*30fdc8d8SChris Lattner static char g_basic_info_string[1024]; 123*30fdc8d8SChris Lattner struct thread_basic_info basicInfo; 124*30fdc8d8SChris Lattner 125*30fdc8d8SChris Lattner if (GetBasicInfo(m_tid, &basicInfo)) 126*30fdc8d8SChris Lattner { 127*30fdc8d8SChris Lattner 128*30fdc8d8SChris Lattner // char run_state_str[32]; 129*30fdc8d8SChris Lattner // size_t run_state_str_size = sizeof(run_state_str); 130*30fdc8d8SChris Lattner // switch (basicInfo.run_state) 131*30fdc8d8SChris Lattner // { 132*30fdc8d8SChris Lattner // case TH_STATE_RUNNING: strncpy(run_state_str, "running", run_state_str_size); break; 133*30fdc8d8SChris Lattner // case TH_STATE_STOPPED: strncpy(run_state_str, "stopped", run_state_str_size); break; 134*30fdc8d8SChris Lattner // case TH_STATE_WAITING: strncpy(run_state_str, "waiting", run_state_str_size); break; 135*30fdc8d8SChris Lattner // case TH_STATE_UNINTERRUPTIBLE: strncpy(run_state_str, "uninterruptible", run_state_str_size); break; 136*30fdc8d8SChris Lattner // case TH_STATE_HALTED: strncpy(run_state_str, "halted", run_state_str_size); break; 137*30fdc8d8SChris Lattner // default: snprintf(run_state_str, run_state_str_size, "%d", basicInfo.run_state); break; // ??? 138*30fdc8d8SChris Lattner // } 139*30fdc8d8SChris Lattner float user = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f; 140*30fdc8d8SChris Lattner float system = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f; 141*30fdc8d8SChris Lattner snprintf(g_basic_info_string, sizeof(g_basic_info_string), "Thread 0x%4.4x: user=%f system=%f cpu=%d sleep_time=%d", 142*30fdc8d8SChris Lattner InferiorThreadID(), 143*30fdc8d8SChris Lattner user, 144*30fdc8d8SChris Lattner system, 145*30fdc8d8SChris Lattner basicInfo.cpu_usage, 146*30fdc8d8SChris Lattner basicInfo.sleep_time); 147*30fdc8d8SChris Lattner 148*30fdc8d8SChris Lattner return g_basic_info_string; 149*30fdc8d8SChris Lattner } 150*30fdc8d8SChris Lattner return NULL; 151*30fdc8d8SChris Lattner } 152*30fdc8d8SChris Lattner 153*30fdc8d8SChris Lattner thread_t 154*30fdc8d8SChris Lattner MachThread::InferiorThreadID() const 155*30fdc8d8SChris Lattner { 156*30fdc8d8SChris Lattner mach_msg_type_number_t i; 157*30fdc8d8SChris Lattner mach_port_name_array_t names; 158*30fdc8d8SChris Lattner mach_port_type_array_t types; 159*30fdc8d8SChris Lattner mach_msg_type_number_t ncount, tcount; 160*30fdc8d8SChris Lattner thread_t inferior_tid = INVALID_NUB_THREAD; 161*30fdc8d8SChris Lattner task_t my_task = ::mach_task_self(); 162*30fdc8d8SChris Lattner task_t task = m_process->Task().TaskPort(); 163*30fdc8d8SChris Lattner 164*30fdc8d8SChris Lattner kern_return_t kret = ::mach_port_names (task, &names, &ncount, &types, &tcount); 165*30fdc8d8SChris Lattner if (kret == KERN_SUCCESS) 166*30fdc8d8SChris Lattner { 167*30fdc8d8SChris Lattner 168*30fdc8d8SChris Lattner for (i = 0; i < ncount; i++) 169*30fdc8d8SChris Lattner { 170*30fdc8d8SChris Lattner mach_port_t my_name; 171*30fdc8d8SChris Lattner mach_msg_type_name_t my_type; 172*30fdc8d8SChris Lattner 173*30fdc8d8SChris Lattner kret = ::mach_port_extract_right (task, names[i], MACH_MSG_TYPE_COPY_SEND, &my_name, &my_type); 174*30fdc8d8SChris Lattner if (kret == KERN_SUCCESS) 175*30fdc8d8SChris Lattner { 176*30fdc8d8SChris Lattner ::mach_port_deallocate (my_task, my_name); 177*30fdc8d8SChris Lattner if (my_name == m_tid) 178*30fdc8d8SChris Lattner { 179*30fdc8d8SChris Lattner inferior_tid = names[i]; 180*30fdc8d8SChris Lattner break; 181*30fdc8d8SChris Lattner } 182*30fdc8d8SChris Lattner } 183*30fdc8d8SChris Lattner } 184*30fdc8d8SChris Lattner // Free up the names and types 185*30fdc8d8SChris Lattner ::vm_deallocate (my_task, (vm_address_t) names, ncount * sizeof (mach_port_name_t)); 186*30fdc8d8SChris Lattner ::vm_deallocate (my_task, (vm_address_t) types, tcount * sizeof (mach_port_type_t)); 187*30fdc8d8SChris Lattner } 188*30fdc8d8SChris Lattner return inferior_tid; 189*30fdc8d8SChris Lattner } 190*30fdc8d8SChris Lattner 191*30fdc8d8SChris Lattner bool 192*30fdc8d8SChris Lattner MachThread::GetBasicInfo(thread_t thread, struct thread_basic_info *basicInfoPtr) 193*30fdc8d8SChris Lattner { 194*30fdc8d8SChris Lattner if (ThreadIDIsValid(thread)) 195*30fdc8d8SChris Lattner { 196*30fdc8d8SChris Lattner unsigned int info_count = THREAD_BASIC_INFO_COUNT; 197*30fdc8d8SChris Lattner kern_return_t err = ::thread_info (thread, THREAD_BASIC_INFO, (thread_info_t) basicInfoPtr, &info_count); 198*30fdc8d8SChris Lattner if (err == KERN_SUCCESS) 199*30fdc8d8SChris Lattner return true; 200*30fdc8d8SChris Lattner } 201*30fdc8d8SChris Lattner ::memset (basicInfoPtr, 0, sizeof (struct thread_basic_info)); 202*30fdc8d8SChris Lattner return false; 203*30fdc8d8SChris Lattner } 204*30fdc8d8SChris Lattner 205*30fdc8d8SChris Lattner 206*30fdc8d8SChris Lattner bool 207*30fdc8d8SChris Lattner MachThread::ThreadIDIsValid(thread_t thread) 208*30fdc8d8SChris Lattner { 209*30fdc8d8SChris Lattner return thread != THREAD_NULL; 210*30fdc8d8SChris Lattner } 211*30fdc8d8SChris Lattner 212*30fdc8d8SChris Lattner bool 213*30fdc8d8SChris Lattner MachThread::GetRegisterState(int flavor, bool force) 214*30fdc8d8SChris Lattner { 215*30fdc8d8SChris Lattner return m_arch.GetRegisterState(flavor, force) == KERN_SUCCESS; 216*30fdc8d8SChris Lattner } 217*30fdc8d8SChris Lattner 218*30fdc8d8SChris Lattner bool 219*30fdc8d8SChris Lattner MachThread::SetRegisterState(int flavor) 220*30fdc8d8SChris Lattner { 221*30fdc8d8SChris Lattner return m_arch.SetRegisterState(flavor) == KERN_SUCCESS; 222*30fdc8d8SChris Lattner } 223*30fdc8d8SChris Lattner 224*30fdc8d8SChris Lattner uint64_t 225*30fdc8d8SChris Lattner MachThread::GetPC(uint64_t failValue) 226*30fdc8d8SChris Lattner { 227*30fdc8d8SChris Lattner // Get program counter 228*30fdc8d8SChris Lattner return m_arch.GetPC(failValue); 229*30fdc8d8SChris Lattner } 230*30fdc8d8SChris Lattner 231*30fdc8d8SChris Lattner bool 232*30fdc8d8SChris Lattner MachThread::SetPC(uint64_t value) 233*30fdc8d8SChris Lattner { 234*30fdc8d8SChris Lattner // Set program counter 235*30fdc8d8SChris Lattner return m_arch.SetPC(value); 236*30fdc8d8SChris Lattner } 237*30fdc8d8SChris Lattner 238*30fdc8d8SChris Lattner uint64_t 239*30fdc8d8SChris Lattner MachThread::GetSP(uint64_t failValue) 240*30fdc8d8SChris Lattner { 241*30fdc8d8SChris Lattner // Get stack pointer 242*30fdc8d8SChris Lattner return m_arch.GetSP(failValue); 243*30fdc8d8SChris Lattner } 244*30fdc8d8SChris Lattner 245*30fdc8d8SChris Lattner nub_process_t 246*30fdc8d8SChris Lattner MachThread::ProcessID() const 247*30fdc8d8SChris Lattner { 248*30fdc8d8SChris Lattner if (m_process) 249*30fdc8d8SChris Lattner return m_process->ProcessID(); 250*30fdc8d8SChris Lattner return INVALID_NUB_PROCESS; 251*30fdc8d8SChris Lattner } 252*30fdc8d8SChris Lattner 253*30fdc8d8SChris Lattner void 254*30fdc8d8SChris Lattner MachThread::Dump(uint32_t index) 255*30fdc8d8SChris Lattner { 256*30fdc8d8SChris Lattner const char * thread_run_state = NULL; 257*30fdc8d8SChris Lattner 258*30fdc8d8SChris Lattner switch (m_basicInfo.run_state) 259*30fdc8d8SChris Lattner { 260*30fdc8d8SChris Lattner case TH_STATE_RUNNING: thread_run_state = "running"; break; // 1 thread is running normally 261*30fdc8d8SChris Lattner case TH_STATE_STOPPED: thread_run_state = "stopped"; break; // 2 thread is stopped 262*30fdc8d8SChris Lattner case TH_STATE_WAITING: thread_run_state = "waiting"; break; // 3 thread is waiting normally 263*30fdc8d8SChris Lattner case TH_STATE_UNINTERRUPTIBLE: thread_run_state = "uninter"; break; // 4 thread is in an uninterruptible wait 264*30fdc8d8SChris Lattner case TH_STATE_HALTED: thread_run_state = "halted "; break; // 5 thread is halted at a 265*30fdc8d8SChris Lattner default: thread_run_state = "???"; break; 266*30fdc8d8SChris Lattner } 267*30fdc8d8SChris Lattner 268*30fdc8d8SChris 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", 269*30fdc8d8SChris Lattner index, 270*30fdc8d8SChris Lattner m_tid, 271*30fdc8d8SChris Lattner m_seq_id, 272*30fdc8d8SChris Lattner GetPC(INVALID_NUB_ADDRESS), 273*30fdc8d8SChris Lattner GetSP(INVALID_NUB_ADDRESS), 274*30fdc8d8SChris Lattner m_breakID, 275*30fdc8d8SChris Lattner m_basicInfo.user_time.seconds, m_basicInfo.user_time.microseconds, 276*30fdc8d8SChris Lattner m_basicInfo.system_time.seconds, m_basicInfo.system_time.microseconds, 277*30fdc8d8SChris Lattner m_basicInfo.cpu_usage, 278*30fdc8d8SChris Lattner m_basicInfo.policy, 279*30fdc8d8SChris Lattner m_basicInfo.run_state, 280*30fdc8d8SChris Lattner thread_run_state, 281*30fdc8d8SChris Lattner m_basicInfo.flags, 282*30fdc8d8SChris Lattner m_basicInfo.suspend_count, m_suspendCount, 283*30fdc8d8SChris Lattner m_basicInfo.sleep_time); 284*30fdc8d8SChris Lattner //DumpRegisterState(0); 285*30fdc8d8SChris Lattner } 286*30fdc8d8SChris Lattner 287*30fdc8d8SChris Lattner void 288*30fdc8d8SChris Lattner MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action) 289*30fdc8d8SChris Lattner { 290*30fdc8d8SChris Lattner if (thread_action->addr != INVALID_NUB_ADDRESS) 291*30fdc8d8SChris Lattner SetPC (thread_action->addr); 292*30fdc8d8SChris Lattner 293*30fdc8d8SChris Lattner SetState (thread_action->state); 294*30fdc8d8SChris Lattner switch (thread_action->state) 295*30fdc8d8SChris Lattner { 296*30fdc8d8SChris Lattner case eStateStopped: 297*30fdc8d8SChris Lattner case eStateSuspended: 298*30fdc8d8SChris Lattner Suspend(); 299*30fdc8d8SChris Lattner break; 300*30fdc8d8SChris Lattner 301*30fdc8d8SChris Lattner case eStateRunning: 302*30fdc8d8SChris Lattner case eStateStepping: 303*30fdc8d8SChris Lattner Resume(); 304*30fdc8d8SChris Lattner break; 305*30fdc8d8SChris Lattner } 306*30fdc8d8SChris Lattner m_arch.ThreadWillResume(); 307*30fdc8d8SChris Lattner m_stop_exception.Clear(); 308*30fdc8d8SChris Lattner } 309*30fdc8d8SChris Lattner 310*30fdc8d8SChris Lattner bool 311*30fdc8d8SChris Lattner MachThread::ShouldStop(bool &step_more) 312*30fdc8d8SChris Lattner { 313*30fdc8d8SChris Lattner // See if this thread is at a breakpoint? 314*30fdc8d8SChris Lattner nub_break_t breakID = CurrentBreakpoint(); 315*30fdc8d8SChris Lattner 316*30fdc8d8SChris Lattner if (NUB_BREAK_ID_IS_VALID(breakID)) 317*30fdc8d8SChris Lattner { 318*30fdc8d8SChris Lattner // This thread is sitting at a breakpoint, ask the breakpoint 319*30fdc8d8SChris Lattner // if we should be stopping here. 320*30fdc8d8SChris Lattner if (Process()->Breakpoints().ShouldStop(ProcessID(), ThreadID(), breakID)) 321*30fdc8d8SChris Lattner return true; 322*30fdc8d8SChris Lattner else 323*30fdc8d8SChris Lattner { 324*30fdc8d8SChris Lattner // The breakpoint said we shouldn't stop, but we may have gotten 325*30fdc8d8SChris Lattner // a signal or the user may have requested to stop in some other 326*30fdc8d8SChris Lattner // way. Stop if we have a valid exception (this thread won't if 327*30fdc8d8SChris Lattner // another thread was the reason this process stopped) and that 328*30fdc8d8SChris Lattner // exception, is NOT a breakpoint exception (a common case would 329*30fdc8d8SChris Lattner // be a SIGINT signal). 330*30fdc8d8SChris Lattner if (GetStopException().IsValid() && !GetStopException().IsBreakpoint()) 331*30fdc8d8SChris Lattner return true; 332*30fdc8d8SChris Lattner } 333*30fdc8d8SChris Lattner } 334*30fdc8d8SChris Lattner else 335*30fdc8d8SChris Lattner { 336*30fdc8d8SChris Lattner if (m_arch.StepNotComplete()) 337*30fdc8d8SChris Lattner { 338*30fdc8d8SChris Lattner step_more = true; 339*30fdc8d8SChris Lattner return false; 340*30fdc8d8SChris Lattner } 341*30fdc8d8SChris Lattner // The thread state is used to let us know what the thread was 342*30fdc8d8SChris Lattner // trying to do. MachThread::ThreadWillResume() will set the 343*30fdc8d8SChris Lattner // thread state to various values depending if the thread was 344*30fdc8d8SChris Lattner // the current thread and if it was to be single stepped, or 345*30fdc8d8SChris Lattner // resumed. 346*30fdc8d8SChris Lattner if (GetState() == eStateRunning) 347*30fdc8d8SChris Lattner { 348*30fdc8d8SChris Lattner // If our state is running, then we should continue as we are in 349*30fdc8d8SChris Lattner // the process of stepping over a breakpoint. 350*30fdc8d8SChris Lattner return false; 351*30fdc8d8SChris Lattner } 352*30fdc8d8SChris Lattner else 353*30fdc8d8SChris Lattner { 354*30fdc8d8SChris Lattner // Stop if we have any kind of valid exception for this 355*30fdc8d8SChris Lattner // thread. 356*30fdc8d8SChris Lattner if (GetStopException().IsValid()) 357*30fdc8d8SChris Lattner return true; 358*30fdc8d8SChris Lattner } 359*30fdc8d8SChris Lattner } 360*30fdc8d8SChris Lattner return false; 361*30fdc8d8SChris Lattner } 362*30fdc8d8SChris Lattner bool 363*30fdc8d8SChris Lattner MachThread::IsStepping() 364*30fdc8d8SChris Lattner { 365*30fdc8d8SChris Lattner // Return true if this thread is currently being stepped. 366*30fdc8d8SChris Lattner // MachThread::ThreadWillResume currently determines this by looking if we 367*30fdc8d8SChris Lattner // have been asked to single step, or if we are at a breakpoint instruction 368*30fdc8d8SChris Lattner // and have been asked to resume. In the latter case we need to disable the 369*30fdc8d8SChris Lattner // breakpoint we are at, single step, re-enable and continue. 370*30fdc8d8SChris Lattner nub_state_t state = GetState(); 371*30fdc8d8SChris Lattner return (state == eStateStepping) || 372*30fdc8d8SChris Lattner (state == eStateRunning && NUB_BREAK_ID_IS_VALID(CurrentBreakpoint())); 373*30fdc8d8SChris Lattner } 374*30fdc8d8SChris Lattner 375*30fdc8d8SChris Lattner 376*30fdc8d8SChris Lattner bool 377*30fdc8d8SChris Lattner MachThread::ThreadDidStop() 378*30fdc8d8SChris Lattner { 379*30fdc8d8SChris Lattner // This thread has existed prior to resuming under debug nub control, 380*30fdc8d8SChris Lattner // and has just been stopped. Do any cleanup that needs to be done 381*30fdc8d8SChris Lattner // after running. 382*30fdc8d8SChris Lattner 383*30fdc8d8SChris Lattner // The thread state and breakpoint will still have the same values 384*30fdc8d8SChris Lattner // as they had prior to resuming the thread, so it makes it easy to check 385*30fdc8d8SChris Lattner // if we were trying to step a thread, or we tried to resume while being 386*30fdc8d8SChris Lattner // at a breakpoint. 387*30fdc8d8SChris Lattner 388*30fdc8d8SChris Lattner // When this method gets called, the process state is still in the 389*30fdc8d8SChris Lattner // state it was in while running so we can act accordingly. 390*30fdc8d8SChris Lattner m_arch.ThreadDidStop(); 391*30fdc8d8SChris Lattner 392*30fdc8d8SChris Lattner 393*30fdc8d8SChris Lattner // We may have suspended this thread so the primary thread could step 394*30fdc8d8SChris Lattner // without worrying about race conditions, so lets restore our suspend 395*30fdc8d8SChris Lattner // count. 396*30fdc8d8SChris Lattner RestoreSuspendCount(); 397*30fdc8d8SChris Lattner 398*30fdc8d8SChris Lattner // Update the basic information for a thread 399*30fdc8d8SChris Lattner MachThread::GetBasicInfo(m_tid, &m_basicInfo); 400*30fdc8d8SChris Lattner m_suspendCount = m_basicInfo.suspend_count; 401*30fdc8d8SChris Lattner 402*30fdc8d8SChris Lattner // See if we were at a breakpoint when we last resumed that we disabled, 403*30fdc8d8SChris Lattner // re-enable it. 404*30fdc8d8SChris Lattner nub_break_t breakID = CurrentBreakpoint(); 405*30fdc8d8SChris Lattner 406*30fdc8d8SChris Lattner if (NUB_BREAK_ID_IS_VALID(breakID)) 407*30fdc8d8SChris Lattner { 408*30fdc8d8SChris Lattner m_process->EnableBreakpoint(breakID); 409*30fdc8d8SChris Lattner if (m_suspendCount > 0) 410*30fdc8d8SChris Lattner { 411*30fdc8d8SChris Lattner SetState(eStateSuspended); 412*30fdc8d8SChris Lattner } 413*30fdc8d8SChris Lattner else 414*30fdc8d8SChris Lattner { 415*30fdc8d8SChris Lattner // If we last were at a breakpoint and we single stepped, our state 416*30fdc8d8SChris Lattner // will be "running" to indicate we need to continue after stepping 417*30fdc8d8SChris Lattner // over the breakpoint instruction. If we step over a breakpoint 418*30fdc8d8SChris Lattner // instruction, we need to stop. 419*30fdc8d8SChris Lattner if (GetState() == eStateRunning) 420*30fdc8d8SChris Lattner { 421*30fdc8d8SChris Lattner // Leave state set to running so we will continue automatically 422*30fdc8d8SChris Lattner // from this breakpoint 423*30fdc8d8SChris Lattner } 424*30fdc8d8SChris Lattner else 425*30fdc8d8SChris Lattner { 426*30fdc8d8SChris Lattner SetState(eStateStopped); 427*30fdc8d8SChris Lattner } 428*30fdc8d8SChris Lattner } 429*30fdc8d8SChris Lattner } 430*30fdc8d8SChris Lattner else 431*30fdc8d8SChris Lattner { 432*30fdc8d8SChris Lattner if (m_suspendCount > 0) 433*30fdc8d8SChris Lattner { 434*30fdc8d8SChris Lattner SetState(eStateSuspended); 435*30fdc8d8SChris Lattner } 436*30fdc8d8SChris Lattner else 437*30fdc8d8SChris Lattner { 438*30fdc8d8SChris Lattner SetState(eStateStopped); 439*30fdc8d8SChris Lattner } 440*30fdc8d8SChris Lattner } 441*30fdc8d8SChris Lattner 442*30fdc8d8SChris Lattner 443*30fdc8d8SChris Lattner SetCurrentBreakpoint(INVALID_NUB_BREAK_ID); 444*30fdc8d8SChris Lattner 445*30fdc8d8SChris Lattner return true; 446*30fdc8d8SChris Lattner } 447*30fdc8d8SChris Lattner 448*30fdc8d8SChris Lattner bool 449*30fdc8d8SChris Lattner MachThread::NotifyException(MachException::Data& exc) 450*30fdc8d8SChris Lattner { 451*30fdc8d8SChris Lattner if (m_stop_exception.IsValid()) 452*30fdc8d8SChris Lattner { 453*30fdc8d8SChris Lattner // We may have more than one exception for a thread, but we need to 454*30fdc8d8SChris Lattner // only remember the one that we will say is the reason we stopped. 455*30fdc8d8SChris Lattner // We may have been single stepping and also gotten a signal exception, 456*30fdc8d8SChris Lattner // so just remember the most pertinent one. 457*30fdc8d8SChris Lattner if (m_stop_exception.IsBreakpoint()) 458*30fdc8d8SChris Lattner m_stop_exception = exc; 459*30fdc8d8SChris Lattner } 460*30fdc8d8SChris Lattner else 461*30fdc8d8SChris Lattner { 462*30fdc8d8SChris Lattner m_stop_exception = exc; 463*30fdc8d8SChris Lattner } 464*30fdc8d8SChris Lattner bool handled = m_arch.NotifyException(exc); 465*30fdc8d8SChris Lattner if (!handled) 466*30fdc8d8SChris Lattner { 467*30fdc8d8SChris Lattner handled = true; 468*30fdc8d8SChris Lattner nub_addr_t pc = GetPC(); 469*30fdc8d8SChris Lattner nub_break_t breakID = m_process->Breakpoints().FindIDByAddress(pc); 470*30fdc8d8SChris Lattner SetCurrentBreakpoint(breakID); 471*30fdc8d8SChris Lattner switch (exc.exc_type) 472*30fdc8d8SChris Lattner { 473*30fdc8d8SChris Lattner case EXC_BAD_ACCESS: 474*30fdc8d8SChris Lattner break; 475*30fdc8d8SChris Lattner case EXC_BAD_INSTRUCTION: 476*30fdc8d8SChris Lattner break; 477*30fdc8d8SChris Lattner case EXC_ARITHMETIC: 478*30fdc8d8SChris Lattner break; 479*30fdc8d8SChris Lattner case EXC_EMULATION: 480*30fdc8d8SChris Lattner break; 481*30fdc8d8SChris Lattner case EXC_SOFTWARE: 482*30fdc8d8SChris Lattner break; 483*30fdc8d8SChris Lattner case EXC_BREAKPOINT: 484*30fdc8d8SChris Lattner break; 485*30fdc8d8SChris Lattner case EXC_SYSCALL: 486*30fdc8d8SChris Lattner break; 487*30fdc8d8SChris Lattner case EXC_MACH_SYSCALL: 488*30fdc8d8SChris Lattner break; 489*30fdc8d8SChris Lattner case EXC_RPC_ALERT: 490*30fdc8d8SChris Lattner break; 491*30fdc8d8SChris Lattner } 492*30fdc8d8SChris Lattner } 493*30fdc8d8SChris Lattner return handled; 494*30fdc8d8SChris Lattner } 495*30fdc8d8SChris Lattner 496*30fdc8d8SChris Lattner 497*30fdc8d8SChris Lattner nub_state_t 498*30fdc8d8SChris Lattner MachThread::GetState() 499*30fdc8d8SChris Lattner { 500*30fdc8d8SChris Lattner // If any other threads access this we will need a mutex for it 501*30fdc8d8SChris Lattner PTHREAD_MUTEX_LOCKER (locker, m_state_mutex); 502*30fdc8d8SChris Lattner return m_state; 503*30fdc8d8SChris Lattner } 504*30fdc8d8SChris Lattner 505*30fdc8d8SChris Lattner void 506*30fdc8d8SChris Lattner MachThread::SetState(nub_state_t state) 507*30fdc8d8SChris Lattner { 508*30fdc8d8SChris Lattner PTHREAD_MUTEX_LOCKER (locker, m_state_mutex); 509*30fdc8d8SChris Lattner m_state = state; 510*30fdc8d8SChris Lattner DNBLogThreadedIf(LOG_THREAD, "MachThread::SetState ( %s ) for tid = 0x%4.4x", DNBStateAsString(state), m_tid); 511*30fdc8d8SChris Lattner } 512*30fdc8d8SChris Lattner 513*30fdc8d8SChris Lattner uint32_t 514*30fdc8d8SChris Lattner MachThread::GetNumRegistersInSet(int regSet) const 515*30fdc8d8SChris Lattner { 516*30fdc8d8SChris Lattner if (regSet < m_regSets.size()) 517*30fdc8d8SChris Lattner return m_regSets[regSet].num_registers; 518*30fdc8d8SChris Lattner return 0; 519*30fdc8d8SChris Lattner } 520*30fdc8d8SChris Lattner 521*30fdc8d8SChris Lattner const char * 522*30fdc8d8SChris Lattner MachThread::GetRegisterSetName(int regSet) const 523*30fdc8d8SChris Lattner { 524*30fdc8d8SChris Lattner if (regSet < m_regSets.size()) 525*30fdc8d8SChris Lattner return m_regSets[regSet].name; 526*30fdc8d8SChris Lattner return NULL; 527*30fdc8d8SChris Lattner } 528*30fdc8d8SChris Lattner 529*30fdc8d8SChris Lattner const DNBRegisterInfo * 530*30fdc8d8SChris Lattner MachThread::GetRegisterInfo(int regSet, int regIndex) const 531*30fdc8d8SChris Lattner { 532*30fdc8d8SChris Lattner if (regSet < m_regSets.size()) 533*30fdc8d8SChris Lattner if (regIndex < m_regSets[regSet].num_registers) 534*30fdc8d8SChris Lattner return &m_regSets[regSet].registers[regIndex]; 535*30fdc8d8SChris Lattner return NULL; 536*30fdc8d8SChris Lattner } 537*30fdc8d8SChris Lattner void 538*30fdc8d8SChris Lattner MachThread::DumpRegisterState(int regSet) 539*30fdc8d8SChris Lattner { 540*30fdc8d8SChris Lattner if (regSet == REGISTER_SET_ALL) 541*30fdc8d8SChris Lattner { 542*30fdc8d8SChris Lattner for (regSet = 1; regSet < m_regSets.size(); regSet++) 543*30fdc8d8SChris Lattner DumpRegisterState(regSet); 544*30fdc8d8SChris Lattner } 545*30fdc8d8SChris Lattner else 546*30fdc8d8SChris Lattner { 547*30fdc8d8SChris Lattner if (m_arch.RegisterSetStateIsValid(regSet)) 548*30fdc8d8SChris Lattner { 549*30fdc8d8SChris Lattner const size_t numRegisters = GetNumRegistersInSet(regSet); 550*30fdc8d8SChris Lattner size_t regIndex = 0; 551*30fdc8d8SChris Lattner DNBRegisterValueClass reg; 552*30fdc8d8SChris Lattner for (regIndex = 0; regIndex < numRegisters; ++regIndex) 553*30fdc8d8SChris Lattner { 554*30fdc8d8SChris Lattner if (m_arch.GetRegisterValue(regSet, regIndex, ®)) 555*30fdc8d8SChris Lattner { 556*30fdc8d8SChris Lattner reg.Dump(NULL, NULL); 557*30fdc8d8SChris Lattner } 558*30fdc8d8SChris Lattner } 559*30fdc8d8SChris Lattner } 560*30fdc8d8SChris Lattner else 561*30fdc8d8SChris Lattner { 562*30fdc8d8SChris Lattner DNBLog("%s: registers are not currently valid.", GetRegisterSetName(regSet)); 563*30fdc8d8SChris Lattner } 564*30fdc8d8SChris Lattner } 565*30fdc8d8SChris Lattner } 566*30fdc8d8SChris Lattner 567*30fdc8d8SChris Lattner const DNBRegisterSetInfo * 568*30fdc8d8SChris Lattner MachThread::GetRegisterSetInfo(nub_size_t *num_reg_sets ) const 569*30fdc8d8SChris Lattner { 570*30fdc8d8SChris Lattner *num_reg_sets = m_regSets.size(); 571*30fdc8d8SChris Lattner return &m_regSets[0]; 572*30fdc8d8SChris Lattner } 573*30fdc8d8SChris Lattner 574*30fdc8d8SChris Lattner bool 575*30fdc8d8SChris Lattner MachThread::GetRegisterValue ( uint32_t set, uint32_t reg, DNBRegisterValue *value ) 576*30fdc8d8SChris Lattner { 577*30fdc8d8SChris Lattner return m_arch.GetRegisterValue(set, reg, value); 578*30fdc8d8SChris Lattner } 579*30fdc8d8SChris Lattner 580*30fdc8d8SChris Lattner bool 581*30fdc8d8SChris Lattner MachThread::SetRegisterValue ( uint32_t set, uint32_t reg, const DNBRegisterValue *value ) 582*30fdc8d8SChris Lattner { 583*30fdc8d8SChris Lattner return m_arch.SetRegisterValue(set, reg, value); 584*30fdc8d8SChris Lattner } 585*30fdc8d8SChris Lattner 586*30fdc8d8SChris Lattner nub_size_t 587*30fdc8d8SChris Lattner MachThread::GetRegisterContext (void *buf, nub_size_t buf_len) 588*30fdc8d8SChris Lattner { 589*30fdc8d8SChris Lattner return m_arch.GetRegisterContext(buf, buf_len); 590*30fdc8d8SChris Lattner } 591*30fdc8d8SChris Lattner 592*30fdc8d8SChris Lattner nub_size_t 593*30fdc8d8SChris Lattner MachThread::SetRegisterContext (const void *buf, nub_size_t buf_len) 594*30fdc8d8SChris Lattner { 595*30fdc8d8SChris Lattner return m_arch.SetRegisterContext(buf, buf_len); 596*30fdc8d8SChris Lattner } 597*30fdc8d8SChris Lattner 598*30fdc8d8SChris Lattner uint32_t 599*30fdc8d8SChris Lattner MachThread::EnableHardwareBreakpoint (const DNBBreakpoint *bp) 600*30fdc8d8SChris Lattner { 601*30fdc8d8SChris Lattner if (bp != NULL && bp->IsBreakpoint()) 602*30fdc8d8SChris Lattner return m_arch.EnableHardwareBreakpoint(bp->Address(), bp->ByteSize()); 603*30fdc8d8SChris Lattner return INVALID_NUB_HW_INDEX; 604*30fdc8d8SChris Lattner } 605*30fdc8d8SChris Lattner 606*30fdc8d8SChris Lattner uint32_t 607*30fdc8d8SChris Lattner MachThread::EnableHardwareWatchpoint (const DNBBreakpoint *wp) 608*30fdc8d8SChris Lattner { 609*30fdc8d8SChris Lattner if (wp != NULL && wp->IsWatchpoint()) 610*30fdc8d8SChris Lattner return m_arch.EnableHardwareWatchpoint(wp->Address(), wp->ByteSize(), wp->WatchpointRead(), wp->WatchpointWrite()); 611*30fdc8d8SChris Lattner return INVALID_NUB_HW_INDEX; 612*30fdc8d8SChris Lattner } 613*30fdc8d8SChris Lattner 614*30fdc8d8SChris Lattner bool 615*30fdc8d8SChris Lattner MachThread::DisableHardwareBreakpoint (const DNBBreakpoint *bp) 616*30fdc8d8SChris Lattner { 617*30fdc8d8SChris Lattner if (bp != NULL && bp->IsHardware()) 618*30fdc8d8SChris Lattner return m_arch.DisableHardwareBreakpoint(bp->GetHardwareIndex()); 619*30fdc8d8SChris Lattner return false; 620*30fdc8d8SChris Lattner } 621*30fdc8d8SChris Lattner 622*30fdc8d8SChris Lattner bool 623*30fdc8d8SChris Lattner MachThread::DisableHardwareWatchpoint (const DNBBreakpoint *wp) 624*30fdc8d8SChris Lattner { 625*30fdc8d8SChris Lattner if (wp != NULL && wp->IsHardware()) 626*30fdc8d8SChris Lattner return m_arch.DisableHardwareWatchpoint(wp->GetHardwareIndex()); 627*30fdc8d8SChris Lattner return false; 628*30fdc8d8SChris Lattner } 629*30fdc8d8SChris Lattner 630*30fdc8d8SChris Lattner 631*30fdc8d8SChris Lattner void 632*30fdc8d8SChris Lattner MachThread::NotifyBreakpointChanged (const DNBBreakpoint *bp) 633*30fdc8d8SChris Lattner { 634*30fdc8d8SChris Lattner nub_break_t breakID = bp->GetID(); 635*30fdc8d8SChris Lattner if (bp->IsEnabled()) 636*30fdc8d8SChris Lattner { 637*30fdc8d8SChris Lattner if (bp->Address() == GetPC()) 638*30fdc8d8SChris Lattner { 639*30fdc8d8SChris Lattner SetCurrentBreakpoint(breakID); 640*30fdc8d8SChris Lattner } 641*30fdc8d8SChris Lattner } 642*30fdc8d8SChris Lattner else 643*30fdc8d8SChris Lattner { 644*30fdc8d8SChris Lattner if (CurrentBreakpoint() == breakID) 645*30fdc8d8SChris Lattner { 646*30fdc8d8SChris Lattner SetCurrentBreakpoint(INVALID_NUB_BREAK_ID); 647*30fdc8d8SChris Lattner } 648*30fdc8d8SChris Lattner } 649*30fdc8d8SChris Lattner } 650*30fdc8d8SChris Lattner 651*30fdc8d8SChris Lattner bool 652*30fdc8d8SChris Lattner MachThread::GetIdentifierInfo () 653*30fdc8d8SChris Lattner { 654*30fdc8d8SChris Lattner #ifdef THREAD_IDENTIFIER_INFO_COUNT 655*30fdc8d8SChris Lattner if (m_ident_info.thread_id == 0) 656*30fdc8d8SChris Lattner { 657*30fdc8d8SChris Lattner mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; 658*30fdc8d8SChris Lattner return ::thread_info (ThreadID(), THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count) == KERN_SUCCESS; 659*30fdc8d8SChris Lattner } 660*30fdc8d8SChris Lattner #endif 661*30fdc8d8SChris Lattner 662*30fdc8d8SChris Lattner return false; 663*30fdc8d8SChris Lattner } 664*30fdc8d8SChris Lattner 665*30fdc8d8SChris Lattner 666*30fdc8d8SChris Lattner const char * 667*30fdc8d8SChris Lattner MachThread::GetName () 668*30fdc8d8SChris Lattner { 669*30fdc8d8SChris Lattner if (GetIdentifierInfo ()) 670*30fdc8d8SChris Lattner { 671*30fdc8d8SChris Lattner int len = ::proc_pidinfo (m_process->ProcessID(), PROC_PIDTHREADINFO, m_ident_info.thread_handle, &m_proc_threadinfo, sizeof (m_proc_threadinfo)); 672*30fdc8d8SChris Lattner 673*30fdc8d8SChris Lattner if (len && m_proc_threadinfo.pth_name[0]) 674*30fdc8d8SChris Lattner return m_proc_threadinfo.pth_name; 675*30fdc8d8SChris Lattner } 676*30fdc8d8SChris Lattner return NULL; 677*30fdc8d8SChris Lattner } 678*30fdc8d8SChris Lattner 679*30fdc8d8SChris Lattner 680*30fdc8d8SChris Lattner // 681*30fdc8d8SChris Lattner //const char * 682*30fdc8d8SChris Lattner //MachThread::GetDispatchQueueName() 683*30fdc8d8SChris Lattner //{ 684*30fdc8d8SChris Lattner // if (GetIdentifierInfo ()) 685*30fdc8d8SChris Lattner // { 686*30fdc8d8SChris Lattner // if (m_ident_info.dispatch_qaddr == 0) 687*30fdc8d8SChris Lattner // return NULL; 688*30fdc8d8SChris Lattner // 689*30fdc8d8SChris Lattner // uint8_t memory_buffer[8]; 690*30fdc8d8SChris Lattner // DNBDataRef data(memory_buffer, sizeof(memory_buffer), false); 691*30fdc8d8SChris Lattner // ModuleSP module_sp(GetProcess()->GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib"))); 692*30fdc8d8SChris Lattner // if (module_sp.get() == NULL) 693*30fdc8d8SChris Lattner // return NULL; 694*30fdc8d8SChris Lattner // 695*30fdc8d8SChris Lattner // lldb::addr_t dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS; 696*30fdc8d8SChris Lattner // const Symbol *dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (ConstString("dispatch_queue_offsets"), eSymbolTypeData); 697*30fdc8d8SChris Lattner // if (dispatch_queue_offsets_symbol) 698*30fdc8d8SChris Lattner // dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetValue().GetLoadAddress(GetProcess()); 699*30fdc8d8SChris Lattner // 700*30fdc8d8SChris Lattner // if (dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS) 701*30fdc8d8SChris Lattner // return NULL; 702*30fdc8d8SChris Lattner // 703*30fdc8d8SChris Lattner // // Excerpt from src/queue_private.h 704*30fdc8d8SChris Lattner // struct dispatch_queue_offsets_s 705*30fdc8d8SChris Lattner // { 706*30fdc8d8SChris Lattner // uint16_t dqo_version; 707*30fdc8d8SChris Lattner // uint16_t dqo_label; 708*30fdc8d8SChris Lattner // uint16_t dqo_label_size; 709*30fdc8d8SChris Lattner // } dispatch_queue_offsets; 710*30fdc8d8SChris Lattner // 711*30fdc8d8SChris Lattner // 712*30fdc8d8SChris Lattner // if (GetProcess()->ReadMemory (dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets)) == sizeof(dispatch_queue_offsets)) 713*30fdc8d8SChris Lattner // { 714*30fdc8d8SChris Lattner // uint32_t data_offset = 0; 715*30fdc8d8SChris Lattner // if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t))) 716*30fdc8d8SChris Lattner // { 717*30fdc8d8SChris Lattner // if (GetProcess()->ReadMemory (m_ident_info.dispatch_qaddr, &memory_buffer, data.GetAddressByteSize()) == data.GetAddressByteSize()) 718*30fdc8d8SChris Lattner // { 719*30fdc8d8SChris Lattner // data_offset = 0; 720*30fdc8d8SChris Lattner // lldb::addr_t queue_addr = data.GetAddress(&data_offset); 721*30fdc8d8SChris Lattner // lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label; 722*30fdc8d8SChris Lattner // const size_t chunk_size = 32; 723*30fdc8d8SChris Lattner // uint32_t label_pos = 0; 724*30fdc8d8SChris Lattner // m_dispatch_queue_name.resize(chunk_size, '\0'); 725*30fdc8d8SChris Lattner // while (1) 726*30fdc8d8SChris Lattner // { 727*30fdc8d8SChris Lattner // size_t bytes_read = GetProcess()->ReadMemory (label_addr + label_pos, &m_dispatch_queue_name[label_pos], chunk_size); 728*30fdc8d8SChris Lattner // 729*30fdc8d8SChris Lattner // if (bytes_read <= 0) 730*30fdc8d8SChris Lattner // break; 731*30fdc8d8SChris Lattner // 732*30fdc8d8SChris Lattner // if (m_dispatch_queue_name.find('\0', label_pos) != std::string::npos) 733*30fdc8d8SChris Lattner // break; 734*30fdc8d8SChris Lattner // label_pos += bytes_read; 735*30fdc8d8SChris Lattner // } 736*30fdc8d8SChris Lattner // m_dispatch_queue_name.erase(m_dispatch_queue_name.find('\0')); 737*30fdc8d8SChris Lattner // } 738*30fdc8d8SChris Lattner // } 739*30fdc8d8SChris Lattner // } 740*30fdc8d8SChris Lattner // } 741*30fdc8d8SChris Lattner // 742*30fdc8d8SChris Lattner // if (m_dispatch_queue_name.empty()) 743*30fdc8d8SChris Lattner // return NULL; 744*30fdc8d8SChris Lattner // return m_dispatch_queue_name.c_str(); 745*30fdc8d8SChris Lattner //} 746