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