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, &reg))
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