1
2""" Please make sure you read the README file COMPLETELY BEFORE reading anything below.
3    It is very critical that you read coding guidelines in Section E in README file.
4"""
5
6from xnu import *
7import sys, shlex
8from utils import *
9from core.lazytarget import *
10import xnudefines
11
12def GetProcInfo(proc):
13    """ returns a string name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields.
14        params:
15            proc : value object representing a proc in the kernel
16        returns:
17            str : A string describing various information for process.
18    """
19    out_string = ""
20    out_string += ("Process {p: <#020x}\n\tname {p.p_comm: <20s}\n\tpid:{p.p_pid: <6d} " +
21                   "task:{p.task: <#020x} p_stat:{p.p_stat: <6d} parent pid: {p.p_ppid: <6d}\n"
22                   ).format(p=proc)
23    #print the Creds
24    ucred = proc.p_ucred
25    if ucred:
26        out_string += "Cred: euid {:d} ruid {:d} svuid {:d}\n".format(ucred.cr_posix.cr_uid,
27                                                                      ucred.cr_posix.cr_ruid,
28                                                                      ucred.cr_posix.cr_svuid )
29    #print the flags
30    flags = int(proc.p_flag)
31    out_string += "Flags: {0: <#020x}\n".format(flags)
32    i = 1
33    num = 1
34    while num <= flags:
35        if flags & num:
36            out_string += "\t" + xnudefines.proc_flag_explain_strings[i] + "\n"
37        elif num == 0x4: #special case for 32bit flag
38            out_string += "\t" + xnudefines.proc_flag_explain_strings[0] + "\n"
39        i += 1
40        num = num << 1
41    out_string += "State: "
42    state_val = proc.p_stat
43    if state_val < 1 or state_val > len(xnudefines.proc_state_strings) :
44        out_string += "(Unknown)"
45    else:
46        out_string += xnudefines.proc_state_strings[int(state_val)]
47
48    return out_string
49
50def GetProcNameForPid(pid):
51    """ Finds the name of the process corresponding to a given pid
52        params:
53            pid     : int, pid you want to find the procname for
54        returns
55            str     : Name of the process corresponding to the pid, "Unknown" if not found
56    """
57    for p in kern.procs:
58        if int(p.p_pid) == int(pid):
59            return str(p.p_comm)
60    return "Unknown"
61
62def GetProcForPid(search_pid):
63    """ Finds the value object representing a proc in the kernel based on its pid
64        params:
65            search_pid  : int, pid whose proc structure you want to find
66        returns:
67            value       : The value object representing the proc, if a proc corresponding
68                          to the given pid is found. Returns None otherwise
69    """
70    if search_pid == 0:
71        return kern.globals.initproc
72    else:
73        headp = kern.globals.allproc
74        for proc in IterateListEntry(headp, 'struct proc *', 'p_list'):
75            if proc.p_pid == search_pid:
76                return proc
77        return None
78
79@lldb_command('allproc')
80def AllProc(cmd_args=None):
81    """ Walk through the allproc structure and print procinfo for each process structure.
82        params:
83            cmd_args - [] : array of strings passed from lldb command prompt
84    """
85    for proc in kern.procs :
86        print GetProcInfo(proc)
87
88
89@lldb_command('zombproc')
90def ZombProc(cmd_args=None):
91    """ Routine to print out all procs in the zombie list
92        params:
93            cmd_args - [] : array of strings passed from lldb command prompt
94    """
95    for proc in kern.zombprocs:
96        print GetProcInfo(proc)
97
98@lldb_command('zombstacks')
99def ZombStacks(cmd_args=None):
100    """ Routine to print out all stacks of tasks that are exiting
101    """
102    for proc in kern.zombprocs:
103        if proc.p_stat != 5:
104            t = Cast(proc.task, 'task *')
105            ShowTaskStacks(t)
106#End of Zombstacks
107
108@lldb_type_summary(['task', 'task_t'])
109@header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags"))
110def GetTaskSummary(task):
111    """ Summarizes the important fields in task structure.
112        params: task: value - value object representing a task in kernel
113        returns: str - summary of the task
114    """
115    out_string = ""
116    format_string = '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}'
117    thread_count = int(task.thread_count)
118    task_flags = ''
119    if hasattr(task, "suppression_generation") and (int(task.suppression_generation) & 0x1) == 0x1:
120        task_flags += 'P'
121    if hasattr(task, "suspend_count") and int(task.suspend_count) > 0:
122        task_flags += 'S'
123    if hasattr(task, "imp_receiver") and int(task.imp_receiver) == 1:
124        task_flags += 'R'
125    if hasattr(task, "imp_donor") and int(task.imp_donor) == 1:
126        task_flags += 'D'
127    if hasattr(task, "task_imp_assertcnt") and int(task.task_imp_assertcnt) > 0:
128        task_flags += 'B'
129    out_string += format_string.format(task, task.map, task.itk_space, thread_count, task_flags)
130    return out_string
131
132@lldb_type_summary(['thread *', 'thread_t'])
133@header("{0: <24s} {1: <10s} {2: <20s} {3: <6s} {4: <10s} {5: <5s} {6: <20s} {7: <45s} {8: <20s} {9: <20s}".format('thread', 'thread_id', 'processor', 'pri', 'io_policy', 'state', 'wait_queue', 'wait_event', 'wmesg', 'thread_name'))
134def GetThreadSummary(thread):
135    """ Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct.
136        params: thread: value - value objecte representing a thread in kernel
137        returns: str - summary of a thread
138    """
139    out_string = ""
140    format_string = "{0: <24s} {1: <10s} {2: <20s} {3: <6s} {4: <10s} {5: <5s} {6: <20s} {7: <45s} {8: <20s} {9: <20s}"
141    thread_ptr_str = str("{0: <#020x}".format(thread))
142    if int(thread.static_param) :
143        thread_ptr_str+="[WQ]"
144    thread_id = hex(thread.thread_id)
145    thread_name = ''
146    processor = hex(thread.last_processor)
147    sched_priority = str(int(thread.sched_pri))
148
149    io_policy_str = ""
150    if int(thread.uthread) != 0:
151        uthread = Cast(thread.uthread, 'uthread *')
152        #check for thread name
153        if int(uthread.pth_name) != 0 :
154            th_name_strval = Cast(uthread.pth_name, 'char *')
155            if len(str(th_name_strval)) > 0 :
156                thread_name = str(th_name_strval)
157
158        #check for io_policy flags
159        if int(uthread.uu_flag) & 0x400:
160            io_policy_str+='RAGE '
161
162        #now flags for task_policy
163
164        io_policy_str = ""
165
166        if int(thread.effective_policy.darwinbg) != 0:
167            io_policy_str += "B"
168        if int(thread.effective_policy.lowpri_cpu) != 0:
169            io_policy_str += "L"
170
171        if int(thread.effective_policy.io_tier) != 0:
172            io_policy_str += "T"
173        if int(thread.effective_policy.io_passive) != 0:
174            io_policy_str += "P"
175        if int(thread.effective_policy.terminated) != 0:
176            io_policy_str += "D"
177
178    state = int(thread.state)
179    thread_state_chars = {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'}
180    state_str = ''
181    state_str += thread_state_chars[int(state & 0x1)]
182    state_str += thread_state_chars[int(state & 0x2)]
183    state_str += thread_state_chars[int(state & 0x4)]
184    state_str += thread_state_chars[int(state & 0x8)]
185    state_str += thread_state_chars[int(state & 0x10)]
186    state_str += thread_state_chars[int(state & 0x20)]
187    state_str += thread_state_chars[int(state & 0x40)]
188    state_str += thread_state_chars[int(state & 0x80)]
189
190    #wait queue information
191    wait_queue_str = ''
192    wait_event_str = ''
193    wait_message = ''
194    if ( state & 0x1 ) != 0:
195        #we need to look at the waitqueue as well
196        wait_queue_str = str("{0: <#020x}".format(int(hex(thread.wait_queue), 16)))
197        wait_event_str = str("{0: <#020x}".format(int(hex(thread.wait_event), 16)))
198        wait_event_str_sym = kern.Symbolicate(int(hex(thread.wait_event), 16))
199        if len(wait_event_str_sym) > 0:
200            wait_event_str = wait_event_str.strip() + " <" + wait_event_str_sym + ">"
201        if int(thread.uthread) != 0 :
202            uthread = Cast(thread.uthread, 'uthread *')
203            if int(uthread.uu_wmesg) != 0:
204                wait_message = str(Cast(uthread.uu_wmesg, 'char *'))
205
206    out_string += format_string.format(thread_ptr_str, thread_id, processor, sched_priority, io_policy_str, state_str, wait_queue_str, wait_event_str, wait_message, thread_name )
207    return out_string
208
209
210
211@lldb_type_summary(['proc'])
212@header("{0: >6s} {1: ^20s} {2: >14s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command"))
213def GetProcSummary(proc):
214    """ Summarize the process data.
215        params:
216          proc : value - value representaitng a proc * in kernel
217        returns:
218          str - string summary of the process.
219    """
220    out_string = ""
221    format_string= "{0: >6d} {1: >#020x} {2: >14s} {3: >2d} {4: >2d} {5: >2d}    {6: <20s}"
222    pval = proc.GetSBValue()
223    #code.interact(local=locals())
224    if str(pval.GetType()) != str(gettype('proc *')) :
225        return "Unknown type " + str(pval.GetType()) + " " + str(hex(proc))
226    if not proc:
227        out_string += "Process " + hex(proc) + " is not valid."
228        return out_string
229    pid = int(proc.p_pid)
230    proc_addr = int(hex(proc), 16)
231    proc_rage_str = ""
232    if int(proc.p_lflag) & 0x400000 :
233        proc_rage_str = "RAGE"
234
235    task = Cast(proc.task, 'task *')
236
237    io_policy_str = ""
238
239    if int(task.effective_policy.darwinbg) != 0:
240        io_policy_str += "B"
241    if int(task.effective_policy.lowpri_cpu) != 0:
242        io_policy_str += "L"
243
244    if int(task.effective_policy.io_tier) != 0:
245        io_policy_str += "T"
246    if int(task.effective_policy.io_passive) != 0:
247        io_policy_str += "P"
248    if int(task.effective_policy.terminated) != 0:
249        io_policy_str += "D"
250
251    if int(task.effective_policy.t_suspended) != 0:
252        io_policy_str += "S"
253    if int(task.effective_policy.t_latency_qos) != 0:
254        io_policy_str += "Q"
255    if int(task.effective_policy.t_sup_active) != 0:
256        io_policy_str += "A"
257
258
259    try:
260        work_queue = Cast(proc.p_wqptr, 'workqueue *')
261        if proc.p_wqptr != 0 :
262            wq_num_threads = int(work_queue.wq_nthreads)
263            wq_idle_threads = int(work_queue.wq_thidlecount)
264            wq_req_threads = int(work_queue.wq_reqcount)
265        else:
266            wq_num_threads = 0
267            wq_idle_threads = 0
268            wq_req_threads = 0
269    except:
270        wq_num_threads = -1
271        wq_idle_threads = -1
272        wq_req_threads = -1
273    process_name = str(proc.p_comm)
274    out_string += format_string.format(pid, proc_addr, " ".join([proc_rage_str, io_policy_str]), wq_num_threads, wq_idle_threads, wq_req_threads, process_name)
275    return out_string
276
277# Macro: showtask
278
279@lldb_command('showtask', 'F:')
280def ShowTask(cmd_args=None, cmd_options={}):
281    """  Routine to print a summary listing of given task
282         Usage: showtask <address of task>
283         or   : showtask -F <name of task>
284    """
285    task_list = []
286    if "-F" in cmd_options:
287        task_list = FindTasksByName(cmd_options['-F'])
288    else:
289        if not cmd_args:
290            raise ArgumentError("Invalid arguments passed.")
291
292        tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
293        if not tval:
294            raise ("Unknown arguments: %r" % cmd_args)
295        task_list.append(tval)
296
297    for tval in task_list:
298        print GetTaskSummary.header + " " + GetProcSummary.header
299        pval = Cast(tval.bsd_info, 'proc *')
300        print GetTaskSummary(tval) +" "+ GetProcSummary(pval)
301
302# EndMacro: showtask
303
304# Macro: showpid
305
306@lldb_command('showpid')
307def ShowPid(cmd_args=None):
308    """  Routine to print a summary listing of task corresponding to given pid
309         Usage: showpid <pid value>
310    """
311    if not cmd_args:
312        print "No arguments passed"
313        print ShowPid.__doc__
314        return False
315    pidval = ArgumentStringToInt(cmd_args[0])
316    for t in kern.tasks:
317        pval = Cast(t.bsd_info, 'proc *')
318        if pval and pval.p_pid == pidval:
319            print GetTaskSummary.header + " " + GetProcSummary.header
320            print GetTaskSummary(t) + " " + GetProcSummary(pval)
321            break
322
323# EndMacro: showpid
324
325# Macro: showproc
326
327@lldb_command('showproc')
328def ShowProc(cmd_args=None):
329    """  Routine to print a summary listing of task corresponding to given proc
330         Usage: showproc <address of proc>
331    """
332    if not cmd_args:
333        print "No arguments passed"
334        print ShowProc.__doc__
335        return False
336    pval = kern.GetValueFromAddress(cmd_args[0], 'proc *')
337    if not pval:
338        print "unknown arguments:", str(cmd_args)
339        return False
340    print GetTaskSummary.header + " " + GetProcSummary.header
341    tval = Cast(pval.task, 'task *')
342    print GetTaskSummary(tval) +" "+ GetProcSummary(pval)
343
344# EndMacro: showproc
345
346# Macro: showprocinfo
347
348@lldb_command('showprocinfo')
349def ShowProcInfo(cmd_args=None):
350    """  Routine to display name, pid, parent & task for the given proc address
351         It also shows the Cred, Flags and state of the process
352         Usage: showprocinfo <address of proc>
353    """
354    if not cmd_args:
355        print "No arguments passed"
356        print ShowProcInfo.__doc__
357        return False
358    pval = kern.GetValueFromAddress(cmd_args[0], 'proc *')
359    if not pval:
360        print "unknown arguments:", str(cmd_args)
361        return False
362    print GetProcInfo(pval)
363
364# EndMacro: showprocinfo
365
366#Macro: showprocfiles
367
368@lldb_command('showprocfiles')
369def ShowProcFiles(cmd_args=None):
370    """ Given a proc_t pointer, display the list of open file descriptors for the referenced process.
371        Usage: showprocfiles <proc_t>
372    """
373    if not cmd_args:
374        print ShowProcFiles.__doc__
375        return
376    proc = kern.GetValueFromAddress(cmd_args[0], 'proc_t')
377    proc_filedesc = proc.p_fd
378    proc_lastfile = unsigned(proc_filedesc.fd_lastfile)
379    proc_ofiles = proc_filedesc.fd_ofiles
380    if unsigned(proc_ofiles) == 0:
381        print 'No open files for proc {0: <s}'.format(cmd_args[0])
382        return
383    print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')
384    print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")
385    count = 0
386
387    # Filetype map
388    filetype_dict = {
389                1: 'VNODE',
390                2: 'SOCKET',
391                3: 'PSXSHM',
392                4: 'PSXSEM',
393                5: 'KQUEUE',
394                6: 'PIPE',
395                7: 'FSEVENTS'
396              }
397
398    while count <= proc_lastfile:
399        if unsigned(proc_ofiles[count]) != 0:
400            out_str = ''
401            proc_fd_flags = proc_ofiles[count].f_flags
402            proc_fd_fglob = proc_ofiles[count].f_fglob
403            out_str += "{0: <5d} ".format(count)
404            out_str += "{0: <#18x} ".format(unsigned(proc_fd_fglob))
405            out_str += "0x{0:0>8x} ".format(unsigned(proc_fd_flags))
406            proc_fd_ftype = unsigned(proc_fd_fglob.fg_ops.fo_type)
407            if proc_fd_ftype in filetype_dict:
408                out_str += "{0: <8s} ".format(filetype_dict[proc_fd_ftype])
409            else:
410                out_str += "?: {0: <5d} ".format(proc_fd_ftype)
411            out_str += "{0: <#18x} ".format(unsigned(proc_fd_fglob.fg_data))
412            if proc_fd_ftype == 1:
413                fd_name = Cast(proc_fd_fglob.fg_data, 'struct vnode *').v_name
414                out_str += "{0: <64s}".format(fd_name)
415            out_str += "\n"
416            print out_str
417        count += 1
418
419#EndMacro: showprocfiles
420
421#Macro: showtty
422
423@lldb_command('showtty')
424def ShowTTY(cmd_args=None):
425    """ Display information about a struct tty
426        Usage: showtty <tty struct>
427    """
428    if not cmd_args:
429        print ShowTTY.__doc__
430        return
431
432    tty = kern.GetValueFromAddress(cmd_args[0], 'struct tty *')
433    print "TTY structure at:              {0: <s}".format(cmd_args[0])
434    print "Last input to raw queue:       {0: <#18x} \"{1: <s}\"".format(unsigned(tty.t_rawq.c_cs), tty.t_rawq.c_cs)
435    print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty.t_canq.c_cs), tty.t_canq.c_cs)
436    print "Last output data:              {0: <#18x} \"{1: <s}\"".format(unsigned(tty.t_outq.c_cs), tty.t_outq.c_cs)
437    tty_state_info = [
438                  ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'],
439                  ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'],
440                  ['', 'TS_BUSY (Draining output)'],
441                  ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'],
442                  ['', 'TS_FLUSH (Outq has been flushed during DMA)'],
443                  ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'],
444                  ['', 'TS_TBLOCK (Further input blocked)'],
445                  ['', 'TS_TIMEOUT (Wait for output char processing)'],
446                  ['', 'TS_TTSTOP (Output paused)'],
447                  ['', 'TS_WOPEN (Open in progress)'],
448                  ['', 'TS_XCLUDE (Tty requires exclusivity)'],
449                  ['', 'TS_BKSL (State for lowercase \\ work)'],
450                  ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'],
451                  ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'],
452                  ['', 'TS_LNCH (Next character is literal)'],
453                  ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'],
454                  ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'],
455                  ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'],
456                  ['', 'TS_SNOOP (Device is being snooped on)'],
457                  ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'],
458                  ['', 'TS_ZOMBIE (Connection lost)'],
459                  ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'],
460                  ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'],
461                  ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)']
462                ]
463    index = 0
464    mask = 0x1
465    tty_state = unsigned(tty.t_state)
466    print "State:"
467    while index < 24:
468        if tty_state & mask != 0:
469            if len(tty_state_info[index][1]) > 0:
470                print '\t' + tty_state_info[index][1]
471        else:
472            if len(tty_state_info[index][0]) > 0:
473                print '\t' + tty_state_info[index][0]
474        index += 1
475        mask = mask << 1
476    print "Flags:                    0x{0:0>8x}".format(unsigned(tty.t_flags))
477    print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty.t_pgrp))
478    print "Enclosing session:        0x{0:0>16x}".format(unsigned(tty.t_session))
479    print "Termios:"
480    print "\tInput Flags:   0x{0:0>8x}".format(unsigned(tty.t_termios.c_iflag))
481    print "\tOutput Flags:  0x{0:0>8x}".format(unsigned(tty.t_termios.c_oflag))
482    print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty.t_termios.c_cflag))
483    print "\tLocal Flags:   0x{0:0>8x}".format(unsigned(tty.t_termios.c_lflag))
484    print "\tInput Speed:   {0: <8d}".format(tty.t_termios.c_ispeed)
485    print "\tOutput Speed:  {0: <8d}".format(tty.t_termios.c_ospeed)
486    print "High Watermark: {0: <d} bytes".format(tty.t_hiwat)
487    print "Low Watermark : {0: <d} bytes".format(tty.t_lowat)
488
489#EndMacro: showtty
490
491#Macro: dumpcallqueue
492
493@lldb_command('dumpcallqueue')
494def DumpCallQueue(cmd_args=None):
495    """ Displays the contents of the specified call_entry queue.
496        Usage: dumpcallqueue <queue_head_t *>
497    """
498    if not cmd_args:
499        print DumpCallQueue.__doc__
500        return
501    print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
502    callhead = kern.GetValueFromAddress(cmd_args[0], 'queue_head_t *')
503    count = 0
504    for callentry in IterateQueue(callhead, 'struct call_entry *',  'q_link'):
505        print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format(
506              unsigned(callentry), unsigned(callentry.param0), unsigned(callentry.param1),
507              unsigned(callentry.deadline), unsigned(callentry.func))
508        count += 1
509    print "{0: <d} entries!".format(count)
510
511#EndMacro: dumpcallqueue
512
513@lldb_command('showalltasks')
514def ShowAllTasks(cmd_args=None):
515    """  Routine to print a summary listing of all the tasks
516         wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
517         if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
518         io_policy -> RAGE  - rapid aging of vnodes requested
519                     NORM  - normal I/O explicitly requested (this is the default)
520                     PASS  - passive I/O requested (i.e. I/Os do not affect throttling decisions)
521                     THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
522    """
523    global kern
524    print GetTaskSummary.header + " " + GetProcSummary.header
525    for t in kern.tasks:
526        pval = Cast(t.bsd_info, 'proc *')
527        print GetTaskSummary(t) +" "+ GetProcSummary(pval)
528
529@lldb_command('showterminatedtasks')
530def ShowTerminatedTasks(cmd_args=None):
531    """  Routine to print a summary listing of all the terminated tasks
532         wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
533         if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
534         io_policy -> RAGE  - rapid aging of vnodes requested
535                     NORM  - normal I/O explicitly requested (this is the default)
536                     PASS  - passive I/O requested (i.e. I/Os do not affect throttling decisions)
537                     THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
538        syntax: (lldb)showallterminatedtasks
539    """
540    global kern
541    print GetTaskSummary.header + " " + GetProcSummary.header
542    for t in kern.terminated_tasks:
543        pval = Cast(t.bsd_info, 'proc *')
544        print GetTaskSummary(t) +" "+ GetProcSummary(pval)
545    return True
546
547# Macro: showtaskstacks
548
549def ShowTaskStacks(task):
550    """ Print a task with summary and stack information for each of its threads
551    """
552    global kern
553    print GetTaskSummary.header + " " + GetProcSummary.header
554    pval = Cast(task.bsd_info, 'proc *')
555    print GetTaskSummary(task) + " " + GetProcSummary(pval)
556    for th in IterateQueue(task.threads, 'thread *', 'task_threads'):
557        print "  " + GetThreadSummary.header
558        print "  " + GetThreadSummary(th)
559        print GetThreadBackTrace(th, prefix="    ") + "\n"
560
561def FindTasksByName(searchstr, ignore_case=True):
562    """ Search the list of tasks by name.
563        params:
564            searchstr: str - a regex like string to search for task
565            ignore_case: bool - If False then exact matching will be enforced
566        returns:
567            [] - array of task object. Empty if not found any
568    """
569    re_options = 0
570    if ignore_case:
571        re_options = re.IGNORECASE
572    search_regex = re.compile(searchstr, re_options)
573    retval = []
574    for t in kern.tasks:
575        pval = Cast(t.bsd_info, "proc *")
576        process_name = "{:s}".format(pval.p_comm)
577        if search_regex.search(process_name):
578            retval.append(t)
579    return retval
580
581@lldb_command('showtaskstacks', 'F:')
582def ShowTaskStacksCmdHelper(cmd_args=None, cmd_options={}):
583    """ Routine to print out the stack for each thread in a task
584        Usage: showtaskstacks <0xaddress of task>
585           or: showtaskstacks -F launchd
586    """
587
588    if "-F" in cmd_options:
589        find_task_str = cmd_options["-F"]
590        task_list = FindTasksByName(find_task_str)
591        for tval in task_list:
592            ShowTaskStacks(tval)
593        return
594
595    if not cmd_args:
596        raise ArgumentError("No arguments passed")
597
598    tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
599    if not tval:
600        raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args)))
601    else:
602        ShowTaskStacks(tval)
603        return
604
605# EndMacro: showtaskstacks
606
607@lldb_command('showallthreads')
608def ShowAllThreads(cmd_args = None):
609    """ Display info about all threads in the system
610    """
611    for t in kern.tasks:
612        ShowTaskThreads([str(int(t))])
613        print " \n"
614    return
615
616@lldb_command('showtaskthreads', "F:")
617def ShowTaskThreads(cmd_args = None, cmd_options={}):
618    """ Display thread information for a given task
619        Usage: showtaskthreads <0xaddress of task>
620           or: showtaskthreads -F <name>
621    """
622    task_list = []
623    if "-F" in cmd_options:
624        task_list = FindTasksByName(cmd_options["-F"])
625    elif cmd_args:
626        t = kern.GetValueFromAddress(cmd_args[0], 'task *')
627        task_list.append(t)
628    else:
629        raise ArgumentError("No arguments passed")
630
631    for task in task_list:
632        print GetTaskSummary.header + " " + GetProcSummary.header
633        pval = Cast(task.bsd_info, 'proc *')
634        print GetTaskSummary(task) + " " + GetProcSummary(pval)
635        print "\t" + GetThreadSummary.header
636        for thval in IterateQueue(task.threads, 'thread *', 'task_threads'):
637            print "\t" + GetThreadSummary(thval)
638    return
639
640@lldb_command('showact')
641def ShowAct(cmd_args=None):
642    """ Routine to print out the state of a specific thread.
643        usage: showact <activation>
644    """
645    if cmd_args == None or len(cmd_args) < 1:
646        print "No arguments passed"
647        print ShowAct.__doc__
648        return False
649    threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *')
650    print GetThreadSummary.header
651    print GetThreadSummary(threadval)
652
653@lldb_command('showactstack')
654def ShowActStack(cmd_args=None):
655    """ Routine to print out the stack of a specific thread.
656        usage:  showactstack <activation>
657    """
658    if cmd_args == None or len(cmd_args) < 1:
659        print "No arguments passed"
660        print ShowAct.__doc__.strip()
661        return False
662    threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *')
663    print GetThreadSummary.header
664    print GetThreadSummary(threadval)
665    print GetThreadBackTrace(threadval, prefix="\t")
666    return
667
668@lldb_command('switchtoact')
669def SwitchToAct(cmd_args=None):
670    """ Switch to different context specified by activation
671    This command allows gdb to examine the execution context and call
672    stack for the specified activation. For example, to view the backtrace
673    for an activation issue "switchtoact <address>", followed by "bt".
674    Before resuming execution, issue a "resetctx" command, to
675    return to the original execution context.
676    """
677    if cmd_args == None or len(cmd_args) < 1:
678        print "No arguments passed"
679        print SwitchToAct.__doc__.strip()
680        return False
681    thval = kern.GetValueFromAddress(cmd_args[0], 'thread *')
682    lldbthread = GetLLDBThreadForKernelThread(thval)
683    print GetThreadSummary.header
684    print GetThreadSummary(thval)
685    LazyTarget.GetProcess().selected_thread = lldbthread
686    if not LazyTarget.GetProcess().SetSelectedThread(lldbthread):
687        print "Failed to switch thread."
688    return
689# Macro: showallstacks
690@lldb_command('showallstacks')
691def ShowAllStacks(cmd_args=None):
692    """Routine to print out the stack for each thread in the system.
693    """
694    for t in kern.tasks:
695        ShowTaskStacks(t)
696        print " \n"
697    return
698
699# EndMacro: showallstacks
700
701# Macro: showcurrentstacks
702@lldb_command('showcurrentstacks')
703def ShowCurrentStacks(cmd_args=None):
704    """ Routine to print out the thread running on each cpu (incl. its stack)
705    """
706    processor_list = kern.GetGlobalVariable('processor_list')
707    current_processor = processor_list
708    while unsigned(current_processor) > 0:
709        print "\nProcessor {: <#020x} State {: <d} (cpu_id {: >#04x})".format(current_processor, int(current_processor.state), int(current_processor.cpu_id))
710        active_thread = current_processor.active_thread
711        if unsigned(active_thread) != 0 :
712            task_val = active_thread.task
713            proc_val = Cast(task_val.bsd_info, 'proc *')
714            print GetTaskSummary.header + " " + GetProcSummary.header
715            print GetTaskSummary(task_val) + " " + GetProcSummary(proc_val)
716            print "\t" + GetThreadSummary.header
717            print "\t" + GetThreadSummary(active_thread)
718            print "\tBacktrace:"
719            print GetThreadBackTrace(active_thread, prefix="\t")
720        current_processor = current_processor.processor_list
721    return
722# EndMacro: showcurrentstacks
723
724@lldb_command('showcurrentthreads')
725def ShowCurrentThreads(cmd_args=None):
726    """ Display info about threads running on each cpu """
727    processor_list = kern.GetGlobalVariable('processor_list')
728    current_processor = processor_list
729    while unsigned(current_processor) > 0:
730        print "Processor {: <#020x} State {: <d} (cpu_id {: >#04x})".format(current_processor, int(current_processor.state), int(current_processor.cpu_id))
731        active_thread = current_processor.active_thread
732        if unsigned(active_thread) != 0 :
733            task_val = active_thread.task
734            proc_val = Cast(task_val.bsd_info, 'proc *')
735            print GetTaskSummary.header + " " + GetProcSummary.header
736            print GetTaskSummary(task_val) + " " + GetProcSummary(proc_val)
737            print "\t" + GetThreadSummary.header
738            print "\t" + GetThreadSummary(active_thread)
739        current_processor = current_processor.processor_list
740    return
741
742def GetFullBackTrace(frame_addr, verbosity = vHUMAN, prefix = ""):
743    """ Get backtrace across interrupt context.
744        params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7)
745                prefix - str - prefix for each line of output.
746
747    """
748    out_string = ""
749    bt_count = 0
750    frame_ptr = frame_addr
751    previous_frame_ptr = 0
752    # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
753    mh_execute_addr = int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
754    while frame_ptr and frame_ptr != previous_frame_ptr and bt_count < 128:
755        if (kern.arch != 'arm' and frame_ptr < mh_execute_addr) or (kern.arch == 'arm' and frame_ptr > mh_execute_addr):
756            break
757        pc_val = kern.GetValueFromAddress(frame_ptr + kern.ptrsize,'uintptr_t *')
758        pc_val = unsigned(dereference(pc_val))
759        out_string += prefix + GetSourceInformationForAddress(pc_val) + "\n"
760        bt_count +=1
761        previous_frame_ptr = frame_ptr
762        frame_val = kern.GetValueFromAddress((frame_ptr), 'uintptr_t *')
763        if unsigned(frame_val) == 0:
764            break
765        frame_ptr = unsigned(dereference(frame_val))
766
767    return out_string
768
769@lldb_command('fullbt')
770def FullBackTrace(cmd_args=[]):
771    """ Show full backtrace across the interrupt boundary.
772        Syntax: fullbt <frame ptr>
773        Example: kfullbt  `$rbp`
774    """
775    if len(cmd_args) < 1:
776        print FullBackTrace.__doc__
777        return False
778    print GetFullBackTrace(ArgumentStringToInt(cmd_args[0]), prefix="\t")
779
780
781@lldb_command('symbolicate')
782def SymbolicateAddress(cmd_args=[]):
783    """ Symbolicate an address for symbol information from loaded symbols
784        Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr"
785    """
786    if len(cmd_args) < 1:
787        print "Invalid address.\nSyntax: symbolicate <address>"
788        return False
789    print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args[0]))
790    return True
791
792@lldb_command('showinitchild')
793def ShowInitChild(cmd_args=None):
794    """ Routine to print out all processes in the system
795        which are children of init process
796    """
797    headp = kern.globals.initproc.p_children
798    for pp in IterateListEntry(headp, 'struct proc *', 'p_sibling'):
799        print GetProcInfo(pp)
800    return
801
802@lldb_command('showproctree')
803def ShowProcTree(cmd_args=None):
804    """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes.
805        If no argument is given, showproctree will print all the processes in the system.
806        If pid is specified, showproctree prints all the descendants of the indicated process
807    """
808    search_pid = 0
809    if cmd_args:
810        search_pid = ArgumentStringToInt(cmd_args[0])
811
812    if search_pid < 0:
813        print "pid specified must be a positive number"
814        print ShowProcTree.__doc__
815        return
816
817    hdr_format = "{0: <6s} {1: <14s} {2: <9s}\n"
818    out_string = hdr_format.format("PID", "PROCESS", "POINTER")
819    out_string += hdr_format.format('='*3, '='*7, '='*7)
820    proc = GetProcForPid(search_pid)
821    out_string += "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc.p_ppid, proc.p_pptr.p_comm, unsigned(proc.p_pptr))
822    out_string += "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc.p_pid, proc.p_comm, unsigned(proc))
823    print out_string
824    ShowProcTreeRecurse(proc, "|  ")
825
826    return
827
828def ShowProcTreeRecurse(proc, prefix=""):
829    """ Prints descendants of a given proc in hierarchial tree form
830        params:
831            proc  : core.value representing a struct proc * in the kernel
832        returns:
833            str   : String containing info about a given proc and its descendants in tree form
834    """
835    if proc.p_childrencnt > 0:
836        head_ptr = proc.p_children.lh_first
837
838        for p in IterateListEntry(proc.p_children, 'struct proc *', 'p_sibling'):
839            print prefix + "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p.p_pid, p.p_comm, unsigned(p))
840            ShowProcTreeRecurse(p, prefix + "|  ")
841
842@lldb_command('showthreadfortid')
843def ShowThreadForTid(cmd_args=None):
844    """ The thread structure contains a unique thread_id value for each thread.
845        This command is used to retrieve the address of the thread structure(thread_t)
846        corresponding to a given thread_id.
847    """
848    if not cmd_args:
849        print "Please provide thread_t whose tid you'd like to look up"
850        print ShowThreadForTid.__doc__
851        return
852    search_tid = ArgumentStringToInt(cmd_args[0])
853    for taskp in kern.tasks:
854        for actp in IterateQueue(taskp.threads, 'struct thread *', 'task_threads'):
855            if search_tid == int(actp.thread_id):
856                print "Found {0: #019x}".format(actp)
857                print GetThreadSummary.header
858                print GetThreadSummary(actp)
859                return
860    print "Not a valid thread_id"
861
862# Macro: showallprocessors
863
864def GetProcessorSummary(processor):
865    """ Internal function to print summary of processor
866        params: processor - value representing struct processor *
867        return: str - representing the details of given processor
868    """
869    out_str = "Processor  {: <#012x} ".format(processor)
870    out_str += "State {:d} (cpu_id {:#x})\n".format(processor.state, processor.cpu_id)
871    return out_str
872
873def GetRunQSummary(runq):
874    """ Internal function to print summary of run_queue
875        params: runq - value representing struct run_queue *
876        return: str - representing the details of given run_queue
877    """
878    out_str = "    Priority Run Queue Info: Count {: <10d}\n".format(runq.count)
879    runq_queue_i = 0
880    runq_queue_count = sizeof(runq.queues)/sizeof(runq.queues[0])
881    while runq.count and (runq_queue_i < runq_queue_count):
882        runq_queue_head = addressof(runq.queues[runq_queue_i])
883        runq_queue_p = runq_queue_head.next
884        if unsigned(runq_queue_p) != unsigned(runq_queue_head):
885            runq_queue_this_count = 0
886            while runq_queue_p != runq_queue_head:
887                runq_queue_this_count = runq_queue_this_count + 1
888                runq_queue_p_thread = Cast(runq_queue_p, 'thread_t')
889                # Get the task information
890                out_str += GetTaskSummary.header + " " + GetProcSummary.header
891                pval = Cast(runq_queue_p_thread.task.bsd_info, 'proc *')
892                out_str += GetTaskSummary(runq_queue_p_thread.task) +" "+ GetProcSummary(pval)
893                # Get the thread information with related stack traces
894                out_str += GetThreadSummary.header + GetThreadSummary(runq_queue_p_thread)
895                out_str += GetThreadBackTrace(LazyTarget.GetProcess().GetThreadByID(int(runq_queue_p_thread.thread_id)),
896                    prefix="\t")
897                runq_queue_p = runq_queue_p.next
898
899            out_str += "      Queue Priority {: <3d} [{: <#012x}] Count {:d}\n".format(runq_queue_i,
900                runq_queue_head, runq_queue_this_count)
901
902        runq_queue_i = runq_queue_i + 1
903    return out_str
904
905def GetGrrrSummary(grrr_runq):
906    """ Internal function to print summary of grrr_run_queue
907        params: grrr_runq - value representing struct grrr_run_queue *
908        return: str - representing the details of given grrr_run_queue
909    """
910    out_str = "    GRRR Info: Count {: <10d} Weight {: <10d} Current Group {: <#012x}\n".format(grrr_runq.count,
911        grrr_runq.weight, grrr_runq.current_group)
912    grrr_group_i = 0
913    grrr_group_count = sizeof(grrr_runq.groups)/sizeof(grrr_runq.groups[0])
914    while grrr_runq.count and (grrr_group_i < grrr_group_count):
915        grrr_group = addressof(grrr_runq.groups[grrr_group_i])
916        runq_queue_p = runq_queue_head.next
917        if grrr_group.count > 0:
918            out_str += "      Group {: <3d} [{: <#012x}] ".format(grrr_group.index, grrr_group)
919            out_str += "Count {:d} Weight {:d}\n".format(grrr_group.count, grrr_group.weight)
920            grrr_group_client_head = addressof(grrr_group.clients)
921            grrr_group_client = grrr_group_client_head.next
922            while grrr_group_client != grrr_group_client_head:
923                grrr_group_client_thread = Cast(grrr_group_client, 'thread_t')
924                # Get the task information
925                out_str += GetTaskSummary.header + " " + GetProcSummary.header
926                pval = Cast(grrr_group_client_thread.task.bsd_info, 'proc *')
927                out_str += GetTaskSummary(grrr_group_client_thread.task) +" "+ GetProcSummary(pval)
928                # Get the thread information with related stack traces
929                out_str += GetThreadSummary.header + GetThreadSummary(grrr_group_client_thread)
930                out_str += GetThreadBackTrace(LazyTarget.GetProcess().GetThreadByID(int(grrr_group_client_thread.thread_id)),
931                    prefix="\t")
932                grrr_group_client = grrr_group_client.next
933        grrr_group_i = grrr_group_i + 1
934    return out_str
935
936@lldb_command('showallprocessors')
937def ShowAllProcessors(cmd_args=None):
938    """  Routine to print information of all psets and processors
939         Usage: showallprocessors
940    """
941    pset = addressof(kern.globals.pset0)
942    show_grrr = 0
943    show_priority_runq = 0
944    show_priority_pset_runq = 0
945    show_fairshare_grrr = 0
946    show_fairshare_list = 0
947    sched_enum_val = kern.globals._sched_enum
948
949    if sched_enum_val == 1:
950        show_priority_runq = 1
951        show_fairshare_list = 1
952    elif sched_enum_val == 2:
953        show_priority_pset_runq = 1
954        show_fairshare_list = 1
955    elif sched_enum_val == 4:
956        show_grrr = 1
957        show_fairshare_grrr = 1
958    elif sched_enum_val == 5:
959        show_priority_runq = 1
960        show_fairshare_list = 1
961    elif sched_enum_val == 6:
962        show_priority_pset_runq = 1
963        show_fairshare_list = 1
964
965    out_str = ''
966    while pset:
967        out_str += "Processor Set  {: <#012x} Count {:d} (cpu_id {:<#x}-{:<#x})\n".format(pset,
968            pset.cpu_set_count, pset.cpu_set_low, pset.cpu_set_hi)
969        out_str += "  Active Processors:\n"
970        active_queue_head = addressof(pset.active_queue)
971        active_elt = active_queue_head.next
972        while active_elt != active_queue_head:
973            processor = Cast(active_elt, 'processor *')
974            out_str += "    "
975            out_str += GetProcessorSummary(processor)
976            if show_priority_runq:
977                runq = addressof(processor.runq)
978                out_str += GetRunQSummary(runq)
979            if show_grrr:
980                grrr_runq = addressof(processor.grrr_runq)
981                out_str += GetGrrrSummary(grrr_runq)
982
983            if processor.processor_meta and (processor.processor_meta.primary ==
984                processor):
985                processor_meta_idle_head = addressof(processor.processor_meta.idle_queue)
986                processor_meta_idle = processor_meta_idle_head.next
987                while processor_meta_idle != processor_meta_idle_head:
988                    out_str += "      Idle Meta Processor: "
989                    out_str += GetProcessorSummary(processor_meta_idle)
990                    processor_meta_idle = processor_meta_idle.next
991            active_elt = active_elt.next
992
993        out_str += "  Idle Processors:\n"
994        idle_queue_head = addressof(pset.idle_queue)
995        idle_elt = idle_queue_head.next
996        while idle_elt != idle_queue_head:
997            processor = Cast(idle_elt, 'processor *')
998            out_str += "    "
999            out_str += GetProcessorSummary(processor)
1000
1001            if processor.processor_meta and (processor.processor_meta.primary ==
1002                processor):
1003                processor_meta_idle_head = addressof(processor.processor_meta.idle_queue)
1004                processor_meta_idle = processor_meta_idle_head.next
1005                while processor_meta_idle != processor_meta_idle_head:
1006                    out_str += "      Idle Meta Processor: "
1007                    out_str += GetProcessorSummary(processor_meta_idle)
1008                    processor_meta_idle = processor_meta_idle.next
1009            idle_elt = idle_elt.next
1010
1011        if show_priority_pset_runq:
1012            runq = addressof(pset.pset_runq)
1013            out_str += "\n" + GetRunQSummary(runq)
1014        pset = pset.pset_list
1015
1016    out_str += "\nRealtime Queue Count {:d}\n".format(kern.globals.rt_runq.count)
1017    rt_runq_head = addressof(kern.globals.rt_runq.queue)
1018    rt_runq_local = rt_runq_head.next
1019    while rt_runq_local != rt_runq_head:
1020        rt_runq_thread = Cast(rt_runq_local, 'thread *')
1021        out_str += ShowTask([unsigned(rt_runq_thread.task)])
1022        out_str += ShowAct([unsigned(rt_runq_thread)])
1023        rt_runq_local = rt_runq_local.next
1024
1025    out_str += "\n"
1026    if show_fairshare_list:
1027        out_str += "Fair Share Queue Count {:d}\n".format(kern.globals.fs_runq.count)
1028        fs_runq_head = addressof(kern.globals.fs_runq.queue)
1029        fs_runq_local = fs_runq_head.next
1030        while fs_runq_local != fs_runq_head:
1031            fs_runq_thread = Cast(fs_runq, 'thread *')
1032            out_str += ShowTask([unsigned(fs_runq_thread.task)])
1033            out_str += ShowAct([unsigned(rt_runq_thread)])
1034            fs_runq_local = fs_runq_local.next
1035    if show_fairshare_grrr:
1036        out_str += "Fair Share Queue Count {:d}\n".format(kern.globals.fs_grrr_runq.count)
1037        fs_grrr = addressof(kern.globals.fs_grrr_runq)
1038        out_str += GetGrrrSummary(fs_grrr)
1039
1040    print out_str
1041# EndMacro: showallprocessors
1042
1043def GetLedgerEntrySummary(ledger_template, ledger, i):
1044    """ Internal function to get internals of a ledger entry (*not* a ledger itself)
1045        params: ledger_template - value representing struct ledger_template_t for the task or thread
1046                ledger - value representing struct ledger_entry *
1047        return: str - formatted output information of ledger entries
1048    """
1049    ledger_limit_infinity = (uint64_t(0x1).value << 63) - 1
1050    lf_refill_scheduled = 0x0400
1051    lf_tracking_max = 0x4000
1052
1053    out_str = ''
1054    now = kern.globals.sched_tick / 20
1055    lim_pct = 0
1056
1057    out_str += "{: >25s} {:<d}:".format(ledger_template.lt_entries[i].et_key, i)
1058    out_str += "{: >13d} ".format(ledger.le_credit - ledger.le_debit)
1059    if (ledger.le_flags & lf_tracking_max):
1060        out_str += "{:9d} {:5d} ".format(ledger._le.le_peaks[0].le_max, now - ledger._le.le_peaks[0].le_time)
1061        out_str += "{:9d} {:4d} ".format(ledger._le.le_peaks[1].le_max, now - ledger._le.le_peaks[1].le_time)
1062    else:
1063        out_str += "        -     -         -    - "
1064
1065    out_str += "{:12d} {:12d} ".format(ledger.le_credit, ledger.le_debit)
1066    if (unsigned(ledger.le_limit) != ledger_limit_infinity):
1067        out_str += "{:12d} ".format(unsigned(ledger.le_limit))
1068    else:
1069        out_str += "           - "
1070
1071    if (ledger.le_flags & lf_refill_scheduled):
1072        out_str += "{:15d} ".format(ledger._le.le_refill.le_refill_period)
1073    else:
1074        out_str += "              - "
1075
1076    if (ledger.le_flags & lf_refill_scheduled):
1077        out_str += "{:9d} ".format((unsigned(ledger.le_limit) * 100) / ledger._le.le_refill.le_refill_period)
1078    else:
1079        out_str += "        - "
1080
1081    if (unsigned(ledger.le_warn_level) != ledger_limit_infinity):
1082        out_str += "{:9d} ".format((unsigned(ledger.le_warn_level) * 100) / unsigned(ledger.le_limit))
1083    else:
1084        out_str += "        - "
1085
1086    if ((ledger.le_credit - ledger.le_debit) > unsigned(ledger.le_limit)):
1087        out_str += "    X "
1088    else:
1089        out_str += "      "
1090
1091    out_str += "{:#8x}\n".format(ledger.le_flags)
1092    return out_str
1093
1094def GetThreadLedgerSummary(thread_val):
1095    """ Internal function to get a summary of ledger entries for the given thread
1096        params: thread - value representing struct thread *
1097        return: str - formatted output information for ledger entries of the input thread
1098    """
1099    out_str = "   [{:#08x}]\n".format(thread_val)
1100    ledgerp = thread_val.t_threadledger
1101    if ledgerp:
1102        i = 0
1103        while i != ledgerp.l_template.lt_cnt:
1104            out_str += GetLedgerEntrySummary(kern.globals.thread_ledger_template,
1105                ledgerp.l_entries[i], i)
1106            i = i + 1
1107    return out_str
1108
1109@header("{0: <15s} {1: >9s} {2: <2s} {3: >12s} {4: >9s} {5: >6s} {6: >8s} {7: <10s} {8: <9s} \
1110    {9: <12s} {10: <7s} {11: <15s} {12: <8s} {13: <9s} {14: <6s} {15: >6s}".format(
1111    "task [thread]", "entry", "#", "balance", "peakA", "(age)", "peakB", "(age)", "credit",
1112     "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags"))
1113def GetTaskLedgers(task_val):
1114    """ Internal function to get summary of ledger entries from the task and its threads
1115        params: task_val - value representing struct task *
1116        return: str - formatted output information for ledger entries of the input task
1117    """
1118    out_str = ''
1119    task_ledgerp = task_val.ledger
1120    i = 0
1121    out_str += "{: #08x} ".format(task_val)
1122    pval = Cast(task_val.bsd_info, 'proc *')
1123    if pval:
1124        out_str += "{: <5s}:\n".format(pval.p_comm)
1125    else:
1126        out_str += "Invalid process:\n"
1127    while i != task_ledgerp.l_template.lt_cnt:
1128        out_str += GetLedgerEntrySummary(kern.globals.task_ledger_template, task_ledgerp.l_entries[i], i)
1129        i = i + 1
1130
1131    # Now walk threads
1132    for thval in IterateQueue(task_val.threads, 'thread *', 'task_threads'):
1133        out_str += GetThreadLedgerSummary(thval)
1134
1135    return out_str
1136
1137# Macro: showtaskledgers
1138
1139@lldb_command('showtaskledgers', 'F:')
1140def ShowTaskLedgers(cmd_args=None, cmd_options={}):
1141    """  Routine to print a summary  of ledger entries for the task and all of its threads
1142         Usage: showtaskledgers <address of task>
1143         or   : showtaskledgers -F <name of task>
1144    """
1145    if "-F" in cmd_options:
1146        task_list = FindTasksByName(cmd_options["-F"])
1147        for tval in task_list:
1148            print GetTaskLedgers.header
1149            print GetTaskLedgers(tval)
1150        return
1151
1152    if not cmd_args:
1153        raise ArgumentError("No arguments passed.")
1154    tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
1155    if not tval:
1156        raise ArgumentError("unknown arguments: %r" %cmd_args)
1157    print GetTaskLedgers.header
1158    print GetTaskLedgers(tval)
1159
1160# EndMacro: showtaskledgers
1161
1162# Macro: showalltaskledgers
1163
1164@lldb_command('showalltaskledgers')
1165def ShowAllTaskLedgers(cmd_args=None):
1166    """  Routine to print a summary  of ledger entries for all tasks and respective threads
1167         Usage: showalltaskledgers
1168    """
1169    for t in kern.tasks:
1170        task_val = unsigned(t)
1171        ShowTaskLedgers([task_val])
1172
1173# EndMacro: showalltaskledgers
1174
1175# Macro: showprocuuidpolicytable
1176
1177@lldb_type_summary(['proc_uuid_policy_entry'])
1178@header("{0: <36s} {1: <10s}".format("uuid", "flags"))
1179def GetProcUUIDPolicyEntrySummary(entry):
1180    """ Summarizes the important fields in proc_uuid_policy_entry structure.
1181        params: entry: value - value object representing an entry
1182        returns: str - summary of the entry
1183    """
1184    data = []
1185    for i in range(16):
1186        data.append(int(entry.uuid[i]))
1187    flags = unsigned(entry.flags)
1188    out_string = "{a[0]:02X}{a[1]:02X}{a[2]:02X}{a[3]:02X}-{a[4]:02X}{a[5]:02X}-{a[6]:02X}{a[7]:02X}-{a[8]:02X}{a[9]:02X}-{a[10]:02X}{a[11]:02X}{a[12]:02X}{a[13]:02X}{a[14]:02X}{a[15]:02X} 0x{b:0>8x}".format(a=data, b=flags)
1189    return out_string
1190
1191@lldb_command('showprocuuidpolicytable')
1192def ShowProcUUIDPolicyTable(cmd_args=None):
1193    """ Routine to print the proc UUID policy table
1194        Usage: showprocuuidpolicytable
1195    """
1196    hashslots = unsigned(kern.globals.proc_uuid_policy_hash_mask)
1197    print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary.header
1198    for i in range(0, hashslots+1):
1199        headp = addressof(kern.globals.proc_uuid_policy_hashtbl[i])
1200        entrynum = 0
1201        for entry in IterateListEntry(headp, 'struct proc_uuid_policy_entry *', 'entries'):
1202            print "{0: >2d}.{1: <5d} ".format(i, entrynum) + GetProcUUIDPolicyEntrySummary(entry)
1203            entrynum += 1
1204
1205
1206# EndMacro: showprocuuidpolicytable
1207
1208@lldb_command('showalltaskpolicy')
1209def ShowAllTaskPolicy(cmd_args=None):
1210    """
1211         Routine to print a summary listing of all the tasks
1212         wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1213         if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1214         io_policy -> RAGE  - rapid aging of vnodes requested
1215                     NORM  - normal I/O explicitly requested (this is the default)
1216                     PASS  - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1217                     THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1218    """
1219    global kern
1220    print GetTaskSummary.header + " " + GetProcSummary.header
1221    for t in kern.tasks:
1222        pval = Cast(t.bsd_info, 'proc *')
1223        print GetTaskSummary(t) +" "+ GetProcSummary(pval)
1224        requested_strings = [
1225                ["int_darwinbg",        "DBG-int"],
1226                ["ext_darwinbg",        "DBG-ext"],
1227                ["int_iotier",          "iotier-int"],
1228                ["ext_iotier",          "iotier-ext"],
1229                ["int_iopassive",       "passive-int"],
1230                ["ext_iopassive",       "passive-ext"],
1231                ["bg_iotier",           "bg-iotier"],
1232                ["terminated",          "terminated"],
1233                ["th_pidbind_bg",       "bg-pidbind"],
1234                ["th_workq_bg",         "bg-workq"],
1235                ["t_apptype",           "apptype"],
1236                ["t_boosted",           "boosted"],
1237                ["t_int_gpu_deny",      "gpudeny-int"],
1238                ["t_ext_gpu_deny",      "gpudeny-ext"],
1239                ["t_role",              "role"],
1240                ["t_visibility",        "vis"],
1241                ["t_tal_enabled",       "tal-enabled"],
1242                ["t_base_latency_qos",  "latency-base"],
1243                ["t_over_latency_qos",  "latency-override"],
1244                ["t_base_through_qos",  "throughput-base"],
1245                ["t_over_through_qos",  "throughput-override"]
1246                ]
1247
1248        requested=""
1249        for value in requested_strings:
1250            if t.requested_policy.__getattr__(value[0]) :
1251                requested+=value[1] + ": " + str(t.requested_policy.__getattr__(value[0])) + " "
1252            else:
1253                requested+=""
1254
1255        suppression_strings = [
1256                ["t_sup_active",        "active"],
1257                ["t_sup_lowpri_cpu",    "lowpri-cpu"],
1258                ["t_sup_timer",         "timer-throttling"],
1259                ["t_sup_disk",          "disk-throttling"],
1260                ["t_sup_cpu_limit",     "cpu-limits"],
1261                ["t_sup_suspend",       "suspend"]
1262                ]
1263
1264        suppression=""
1265        for value in suppression_strings:
1266            if t.requested_policy.__getattr__(value[0]) :
1267                suppression+=value[1] + ": " + str(t.requested_policy.__getattr__(value[0])) + " "
1268            else:
1269                suppression+=""
1270
1271        effective_strings = [
1272                ["darwinbg",        "background"],
1273                ["lowpri_cpu",      "lowpri-cpu"],
1274                ["io_tier",         "iotier"],
1275                ["io_passive",      "passive"],
1276                ["all_sockets_bg",  "bg-allsockets"],
1277                ["new_sockets_bg",  "bg-newsockets"],
1278                ["bg_iotier",       "bg-iotier"],
1279                ["terminated",      "terminated"],
1280                ["t_gpu_deny",      "gpu-deny"],
1281                ["t_tal_engaged",   "tal-engaged"],
1282                ["t_suspended",     "suspended"],
1283                ["t_watchers_bg",   "bg-watchers"],
1284                ["t_latency_qos",   "latency-qos"],
1285                ["t_through_qos",   "throughput-qos"],
1286                ["t_sup_active",    "suppression-active"],
1287                ["t_role",          "role"],
1288                ["t_visibility",    "vis"]
1289                ]
1290
1291        effective=""
1292        for value in effective_strings:
1293            if t.effective_policy.__getattr__(value[0]) :
1294                effective+=value[1] + ": " + str(t.effective_policy.__getattr__(value[0])) + " "
1295            else:
1296                effective+=""
1297
1298
1299        pended_strings = [
1300                ["t_updating_policy",     "updating"],
1301                ["update_sockets",        "update_sockets"],
1302                ["t_update_timers",       "update_timers"],
1303                ["t_update_watchers",     "update_watchers"]
1304                ]
1305
1306        pended=""
1307        for value in pended_strings:
1308            if t.pended_policy.__getattr__(value[0]) :
1309                pended+=value[1] + ": " + str(t.pended_policy.__getattr__(value[0])) + " "
1310            else:
1311                pended+=""
1312
1313        print "requested: " + requested
1314        print "suppression: " + suppression
1315        print "effective: " + effective
1316        print "pended: " + pended
1317
1318
1319
1320
1321