xref: /xnu-8019.80.24/tools/lldbmacros/process.py (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
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 time
11import xnudefines
12import memory
13import json
14from collections import defaultdict
15
16def GetProcPID(proc):
17    """ returns the PID of a process.
18        params:
19            proc: value object representing a proc in the kernel.
20        returns:
21            int: the pid of the process.
22    """
23    return unsigned(proc.p_pid)
24
25def GetProcPlatform(proc):
26    """ returns the platform identifier of a process.
27        params:
28            proc: value object representing a proc in the kernel.
29        returns:
30            int: the platform identifier of the process.
31    """
32    return int(proc.p_proc_ro.p_platform_data.p_platform)
33
34def GetProcName(proc):
35    """ returns a string name of the process. Longer variant is preffered if provided.
36        params:
37            proc: value object representing a proc in the kernel.
38        returns:
39            str: a string name of the process linked to the task.
40    """
41    name = str(proc.p_name)
42    if name != '':
43        return name
44    else:
45        return str(proc.p_comm)
46
47def GetProcNameForTask(task):
48    """ returns a string name of the process. If proc is not valid the proc
49        name is looked up in the associated importance structure (if
50        available). If no name can be found, "unknown"  is returned.
51        params:
52            task: value object represeting a task in the kernel.
53        returns:
54            str : A string name of the process linked to the task
55    """
56    if task:
57        if unsigned(task.bsd_info):
58            p = Cast(task.bsd_info, 'proc *')
59            return GetProcName(p)
60
61        if (hasattr(task, 'task_imp_base') and
62           hasattr(task.task_imp_base, 'iit_procname') and
63           unsigned(task.task_imp_base) != 0):
64            return str(task.task_imp_base.iit_procname)
65
66    return "unknown"
67
68def GetProcPIDForTask(task):
69    """ returns a int pid of the process. if the proc is not valid, val[5] from audit_token is returned.
70        params:
71            task: value object representing a task in the kernel
72        returns:
73            int : pid of the process or -1 if not found
74    """
75    if task and unsigned(task.bsd_info):
76        p = Cast(task.bsd_info, 'proc *')
77        return unsigned(GetProcPID(p))
78
79    if task :
80        proc_ro = Cast(link.sl_alloc_task.bsd_info_ro, 'proc_ro *')
81        pid = unsigned(proc_ro.task_tokens.audit_token.val[5])
82        return pid
83
84    return -1
85
86def GetProcInfo(proc):
87    """ returns a string name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields.
88        params:
89            proc : value object representing a proc in the kernel
90        returns:
91            str : A string describing various information for process.
92    """
93    out_string = ""
94    out_string += ("Process {p: <#020x}\n\tname {0: <32s}\n\tpid:{1: <6d} " +
95                   "task:{p.task: <#020x} p_stat:{p.p_stat: <6d} parent pid: {p.p_ppid: <6d}\n"
96                   ).format(GetProcName(proc), GetProcPID(proc), p=proc)
97    #print the Creds
98    ucred = proc.p_proc_ro.p_ucred
99    if ucred:
100        out_string += "Cred: euid {:d} ruid {:d} svuid {:d}\n".format(ucred.cr_posix.cr_uid,
101                                                                      ucred.cr_posix.cr_ruid,
102                                                                      ucred.cr_posix.cr_svuid )
103    #print the flags
104    flags = int(proc.p_flag)
105    out_string += "Flags: {0: <#020x}\n".format(flags)
106    i = 1
107    num = 1
108    while num <= flags:
109        if flags & num:
110            out_string += "\t" + xnudefines.proc_flag_explain_strings[i] + "\n"
111        elif num == 0x4: #special case for 32bit flag
112            out_string += "\t" + xnudefines.proc_flag_explain_strings[0] + "\n"
113        i += 1
114        num = num << 1
115    out_string += "State: "
116    state_val = proc.p_stat
117    if state_val < 1 or state_val > len(xnudefines.proc_state_strings) :
118        out_string += "(Unknown)"
119    else:
120        out_string += xnudefines.proc_state_strings[int(state_val)]
121
122    return out_string
123
124def GetProcNameForPid(pid):
125    """ Finds the name of the process corresponding to a given pid
126        params:
127            pid     : int, pid you want to find the procname for
128        returns
129            str     : Name of the process corresponding to the pid, "Unknown" if not found
130    """
131    for p in kern.procs:
132        if int(GetProcPID(p)) == int(pid):
133            return GetProcName(p)
134    return "Unknown"
135
136def GetProcForPid(search_pid):
137    """ Finds the value object representing a proc in the kernel based on its pid
138        params:
139            search_pid  : int, pid whose proc structure you want to find
140        returns:
141            value       : The value object representing the proc, if a proc corresponding
142                          to the given pid is found. Returns None otherwise
143    """
144    if search_pid == 0:
145        return kern.globals.initproc
146    else:
147        headp = kern.globals.allproc
148        for proc in IterateListEntry(headp, 'struct proc *', 'p_list'):
149            if GetProcPID(proc) == search_pid:
150                return proc
151        return None
152
153@lldb_command('allproc')
154def AllProc(cmd_args=None):
155    """ Walk through the allproc structure and print procinfo for each process structure.
156        params:
157            cmd_args - [] : array of strings passed from lldb command prompt
158    """
159    for proc in kern.procs :
160        print GetProcInfo(proc)
161
162
163@lldb_command('zombproc')
164def ZombProc(cmd_args=None):
165    """ Routine to print out all procs in the zombie list
166        params:
167            cmd_args - [] : array of strings passed from lldb command prompt
168    """
169    if len(kern.zombprocs) != 0:
170        print "\nZombie Processes:"
171        for proc in kern.zombprocs:
172            print GetProcInfo(proc) + "\n\n"
173
174@lldb_command('zombtasks')
175def ZombTasks(cmd_args=None):
176    """ Routine to print out all tasks in the zombie list
177        params: None
178    """
179    out_str = ""
180    if len(kern.zombprocs) != 0:
181        header = "\nZombie Tasks:\n"
182        header += GetTaskSummary.header + " " + GetProcSummary.header
183        for proc in kern.zombprocs:
184            if proc.p_stat != 5:
185                t = Cast(proc.task, 'task *')
186                out_str += GetTaskSummary(t) +" "+ GetProcSummary(proc) + "\n"
187        if out_str != "":
188            print header
189            print out_str
190
191@lldb_command('zombstacks')
192def ZombStacks(cmd_args=None):
193    """ Routine to print out all stacks of tasks that are exiting
194    """
195    header_flag = 0
196    for proc in kern.zombprocs:
197        if proc.p_stat != 5:
198            if header_flag == 0:
199                print "\nZombie Stacks:"
200                header_flag = 1
201            t = Cast(proc.task, 'task *')
202            ShowTaskStacks(t)
203#End of Zombstacks
204
205def GetASTSummary(ast):
206    """ Summarizes an AST field
207        Flags:
208        P - AST_PREEMPT
209        Q - AST_QUANTUM
210        U - AST_URGENT
211        H - AST_HANDOFF
212        Y - AST_YIELD
213        A - AST_APC
214        L - AST_LEDGER
215        B - AST_BSD
216        K - AST_KPERF
217        M - AST_MACF
218        r - AST_RESET_PCS
219        a - AST_ARCADE
220        G - AST_GUARD
221        T - AST_TELEMETRY_USER
222        T - AST_TELEMETRY_KERNEL
223        T - AST_TELEMETRY_WINDOWED
224        S - AST_SFI
225        D - AST_DTRACE
226        I - AST_TELEMETRY_IO
227        E - AST_KEVENT
228        R - AST_REBALANCE
229        N - AST_UNQUIESCE
230        p  - AST_PROC_RESOURCE
231    """
232    out_string = ""
233    state = int(ast)
234    thread_state_chars = {0x0:'', 0x1:'P', 0x2:'Q', 0x4:'U', 0x8:'H', 0x10:'Y', 0x20:'A',
235                          0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M', 0x400: 'r', 0x800: 'a',
236                          0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S',
237                          0x20000: 'D', 0x40000: 'I', 0x80000: 'E', 0x100000: 'R', 0x200000: 'N', 0x400000: 'p'}
238    state_str = ''
239    mask = 0x1
240    while mask <= 0x200000:
241        state_str += thread_state_chars[int(state & mask)]
242        mask = mask << 1
243
244    return state_str
245
246
247@lldb_type_summary(['kcdata_descriptor *', 'kcdata_descriptor_t'])
248@header("{0: <20s} {1: <20s} {2: <20s} {3: <10s} {4: <5s}".format("kcdata_descriptor", "begin_addr", "cur_pos", "size", "flags"))
249def GetKCDataSummary(kcdata):
250    """ Summarizes kcdata_descriptor structure
251        params: kcdata: value - value object representing kcdata_descriptor
252        returns: str - summary of the kcdata object
253    """
254    format_string = "{0: <#020x} {1: <#020x} {2: <#020x} {3: <10d} {4: <#05x}"
255    return format_string.format(kcdata, kcdata.kcd_addr_begin, kcdata.kcd_addr_end, kcdata.kcd_length, kcdata.kcd_flags)
256
257
258@lldb_type_summary(['task', 'task_t'])
259@header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags"))
260def GetTaskSummary(task, showcorpse=False):
261    """ Summarizes the important fields in task structure.
262        params: task: value - value object representing a task in kernel
263        returns: str - summary of the task
264    """
265    out_string = ""
266    format_string = '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}'
267    thread_count = int(task.thread_count)
268    task_flags = ''
269    if hasattr(task, "suppression_generation") and (int(task.suppression_generation) & 0x1) == 0x1:
270        task_flags += 'P'
271    if hasattr(task, "effective_policy") and int(task.effective_policy.tep_sup_active) == 1:
272        task_flags += 'N'
273    if hasattr(task, "suspend_count") and int(task.suspend_count) > 0:
274        task_flags += 'S'
275    if hasattr(task, 'task_imp_base') and unsigned(task.task_imp_base):
276        tib = task.task_imp_base
277        if int(tib.iit_receiver) == 1:
278            task_flags += 'R'
279        if int(tib.iit_donor) == 1:
280            task_flags += 'D'
281        if int(tib.iit_assertcnt) > 0:
282            task_flags += 'B'
283
284    # check if corpse flag is set
285    if unsigned(task.t_flags) & 0x20:
286        task_flags += 'C'
287    if unsigned(task.t_flags) & 0x40:
288        task_flags += 'P'
289
290    out_string += format_string.format(task, task.map, task.itk_space, thread_count, task_flags)
291    if showcorpse is True and unsigned(task.corpse_info) != 0:
292        out_string += " " + GetKCDataSummary(task.corpse_info)
293    return out_string
294
295def GetMachThread(thread):
296    """ Converts the passed in value interpreted as a thread_t into a uthread_t
297    """
298    return addressof(Cast(thread, 'struct thread *')[-1])
299
300def GetBSDThread(thread):
301    """ Converts the passed in value interpreted as a uthread_t into a thread_t
302    """
303    return Cast(addressof(Cast(thread, 'struct thread *')[1]), 'struct uthread *')
304
305def GetThreadName(thread):
306    """ Get the name of a thread, if possible.  Returns the empty string
307        otherwise.
308    """
309    uthread = GetBSDThread(thread)
310    if int(uthread.pth_name) != 0 :
311        th_name_strval = Cast(uthread.pth_name, 'char *')
312        if len(str(th_name_strval)) > 0 :
313            return str(th_name_strval)
314
315    return ''
316
317@lldb_type_summary(['thread *', 'thread_t'])
318@header("{0: <24s} {1: <10s} {2: <20s} {3: <6s} {4: <6s} {5: <15s} {6: <15s} {7: <8s} {8: <12s} {9: <32s} {10: <20s} {11: <20s} {12: <20s}".format('thread', 'thread_id', 'processor', 'base', 'pri', 'sched_mode', 'io_policy', 'state', 'ast', 'waitq', 'wait_event', 'wmesg', 'thread_name'))
319def GetThreadSummary(thread):
320    """ Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct.
321        params: thread: value - value objecte representing a thread in kernel
322        returns: str - summary of a thread
323
324        State flags:
325        W - WAIT
326        S - SUSP
327        R - RUN
328        U - Uninterruptible
329        H - Terminated
330        A - Terminated and on termination queue
331        I - Idle thread
332        C - Crashed thread
333
334        policy flags:
335        B - darwinbg
336        T - IO throttle
337        P - IO passive
338        D - Terminated
339    """
340    out_string = ""
341    format_string = "{0: <24s} {1: <10s} {2: <20s} {3: <6s} {4: <6s} {5: <15s} {6: <15s} {7: <8s} {8: <12s} {9: <32s} {10: <20s} {11: <20s} {12: <20s}"
342    thread_ptr_str = str("{0: <#020x}".format(thread))
343    if int(thread.static_param) :
344        thread_ptr_str+="[WQ]"
345    thread_id = hex(thread.thread_id)
346    processor = hex(thread.last_processor)
347    base_priority = str(int(thread.base_pri))
348    sched_priority = str(int(thread.sched_pri))
349    sched_mode = ''
350    mode = str(thread.sched_mode)
351    if "TIMESHARE" in mode:
352        sched_mode+="timeshare"
353    elif "FIXED" in mode:
354        sched_mode+="fixed"
355    elif "REALTIME" in mode:
356        sched_mode+="realtime"
357
358    if (unsigned(thread.bound_processor) != 0):
359        sched_mode+=" bound"
360
361    # TH_SFLAG_THROTTLED
362    if (unsigned(thread.sched_flags) & 0x0004):
363        sched_mode+=" BG"
364
365    io_policy_str = ""
366    thread_name = GetThreadName(thread)
367    uthread = GetBSDThread(thread)
368
369    # check for io_policy flags
370    if int(uthread.uu_flag) & 0x400:
371        io_policy_str+='RAGE '
372
373    #now flags for task_policy
374
375    io_policy_str = ""
376
377    if int(thread.effective_policy.thep_darwinbg) != 0:
378        io_policy_str += "B"
379    if int(thread.effective_policy.thep_io_tier) != 0:
380        io_policy_str += "T"
381    if int(thread.effective_policy.thep_io_passive) != 0:
382        io_policy_str += "P"
383    if int(thread.effective_policy.thep_terminated) != 0:
384        io_policy_str += "D"
385
386    state = int(thread.state)
387    thread_state_chars = {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
388    state_str = ''
389    mask = 0x1
390    while mask <= 0x80 :
391        state_str += thread_state_chars[int(state & mask)]
392        mask = mask << 1
393
394    if int(thread.inspection):
395        state_str += 'C'
396
397    ast = int(thread.ast) | int(thread.reason)
398    ast_str = GetASTSummary(ast)
399
400    #wait queue information
401    wait_queue_str = ''
402    wait_event_str = ''
403    wait_message = ''
404    if ( state & 0x1 ) != 0:
405        #we need to look at the waitqueue as well
406        wait_queue_str = str("{0: <#020x}".format(int(hex(thread.waitq), 16)))
407        wait_event_str = str("{0: <#020x}".format(int(hex(thread.wait_event), 16)))
408        wait_event_str_sym = kern.Symbolicate(int(hex(thread.wait_event), 16))
409        if len(wait_event_str_sym) > 0:
410            wait_event_str = wait_event_str.strip() + " <" + wait_event_str_sym + ">"
411        uthread = GetBSDThread(thread)
412        if int(uthread.uu_wmesg) != 0:
413            wait_message = str(Cast(uthread.uu_wmesg, 'char *'))
414
415    out_string += format_string.format(thread_ptr_str, thread_id, processor, base_priority, sched_priority, sched_mode, io_policy_str, state_str, ast_str, wait_queue_str, wait_event_str, wait_message, thread_name)
416    return out_string
417
418
419def GetTaskRoleString(role):
420    role_strs = {
421                 0 : "TASK_UNSPECIFIED",
422                 1 : "TASK_FOREGROUND_APPLICATION",
423                 2 : "TASK_BACKGROUND_APPLICATION",
424                 3 : "TASK_CONTROL_APPLICATION",
425                 4 : "TASK_GRAPHICS_SERVER",
426                 5 : "TASK_THROTTLE_APPLICATION",
427                 6 : "TASK_NONUI_APPLICATION",
428                 7 : "TASK_DEFAULT_APPLICATION",
429                }
430    return role_strs[int(role)]
431
432def GetCoalitionFlagString(coal):
433    flags = []
434    if (coal.privileged):
435        flags.append('privileged')
436    if (coal.termrequested):
437        flags.append('termrequested')
438    if (coal.terminated):
439        flags.append('terminated')
440    if (coal.reaped):
441        flags.append('reaped')
442    if (coal.notified):
443        flags.append('notified')
444    if (coal.efficient):
445        flags.append('efficient')
446    return "|".join(flags)
447
448def GetCoalitionTasks(queue, coal_type, thread_details=False):
449    sfi_strs = {
450                 0x0  : "SFI_CLASS_UNSPECIFIED",
451                 0x1  : "SFI_CLASS_DARWIN_BG",
452                 0x2  : "SFI_CLASS_APP_NAP",
453                 0x3  : "SFI_CLASS_MANAGED_FOCAL",
454                 0x4  : "SFI_CLASS_MANAGED_NONFOCAL",
455                 0x5  : "SFI_CLASS_DEFAULT_FOCAL",
456                 0x6  : "SFI_CLASS_DEFAULT_NONFOCAL",
457                 0x7  : "SFI_CLASS_KERNEL",
458                 0x8  : "SFI_CLASS_OPTED_OUT",
459                 0x9  : "SFI_CLASS_UTILITY",
460                 0xA  : "SFI_CLASS_LEGACY_FOCAL",
461                 0xB  : "SFI_CLASS_LEGACY_NONFOCAL",
462                 0xC  : "SFI_CLASS_USER_INITIATED_FOCAL",
463                 0xD  : "SFI_CLASS_USER_INITIATED_NONFOCAL",
464                 0xE  : "SFI_CLASS_USER_INTERACTIVE_FOCAL",
465                 0xF  : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL",
466                 0x10 : "SFI_CLASS_MAINTENANCE",
467                }
468    tasks = []
469    field_name = 'task_coalition'
470    for task in IterateLinkageChain(queue, 'task *', field_name, coal_type * sizeof('queue_chain_t')):
471        task_str = "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task),task,GetProcNameForTask(task),GetTaskRoleString(task.effective_policy.tep_role))
472        if thread_details:
473            for thread in IterateQueue(task.threads, "thread_t", "task_threads"):
474                task_str += "\n\t\t\t|-> thread:" + hex(thread) + ", " + sfi_strs[int(thread.sfi_class)]
475        tasks.append(task_str)
476    return tasks
477
478def GetCoalitionTypeString(type):
479    """ Convert a coalition type field into a string
480    Currently supported types (from <mach/coalition.h>):
481        COALITION_TYPE_RESOURCE
482        COALITION_TYPE_JETSAM
483    """
484    if type == 0: # COALITION_TYPE_RESOURCE
485        return 'RESOURCE'
486    if type == 1:
487        return 'JETSAM'
488    return '<unknown>'
489
490def GetResourceCoalitionSummary(coal, verbose=False):
491    """ Summarize a resource coalition
492    """
493    out_string = "Resource Coalition:\n\t  Ledger:\n"
494    thread_details = False
495    if config['verbosity'] > vSCRIPT:
496        thread_details = True
497    ledgerp = coal.r.ledger
498    if verbose and unsigned(ledgerp) != 0:
499        i = 0
500        while i != ledgerp.l_template.lt_cnt:
501            out_string += "\t\t"
502            out_string += GetLedgerEntrySummary(kern.globals.task_ledger_template, ledgerp, i)
503            i = i + 1
504    out_string += "\t  bytesread {0: <d}\n\t  byteswritten {1: <d}\n\t  gpu_time {2: <d}".format(coal.r.bytesread, coal.r.byteswritten, coal.r.gpu_time)
505    out_string += "\n\t  total_tasks {0: <d}\n\t  dead_tasks {1: <d}\n\t  active_tasks {2: <d}".format(coal.r.task_count, coal.r.dead_task_count, coal.r.task_count - coal.r.dead_task_count)
506    out_string += "\n\t  last_became_nonempty_time {0: <d}\n\t  time_nonempty {1: <d}".format(coal.r.last_became_nonempty_time, coal.r.time_nonempty)
507    out_string += "\n\t  cpu_ptime {0: <d}".format(coal.r.cpu_ptime)
508    if verbose:
509        out_string += "\n\t  cpu_time_effective[THREAD_QOS_DEFAULT] {0: <d}".format(coal.r.cpu_time_eqos[0])
510        out_string += "\n\t  cpu_time_effective[THREAD_QOS_MAINTENANCE] {0: <d}".format(coal.r.cpu_time_eqos[1])
511        out_string += "\n\t  cpu_time_effective[THREAD_QOS_BACKGROUND] {0: <d}".format(coal.r.cpu_time_eqos[2])
512        out_string += "\n\t  cpu_time_effective[THREAD_QOS_UTILITY] {0: <d}".format(coal.r.cpu_time_eqos[3])
513        out_string += "\n\t  cpu_time_effective[THREAD_QOS_LEGACY] {0: <d}".format(coal.r.cpu_time_eqos[4])
514        out_string += "\n\t  cpu_time_effective[THREAD_QOS_USER_INITIATED] {0: <d}".format(coal.r.cpu_time_eqos[5])
515        out_string += "\n\t  cpu_time_effective[THREAD_QOS_USER_INTERACTIVE] {0: <d}".format(coal.r.cpu_time_eqos[6])
516    out_string += "\n\t  Tasks:\n\t\t"
517    tasks = GetCoalitionTasks(addressof(coal.r.tasks), 0, thread_details)
518    out_string += "\n\t\t".join(tasks)
519    return out_string
520
521def GetJetsamCoalitionSummary(coal, verbose=False):
522    out_string = "Jetsam Coalition:"
523    thread_details = False
524    if config['verbosity'] > vSCRIPT:
525        thread_details = True
526    if unsigned(coal.j.leader) == 0:
527        out_string += "\n\t  NO Leader!"
528    else:
529        out_string += "\n\t  Leader:\n\t\t"
530        out_string += "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(coal.j.leader),coal.j.leader,GetProcNameForTask(coal.j.leader),GetTaskRoleString(coal.j.leader.effective_policy.tep_role))
531    out_string += "\n\t  Extensions:\n\t\t"
532    tasks = GetCoalitionTasks(addressof(coal.j.extensions), 1, thread_details)
533    out_string += "\n\t\t".join(tasks)
534    out_string += "\n\t  XPC Services:\n\t\t"
535    tasks = GetCoalitionTasks(addressof(coal.j.services), 1, thread_details)
536    out_string += "\n\t\t".join(tasks)
537    out_string += "\n\t  Other Tasks:\n\t\t"
538    tasks = GetCoalitionTasks(addressof(coal.j.other), 1, thread_details)
539    out_string += "\n\t\t".join(tasks)
540    out_string += "\n\t  Thread Group: {0: <#020x}\n".format(coal.j.thread_group)
541    return out_string
542
543@lldb_type_summary(['coalition_t', 'coalition *'])
544@header("{0: <20s} {1: <15s} {2: <10s} {3: <10s} {4: <10s} {5: <12s} {6: <12s} {7: <20s}".format("coalition", "type", "id", "ref count", "act count", "focal cnt", "nonfocal cnt","flags"))
545def GetCoalitionSummary(coal):
546    if unsigned(coal) == 0:
547        return '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'.format(0, "", -1, -1, -1, -1, -1, "")
548    out_string = ""
549    format_string = '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'
550    type_string = GetCoalitionTypeString(coal.type)
551    flag_string = GetCoalitionFlagString(coal)
552    out_string += format_string.format(coal, type_string, coal.id, coal.ref_count, coal.active_count, coal.focal_task_count, coal.nonfocal_task_count, flag_string)
553    return out_string
554
555def GetCoalitionInfo(coal, verbose=False):
556    """ returns a string describing a coalition, including details about the particular coalition type.
557        params:
558            coal : value object representing a coalition in the kernel
559        returns:
560            str : A string describing the coalition.
561    """
562    if unsigned(coal) == 0:
563        return "<null coalition>"
564    typestr = GetCoalitionTypeString(coal.type)
565    flagstr = GetCoalitionFlagString(coal)
566    out_string = ""
567    out_string += "Coalition {c: <#020x}\n\tID {c.id: <d}\n\tType {c.type: <d} ({t: <s})\n\tRefCount {c.ref_count: <d}\n\tActiveCount {c.active_count: <d}\n\tFocal Tasks: {c.focal_task_count: <d}\n\tNon-Focal Tasks: {c.nonfocal_task_count: <d}\n\tFlags {f: <s}\n\t".format(c=coal,t=typestr,f=flagstr)
568    if coal.type == 0: # COALITION_TYPE_RESOURCE
569        out_string += GetResourceCoalitionSummary(coal, verbose)
570    elif coal.type == 1: # COALITION_TYPE_JETSAM
571        out_string += GetJetsamCoalitionSummary(coal, verbose)
572    else:
573        out_string += "Unknown Type"
574
575    return out_string
576
577# Macro: showcoalitioninfo
578
579@lldb_command('showcoalitioninfo')
580def ShowCoalitionInfo(cmd_args=None, cmd_options={}):
581    """  Display more detailed information about a coalition
582         Usage: showcoalitioninfo <address of coalition>
583    """
584    verbose = False
585    if config['verbosity'] > vHUMAN:
586        verbose = True
587    if not cmd_args:
588        raise ArgumentError("No arguments passed")
589    coal = kern.GetValueFromAddress(cmd_args[0], 'coalition *')
590    if not coal:
591        print "unknown arguments:", str(cmd_args)
592        return False
593    print GetCoalitionInfo(coal, verbose)
594
595# EndMacro: showcoalitioninfo
596
597# Macro: showallcoalitions
598
599@lldb_command('showallcoalitions')
600def ShowAllCoalitions(cmd_args=None):
601    """  Print a summary listing of all the coalitions
602    """
603    global kern
604    print GetCoalitionSummary.header
605    for c in kern.coalitions:
606        print GetCoalitionSummary(c)
607
608# EndMacro: showallcoalitions
609
610# Macro: showallthreadgroups
611
612@lldb_type_summary(['struct thread_group *', 'thread_group *'])
613@header("{0: <20s} {1: <5s} {2: <16s} {3: <5s} {4: <8s} {5: <20s}".format("thread_group", "id", "name", "refc", "flags", "recommendation"))
614def GetThreadGroupSummary(tg):
615    if unsigned(tg) == 0:
616        return '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'.format(0, -1, "", -1, "", -1)
617    out_string = ""
618    format_string = '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'
619    tg_flags = ''
620    if (tg.tg_flags & 0x1):
621        tg_flags += 'E'
622    if (tg.tg_flags & 0x2):
623        tg_flags += 'U'
624    out_string += format_string.format(tg, tg.tg_id, tg.tg_name, tg.tg_refcount.ref_count, tg_flags, tg.tg_recommendation)
625    return out_string
626
627@lldb_command('showallthreadgroups')
628def ShowAllThreadGroups(cmd_args=None):
629    """  Print a summary listing of all thread groups
630    """
631    global kern
632    print GetThreadGroupSummary.header
633    for tg in kern.thread_groups:
634        print GetThreadGroupSummary(tg)
635
636# EndMacro: showallthreadgroups
637
638# Macro: showtaskcoalitions
639
640@lldb_command('showtaskcoalitions', 'F:')
641def ShowTaskCoalitions(cmd_args=None, cmd_options={}):
642    """
643    """
644    task_list = []
645    if "-F" in cmd_options:
646        task_list = FindTasksByName(cmd_options["-F"])
647    elif cmd_args:
648        t = kern.GetValueFromAddress(cmd_args[0], 'task *')
649        task_list.append(t)
650    else:
651        raise ArgumentError("No arguments passed")
652
653    if len(task_list) > 0:
654        print GetCoalitionSummary.header
655    for task in task_list:
656        print GetCoalitionSummary(task.coalition[0])
657        print GetCoalitionSummary(task.coalition[1])
658
659# EndMacro: showtaskcoalitions
660
661@lldb_type_summary(['proc', 'proc *'])
662@header("{0: >6s}   {1: <18s} {2: >11s} {3: ^10s} {4: <32s}".format("pid", "process", "io_policy", "wq_state", "command"))
663def GetProcSummary(proc):
664    """ Summarize the process data.
665        params:
666          proc : value - value representaitng a proc * in kernel
667        returns:
668          str - string summary of the process.
669    """
670    out_string = ""
671    format_string= "{0: >6d}   {1: <#018x} {2: >11s} {3: >2d} {4: >2d} {5: >2d}   {6: <32s}"
672    pval = proc.GetSBValue()
673    #code.interact(local=locals())
674    if str(pval.GetType()) != str(gettype('proc *')) :
675        return "Unknown type " + str(pval.GetType()) + " " + str(hex(proc))
676    if not proc:
677        out_string += "Process " + hex(proc) + " is not valid."
678        return out_string
679    pid = int(GetProcPID(proc))
680    proc_addr = int(hex(proc), 16)
681    proc_rage_str = ""
682    if int(proc.p_lflag) & 0x400000 :
683        proc_rage_str = "RAGE"
684
685    task = Cast(proc.task, 'task *')
686
687    io_policy_str = ""
688
689    if int(task.effective_policy.tep_darwinbg) != 0:
690        io_policy_str += "B"
691    if int(task.effective_policy.tep_lowpri_cpu) != 0:
692        io_policy_str += "L"
693
694    if int(task.effective_policy.tep_io_tier) != 0:
695        io_policy_str += "T"
696    if int(task.effective_policy.tep_io_passive) != 0:
697        io_policy_str += "P"
698    if int(task.effective_policy.tep_terminated) != 0:
699        io_policy_str += "D"
700
701    if int(task.effective_policy.tep_latency_qos) != 0:
702        io_policy_str += "Q"
703    if int(task.effective_policy.tep_sup_active) != 0:
704        io_policy_str += "A"
705
706
707    try:
708        work_queue = Cast(proc.p_wqptr, 'workqueue *')
709        if proc.p_wqptr != 0 :
710            wq_num_threads = int(work_queue.wq_nthreads)
711            wq_idle_threads = int(work_queue.wq_thidlecount)
712            wq_req_threads = int(work_queue.wq_reqcount)
713        else:
714            wq_num_threads = 0
715            wq_idle_threads = 0
716            wq_req_threads = 0
717    except:
718        wq_num_threads = -1
719        wq_idle_threads = -1
720        wq_req_threads = -1
721    process_name = GetProcName(proc)
722    if process_name == 'xpcproxy':
723        for thread in IterateQueue(task.threads, 'thread *', 'task_threads'):
724            thread_name = GetThreadName(thread)
725            if thread_name:
726                process_name += ' (' + thread_name + ')'
727                break
728    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)
729    return out_string
730
731@lldb_type_summary(['tty_dev_t', 'tty_dev_t *'])
732@header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","primary", "replica", "open", "free", "name", "revoke"))
733def GetTTYDevSummary(tty_dev):
734    """ Summarizes the important fields in tty_dev_t structure.
735        params: tty_dev: value - value object representing a tty_dev_t in kernel
736        returns: str - summary of the tty_dev
737    """
738    out_string = ""
739    format_string = "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"
740    open_fn = kern.Symbolicate(int(hex(tty_dev.open), 16))
741    free_fn = kern.Symbolicate(int(hex(tty_dev.free), 16))
742    name_fn = kern.Symbolicate(int(hex(tty_dev.name), 16))
743    revoke_fn = kern.Symbolicate(int(hex(tty_dev.revoke), 16))
744    out_string += format_string.format(tty_dev, tty_dev.primary, tty_dev.replica, open_fn, free_fn, name_fn, revoke_fn)
745    return out_string
746
747# Macro: showtask
748
749@lldb_command('showtask', 'F:')
750def ShowTask(cmd_args=None, cmd_options={}):
751    """  Routine to print a summary listing of given task
752         Usage: showtask <address of task>
753         or   : showtask -F <name of task>
754    """
755    task_list = []
756    if "-F" in cmd_options:
757        task_list = FindTasksByName(cmd_options['-F'])
758    else:
759        if not cmd_args:
760            raise ArgumentError("Invalid arguments passed.")
761
762        tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
763        if not tval:
764            raise ("Unknown arguments: %r" % cmd_args)
765        task_list.append(tval)
766
767    for tval in task_list:
768        print GetTaskSummary.header + " " + GetProcSummary.header
769        pval = Cast(tval.bsd_info, 'proc *')
770        print GetTaskSummary(tval) +" "+ GetProcSummary(pval)
771
772# EndMacro: showtask
773
774# Macro: showpid
775
776@lldb_command('showpid')
777def ShowPid(cmd_args=None):
778    """  Routine to print a summary listing of task corresponding to given pid
779         Usage: showpid <pid value>
780    """
781    if not cmd_args:
782        raise ArgumentError("No arguments passed")
783    pidval = ArgumentStringToInt(cmd_args[0])
784    for t in kern.tasks:
785        pval = Cast(t.bsd_info, 'proc *')
786        if pval and GetProcPID(pval) == pidval:
787            print GetTaskSummary.header + " " + GetProcSummary.header
788            print GetTaskSummary(t) + " " + GetProcSummary(pval)
789            break
790
791# EndMacro: showpid
792
793# Macro: showproc
794
795@lldb_command('showproc')
796def ShowProc(cmd_args=None):
797    """  Routine to print a summary listing of task corresponding to given proc
798         Usage: showproc <address of proc>
799    """
800    if not cmd_args:
801        raise ArgumentError("No arguments passed")
802    pval = kern.GetValueFromAddress(cmd_args[0], 'proc *')
803    if not pval:
804        print "unknown arguments:", str(cmd_args)
805        return False
806    print GetTaskSummary.header + " " + GetProcSummary.header
807    tval = Cast(pval.task, 'task *')
808    print GetTaskSummary(tval) +" "+ GetProcSummary(pval)
809
810# EndMacro: showproc
811
812# Macro: showprocinfo
813
814@lldb_command('showprocinfo')
815def ShowProcInfo(cmd_args=None):
816    """  Routine to display name, pid, parent & task for the given proc address
817         It also shows the Cred, Flags and state of the process
818         Usage: showprocinfo <address of proc>
819    """
820    if not cmd_args:
821        raise ArgumentError("No arguments passed")
822    pval = kern.GetValueFromAddress(cmd_args[0], 'proc *')
823    if not pval:
824        print "unknown arguments:", str(cmd_args)
825        return False
826    print GetProcInfo(pval)
827
828# EndMacro: showprocinfo
829
830#Macro: showprocfiles
831
832@lldb_command('showprocfiles')
833def ShowProcFiles(cmd_args=None):
834    """ Given a proc_t pointer, display the list of open file descriptors for the referenced process.
835        Usage: showprocfiles <proc_t>
836    """
837    if not cmd_args:
838        print ShowProcFiles.__doc__
839        return
840    proc = kern.GetValueFromAddress(cmd_args[0], 'proc_t')
841    proc_filedesc = addressof(proc.p_fd)
842    proc_ofiles = proc_filedesc.fd_ofiles
843    if unsigned(proc_ofiles) == 0:
844        print 'No open files for proc {0: <s}'.format(cmd_args[0])
845        return
846    print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')
847    print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")
848
849    for fd in xrange(0, unsigned(proc_filedesc.fd_afterlast)):
850        if unsigned(proc_ofiles[fd]) != 0:
851            out_str = ''
852            proc_fd_flags = proc_ofiles[fd].fp_flags
853            proc_fd_fglob = proc_ofiles[fd].fp_glob
854            proc_fd_fglob_fg_data = Cast(proc_fd_fglob.fg_data, 'void *')
855            out_str += "{0: <5d} ".format(fd)
856            out_str += "{0: <#18x} ".format(unsigned(proc_fd_fglob))
857            out_str += "0x{0:0>8x} ".format(unsigned(proc_fd_flags))
858            proc_fd_ftype = unsigned(proc_fd_fglob.fg_ops.fo_type)
859            if proc_fd_ftype in xnudefines.filetype_strings:
860                out_str += "{0: <8s} ".format(xnudefines.filetype_strings[proc_fd_ftype])
861            else:
862                out_str += "?: {0: <5d} ".format(proc_fd_ftype)
863            out_str += "{0: <#18x} ".format(unsigned(proc_fd_fglob_fg_data))
864            if proc_fd_ftype == 1:
865                fd_name = Cast(proc_fd_fglob_fg_data, 'struct vnode *').v_name
866                out_str += "{0: <64s}".format(fd_name)
867            out_str += "\n"
868            print out_str
869
870#EndMacro: showprocfiles
871
872#Macro: showtty
873
874@lldb_command('showtty')
875def ShowTTY(cmd_args=None):
876    """ Display information about a struct tty
877        Usage: showtty <tty struct>
878    """
879    if not cmd_args:
880        print ShowTTY.__doc__
881        return
882
883    tty = kern.GetValueFromAddress(cmd_args[0], 'struct tty *')
884    print "TTY structure at:              {0: <s}".format(cmd_args[0])
885    print "Last input to raw queue:       {0: <#18x} \"{1: <s}\"".format(unsigned(tty.t_rawq.c_cs), tty.t_rawq.c_cs)
886    print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty.t_canq.c_cs), tty.t_canq.c_cs)
887    print "Last output data:              {0: <#18x} \"{1: <s}\"".format(unsigned(tty.t_outq.c_cs), tty.t_outq.c_cs)
888    tty_state_info = [
889                  ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'],
890                  ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'],
891                  ['', 'TS_BUSY (Draining output)'],
892                  ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'],
893                  ['', 'TS_FLUSH (Outq has been flushed during DMA)'],
894                  ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'],
895                  ['', 'TS_TBLOCK (Further input blocked)'],
896                  ['', 'TS_TIMEOUT (Wait for output char processing)'],
897                  ['', 'TS_TTSTOP (Output paused)'],
898                  ['', 'TS_WOPEN (Open in progress)'],
899                  ['', 'TS_XCLUDE (Tty requires exclusivity)'],
900                  ['', 'TS_BKSL (State for lowercase \\ work)'],
901                  ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'],
902                  ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'],
903                  ['', 'TS_LNCH (Next character is literal)'],
904                  ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'],
905                  ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'],
906                  ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'],
907                  ['', 'TS_SNOOP (Device is being snooped on)'],
908                  ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'],
909                  ['', 'TS_ZOMBIE (Connection lost)'],
910                  ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'],
911                  ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'],
912                  ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)']
913                ]
914    index = 0
915    mask = 0x1
916    tty_state = unsigned(tty.t_state)
917    print "State:"
918    while index < 24:
919        if tty_state & mask != 0:
920            if len(tty_state_info[index][1]) > 0:
921                print '\t' + tty_state_info[index][1]
922        else:
923            if len(tty_state_info[index][0]) > 0:
924                print '\t' + tty_state_info[index][0]
925        index += 1
926        mask = mask << 1
927    print "Flags:                    0x{0:0>8x}".format(unsigned(tty.t_flags))
928    print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty.t_pgrp))
929    print "Enclosing session:        0x{0:0>16x}".format(unsigned(tty.t_session))
930    print "Termios:"
931    print "\tInput Flags:   0x{0:0>8x}".format(unsigned(tty.t_termios.c_iflag))
932    print "\tOutput Flags:  0x{0:0>8x}".format(unsigned(tty.t_termios.c_oflag))
933    print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty.t_termios.c_cflag))
934    print "\tLocal Flags:   0x{0:0>8x}".format(unsigned(tty.t_termios.c_lflag))
935    print "\tInput Speed:   {0: <8d}".format(tty.t_termios.c_ispeed)
936    print "\tOutput Speed:  {0: <8d}".format(tty.t_termios.c_ospeed)
937    print "High Watermark: {0: <d} bytes".format(tty.t_hiwat)
938    print "Low Watermark : {0: <d} bytes".format(tty.t_lowat)
939
940#EndMacro: showtty
941
942#Macro showallttydevs
943
944@lldb_command('showallttydevs')
945def ShowAllTTYDevs(cmd_args=[], cmd_options={}):
946    """ Show a list of ttydevs registered in the system.
947        Usage:
948        (lldb)showallttydevs
949    """
950    tty_dev_head = kern.globals.tty_dev_head
951    tty_dev = tty_dev_head
952    print GetTTYDevSummary.header
953    while unsigned(tty_dev) != 0:
954        print GetTTYDevSummary(tty_dev)
955        tty_dev = tty_dev.next
956    return ""
957
958#EndMacro: showallttydevs
959
960#Macro: dumpthread_terminate_queue
961
962@lldb_command('dumpthread_terminate_queue')
963def DumpThreadTerminateQueue(cmd_args=None):
964    """ Displays the contents of the specified call_entry queue.
965        Usage: dumpthread_terminate_queue
966    """
967
968    count = 0
969    print GetThreadSummary.header
970    for th in IterateMPSCQueue(addressof(kern.globals.thread_terminate_queue.mpd_queue), 'struct thread', 'mpsc_links'):
971        print GetThreadSummary(th)
972        count += 1
973    print "{0: <d} entries!".format(count)
974
975#EndMacro: dumpthread_terminate_queue
976
977#Macro: dumpcrashed_thread_queue
978
979@lldb_command('dumpcrashed_thread_queue')
980def DumpCrashedThreadsQueue(cmd_args=None):
981    """ Displays the contents of the specified call_entry queue.
982        Usage: dumpcrashed_thread_queue
983    """
984
985    count = 0
986    print GetThreadSummary.header
987    for th in IterateQueue(addressof(kern.globals.crashed_threads_queue), 'struct thread *',  'q_link'):
988        print GetThreadSummary(th)
989        count += 1
990    print "{0: <d} entries!".format(count)
991
992#EndMacro: dumpcrashed_thread_queue
993
994#Macro: dumpcallqueue
995
996@lldb_command('dumpcallqueue')
997def DumpCallQueue(cmd_args=None):
998    """ Displays the contents of the specified call_entry queue.
999        Usage: dumpcallqueue <queue_head_t *>
1000    """
1001    if not cmd_args:
1002        raise ArgumentError("Invalid arguments")
1003
1004    print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
1005    callhead = kern.GetValueFromAddress(cmd_args[0], 'queue_head_t *')
1006    count = 0
1007    for callentry in IterateQueue(callhead, 'struct call_entry *',  'q_link'):
1008        print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format(
1009              unsigned(callentry), unsigned(callentry.param0), unsigned(callentry.param1),
1010              unsigned(callentry.deadline), unsigned(callentry.func))
1011        count += 1
1012    print "{0: <d} entries!".format(count)
1013
1014#EndMacro: dumpcallqueue
1015
1016@lldb_command('showalltasklogicalwrites')
1017def ShowAllTaskIOStats(cmd_args=None):
1018    """ Commad to print I/O stats for all tasks
1019    """
1020    print "{0: <20s} {1: <20s} {2: <20s} {3: <20s} {4: <20s} {5: <20s} {6: <20s} {7: <20s} {8: <20s} {9: <32}".format("task", "Immediate Writes", "Deferred Writes", "Invalidated Writes", "Metadata Writes", "Immediate Writes to External", "Deferred Writes to External", "Invalidated Writes to External", "Metadata Writes to External", "name")
1021    for t in kern.tasks:
1022        pval = Cast(t.bsd_info, 'proc *')
1023        print "{0: <#18x} {1: >20d} {2: >20d} {3: >20d} {4: >20d}  {5: <20s} {6: <20s} {7: <20s} {8: <20s} {9: <20s}".format(t,
1024            t.task_writes_counters_internal.task_immediate_writes,
1025            t.task_writes_counters_internal.task_deferred_writes,
1026            t.task_writes_counters_internal.task_invalidated_writes,
1027            t.task_writes_counters_internal.task_metadata_writes,
1028            t.task_writes_counters_external.task_immediate_writes,
1029            t.task_writes_counters_external.task_deferred_writes,
1030            t.task_writes_counters_external.task_invalidated_writes,
1031            t.task_writes_counters_external.task_metadata_writes,
1032            GetProcName(pval))
1033
1034
1035@lldb_command('showalltasks','C', fancy=True)
1036def ShowAllTasks(cmd_args=None, cmd_options={}, O=None):
1037    """  Routine to print a summary listing of all the tasks
1038         wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1039         if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1040         io_policy -> RAGE  - rapid aging of vnodes requested
1041                     NORM  - normal I/O explicitly requested (this is the default)
1042                     PASS  - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1043                     THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1044         Usage: (lldb) showalltasks -C  : describe the corpse structure
1045    """
1046    global kern
1047    extra_hdr = ''
1048    showcorpse = False
1049    if '-C' in cmd_options:
1050        showcorpse = True
1051        extra_hdr += " " + GetKCDataSummary.header
1052
1053    with O.table(GetTaskSummary.header + extra_hdr + " " + GetProcSummary.header):
1054        for t in kern.tasks:
1055            pval = Cast(t.bsd_info, 'proc *')
1056            print GetTaskSummary(t, showcorpse) + " " + GetProcSummary(pval)
1057
1058    ZombTasks()
1059
1060def TaskForPmapHelper(pmap):
1061    """ Given a pmap pointer, return the task pointer which contains that
1062        address space.
1063
1064        pmap: PMAP pointer whose task to find.
1065    """
1066    for tasklist in [kern.tasks, kern.terminated_tasks]:
1067        for task in tasklist:
1068            if kern.GetValueFromAddress(unsigned(task.map.pmap), 'pmap_t') == pmap:
1069                return task
1070
1071    return None
1072
1073@lldb_command('taskforpmap')
1074def TaskForPmap(cmd_args=None):
1075    """ Find the task whose pmap corresponds to <pmap>.
1076        Syntax: (lldb) taskforpmap <pmap>
1077            Multiple -v's can be specified for increased verbosity
1078    """
1079    if cmd_args == None or len(cmd_args) < 1:
1080        raise ArgumentError("Too few arguments to taskforpmap.")
1081    pmap = kern.GetValueFromAddress(cmd_args[0], 'pmap_t')
1082    task = TaskForPmapHelper(pmap)
1083
1084    if task is None:
1085        print "Couldn't find task for pmap {:#x}".format(pmap)
1086        return
1087
1088    print GetTaskSummary.header + " " + GetProcSummary.header
1089    pval = Cast(task.bsd_info, 'proc *')
1090    print GetTaskSummary(task) + " " + GetProcSummary(pval)
1091
1092@lldb_command('showterminatedtasks')
1093def ShowTerminatedTasks(cmd_args=None):
1094    """  Routine to print a summary listing of all the terminated tasks
1095         wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1096         if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1097         io_policy -> RAGE  - rapid aging of vnodes requested
1098                     NORM  - normal I/O explicitly requested (this is the default)
1099                     PASS  - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1100                     THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1101        syntax: (lldb)showallterminatedtasks
1102    """
1103    global kern
1104    print GetTaskSummary.header + " " + GetProcSummary.header
1105    for t in kern.terminated_tasks:
1106
1107        # If the task has been terminated it's likely that the process is
1108        # gone too. If there is no proc it may still be possible to find
1109        # the original proc name.
1110        pval = Cast(t.bsd_info, 'proc *')
1111        if pval:
1112            psummary = GetProcSummary(pval)
1113        else:
1114            name = GetProcNameForTask(t);
1115            pslen = GetProcSummary.header.find("command");
1116            psummary = "{0: <{indent}} {1: <s}".format("", name, indent = pslen - 1)
1117
1118        print GetTaskSummary(t) + " " + psummary
1119
1120    return True
1121
1122# Macro: showtaskstacks
1123
1124def ShowTaskStacks(task):
1125    """ Print a task with summary and stack information for each of its threads
1126    """
1127    global kern
1128    print GetTaskSummary.header + " " + GetProcSummary.header
1129    pval = Cast(task.bsd_info, 'proc *')
1130    print GetTaskSummary(task) + " " + GetProcSummary(pval)
1131    for th in IterateQueue(task.threads, 'thread *', 'task_threads'):
1132        print "  " + GetThreadSummary.header
1133        print "  " + GetThreadSummary(th)
1134        print GetThreadBackTrace(th, prefix="    ") + "\n"
1135
1136def FindTasksByName(searchstr, ignore_case=True):
1137    """ Search the list of tasks by name.
1138        params:
1139            searchstr: str - a regex like string to search for task
1140            ignore_case: bool - If False then exact matching will be enforced
1141        returns:
1142            [] - array of task object. Empty if not found any
1143    """
1144    re_options = 0
1145    if ignore_case:
1146        re_options = re.IGNORECASE
1147    search_regex = re.compile(searchstr, re_options)
1148    retval = []
1149    for t in kern.tasks:
1150        pval = Cast(t.bsd_info, "proc *")
1151        process_name = "{:s}".format(GetProcName(pval))
1152        if search_regex.search(process_name):
1153            retval.append(t)
1154    return retval
1155
1156@lldb_command('showtaskstacks', 'F:')
1157def ShowTaskStacksCmdHelper(cmd_args=None, cmd_options={}):
1158    """ Routine to print out the stack for each thread in a task
1159        Usage: showtaskstacks <0xaddress of task>
1160           or: showtaskstacks -F launchd
1161    """
1162
1163    if "-F" in cmd_options:
1164        find_task_str = cmd_options["-F"]
1165        task_list = FindTasksByName(find_task_str)
1166        for tval in task_list:
1167            ShowTaskStacks(tval)
1168        return
1169
1170    if not cmd_args:
1171        raise ArgumentError("No arguments passed")
1172
1173    tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
1174    if not tval:
1175        raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args)))
1176    else:
1177        ShowTaskStacks(tval)
1178        return
1179
1180# EndMacro: showtaskstacks
1181
1182def CheckTaskProcRefs(task, proc):
1183    for thread in IterateQueue(task.threads, 'thread *', 'task_threads'):
1184        uthread = GetBSDThread(thread)
1185        refcount = int(uthread.uu_proc_refcount)
1186        uu_ref_info = uthread.uu_proc_ref_info
1187        if int(uu_ref_info) == 0:
1188            continue
1189        uu_ref_index = int(uu_ref_info.upri_pindex)
1190        if refcount == 0:
1191            continue
1192        for ref in range(0, uu_ref_index):
1193            if unsigned(uu_ref_info.upri_proc_ps[ref]) == unsigned(proc):
1194                print GetTaskSummary.header + " " + GetProcSummary.header
1195                pval = Cast(task.bsd_info, 'proc *')
1196                print GetTaskSummary(task) + " " + GetProcSummary(pval)
1197                print "\t" + GetThreadSummary.header
1198                print "\t" + GetThreadSummary(thread) + "\n"
1199
1200                for frame in range (0, 10):
1201                    trace_addr = unsigned(uu_ref_info.upri_proc_pcs[ref][frame])
1202                    symbol_arr = kern.SymbolicateFromAddress(unsigned(trace_addr))
1203                    if symbol_arr:
1204                        symbol_str = str(symbol_arr[0].addr)
1205                    else:
1206                        symbol_str = ''
1207                    print '{0: <#x} {1: <s}'.format(trace_addr, symbol_str)
1208    return
1209
1210@lldb_command('showprocrefs')
1211def ShowProcRefs(cmd_args = None):
1212    """ Display information on threads/BTs that could be holding a reference on the specified proc
1213        NOTE: We can't say affirmatively if any of these references are still held since
1214              there's no way to pair references with drop-refs in the current infrastructure.
1215        Usage: showprocrefs <proc>
1216    """
1217    if cmd_args == None or len(cmd_args) < 1:
1218         raise ArgumentError("No arguments passed")
1219
1220    proc = kern.GetValueFromAddress(cmd_args[0], 'proc *')
1221
1222    for t in kern.tasks:
1223        CheckTaskProcRefs(t, proc)
1224    for t in kern.terminated_tasks:
1225        CheckTaskProcRefs(t, proc)
1226
1227    return
1228
1229@lldb_command('showallthreads')
1230def ShowAllThreads(cmd_args = None):
1231    """ Display info about all threads in the system
1232    """
1233
1234    # Terminated threads get prefixed with a 'T'
1235    def ShowTaskTerminatedThreads(task):
1236        tlist = tmap.get(unsigned(task), [])
1237        for thval in tlist:
1238            print "T\t" + GetThreadSummary(thval)
1239
1240    # Task -> [thread, ..] map of terminated threads
1241    tmap = defaultdict(list)
1242    for thr in kern.terminated_threads:
1243        tmap[unsigned(thr.t_tro.tro_task)].append(thr)
1244
1245    for t in kern.tasks:
1246        ShowTaskThreads([str(int(t))])
1247        ShowTaskTerminatedThreads(t)
1248        print " \n"
1249
1250    for t in kern.terminated_tasks:
1251        print "Terminated: \n"
1252        ShowTaskThreads([str(int(t))])
1253        ShowTaskTerminatedThreads(t)
1254        print " \n"
1255
1256    return
1257
1258@lldb_command('showterminatedthreads')
1259def ShowTerminatedThreads(cmd_args=None):
1260    """ Display info about all terminated threads in the system
1261    """
1262
1263    global kern
1264    print GetThreadSummary.header
1265    for t in kern.terminated_threads:
1266        print GetThreadSummary(t)
1267
1268    return
1269
1270@lldb_command('showtaskthreads', "F:")
1271def ShowTaskThreads(cmd_args = None, cmd_options={}):
1272    """ Display thread information for a given task
1273        Usage: showtaskthreads <0xaddress of task>
1274           or: showtaskthreads -F <name>
1275    """
1276    task_list = []
1277    if "-F" in cmd_options:
1278        task_list = FindTasksByName(cmd_options["-F"])
1279    elif cmd_args:
1280        t = kern.GetValueFromAddress(cmd_args[0], 'task *')
1281        task_list.append(t)
1282    else:
1283        raise ArgumentError("No arguments passed")
1284
1285    for task in task_list:
1286        print GetTaskSummary.header + " " + GetProcSummary.header
1287        pval = Cast(task.bsd_info, 'proc *')
1288        print GetTaskSummary(task) + " " + GetProcSummary(pval)
1289        print "\t" + GetThreadSummary.header
1290        for thval in IterateQueue(task.threads, 'thread *', 'task_threads'):
1291            print "\t" + GetThreadSummary(thval)
1292    return
1293
1294@lldb_command('showact')
1295def ShowAct(cmd_args=None):
1296    """ Routine to print out the state of a specific thread.
1297        usage: showact <activation>
1298    """
1299    if not cmd_args:
1300        raise ArgumentError("No arguments passed")
1301    threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *')
1302    print GetThreadSummary.header
1303    print GetThreadSummary(threadval)
1304
1305@lldb_command('showactstack')
1306def ShowActStack(cmd_args=None):
1307    """ Routine to print out the stack of a specific thread.
1308        usage:  showactstack <activation>
1309    """
1310    if not cmd_args:
1311        raise ArgumentError("No arguments passed")
1312    threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *')
1313    print GetThreadSummary.header
1314    print GetThreadSummary(threadval)
1315    print GetThreadBackTrace(threadval, prefix="\t")
1316    return
1317
1318@lldb_command('switchtoact')
1319def SwitchToAct(cmd_args=None):
1320    """ Switch to different context specified by activation
1321    This command allows gdb to examine the execution context and call
1322    stack for the specified activation. For example, to view the backtrace
1323    for an activation issue "switchtoact <address>", followed by "bt".
1324    Before resuming execution, issue a "resetctx" command, to
1325    return to the original execution context.
1326    """
1327    if cmd_args is None or len(cmd_args) < 1:
1328        raise ArgumentError("No arguments passed")
1329    thval = kern.GetValueFromAddress(cmd_args[0], 'thread *')
1330    lldbthread = GetLLDBThreadForKernelThread(thval)
1331    print GetThreadSummary.header
1332    print GetThreadSummary(thval)
1333    LazyTarget.GetProcess().selected_thread = lldbthread
1334    if not LazyTarget.GetProcess().SetSelectedThread(lldbthread):
1335        print "Failed to switch thread."
1336    return
1337
1338@lldb_command('switchtoregs')
1339def SwitchToRegs(cmd_args=None):
1340    """ Routine to switch to a register state.
1341        Usage: (lldb) switchtoregs <struct arm_saved_state[64] *>
1342        This command creates a fake thread in lldb with the saved register state.
1343        Note: This command ONLY works for ARM based kernel setup.
1344    """
1345
1346    if cmd_args == None or len(cmd_args) < 1:
1347        raise ArgumentError("No arguments passed")
1348
1349    lldb_process = LazyTarget.GetProcess()
1350
1351    saved_state = ArgumentStringToInt(cmd_args[0])
1352    # any change to this logic requires change in operating_system.py as well
1353    fake_thread_id = 0xdead0000 | (saved_state & ~0xffff0000)
1354    fake_thread_id = fake_thread_id & 0xdeadffff
1355    lldb_process.CreateOSPluginThread(0xdeadbeef, saved_state)
1356    lldbthread = lldb_process.GetThreadByID(int(fake_thread_id))
1357
1358    if not lldbthread.IsValid():
1359        print "Failed to create thread"
1360        return
1361
1362    lldb_process.selected_thread = lldbthread
1363    if not lldb_process.SetSelectedThread(lldbthread):
1364        print "Failed to switch thread"
1365    print "Switched to Fake thread created from register state at 0x%x" % saved_state
1366
1367
1368
1369# Macro: showallstacks
1370@lldb_command('showallstacks')
1371def ShowAllStacks(cmd_args=None):
1372    """Routine to print out the stack for each thread in the system.
1373    """
1374    for t in kern.tasks:
1375        ShowTaskStacks(t)
1376        print " \n"
1377    ZombStacks()
1378    return
1379
1380# EndMacro: showallstacks
1381
1382# Macro: showcurrentstacks
1383@lldb_command('showcurrentstacks')
1384def ShowCurrentStacks(cmd_args=None):
1385    """ Routine to print out the thread running on each cpu (incl. its stack)
1386    """
1387    processor_list = kern.GetGlobalVariable('processor_list')
1388    current_processor = processor_list
1389    while unsigned(current_processor) > 0:
1390        print "\n" + GetProcessorSummary(current_processor)
1391        active_thread = current_processor.active_thread
1392        if unsigned(active_thread) != 0 :
1393            task_val = active_thread.t_tro.tro_task
1394            proc_val = Cast(task_val.bsd_info, 'proc *')
1395            print GetTaskSummary.header + " " + GetProcSummary.header
1396            print GetTaskSummary(task_val) + " " + GetProcSummary(proc_val)
1397            print "\t" + GetThreadSummary.header
1398            print "\t" + GetThreadSummary(active_thread)
1399            print "\tBacktrace:"
1400            print GetThreadBackTrace(active_thread, prefix="\t")
1401        current_processor = current_processor.processor_list
1402    return
1403# EndMacro: showcurrentstacks
1404
1405@lldb_command('showcurrentthreads')
1406def ShowCurrentThreads(cmd_args=None):
1407    """ Display info about threads running on each cpu """
1408    processor_list = kern.GetGlobalVariable('processor_list')
1409    current_processor = processor_list
1410    while unsigned(current_processor) > 0:
1411        print GetProcessorSummary(current_processor)
1412        active_thread = current_processor.active_thread
1413        if unsigned(active_thread) != 0 :
1414            task_val = active_thread.t_tro.tro_task
1415            proc_val = Cast(task_val.bsd_info, 'proc *')
1416            print GetTaskSummary.header + " " + GetProcSummary.header
1417            print GetTaskSummary(task_val) + " " + GetProcSummary(proc_val)
1418            print "\t" + GetThreadSummary.header
1419            print "\t" + GetThreadSummary(active_thread)
1420        current_processor = current_processor.processor_list
1421    return
1422
1423def GetFullBackTrace(frame_addr, verbosity = vHUMAN, prefix = ""):
1424    """ Get backtrace across interrupt context.
1425        params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7)
1426                prefix - str - prefix for each line of output.
1427
1428    """
1429    out_string = ""
1430    bt_count = 0
1431    frame_ptr = frame_addr
1432    previous_frame_ptr = 0
1433    # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
1434    mh_execute_addr = int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
1435    while frame_ptr and frame_ptr != previous_frame_ptr and bt_count < 128:
1436        if (not kern.arch.startswith('arm') and frame_ptr < mh_execute_addr) or (kern.arch.startswith('arm') and frame_ptr > mh_execute_addr):
1437            break
1438        pc_val = kern.GetValueFromAddress(frame_ptr + kern.ptrsize,'uintptr_t *')
1439        pc_val = kern.StripKernelPAC(unsigned(dereference(pc_val)))
1440        out_string += prefix + GetSourceInformationForAddress(pc_val) + "\n"
1441        bt_count +=1
1442        previous_frame_ptr = frame_ptr
1443        frame_val = kern.GetValueFromAddress((frame_ptr), 'uintptr_t *')
1444        if unsigned(frame_val) == 0:
1445            break
1446        frame_ptr = unsigned(dereference(frame_val))
1447
1448    return out_string
1449
1450@lldb_command('fullbt')
1451def FullBackTrace(cmd_args=[]):
1452    """ Show full backtrace across the interrupt boundary.
1453        Syntax: fullbt <frame ptr>
1454        Example: fullbt  `$rbp`
1455    """
1456    if len(cmd_args) < 1:
1457        print FullBackTrace.__doc__
1458        return False
1459    print GetFullBackTrace(ArgumentStringToInt(cmd_args[0]), prefix="\t")
1460
1461@lldb_command('fullbtall')
1462def FullBackTraceAll(cmd_args=[]):
1463    """ Show full backtrace across the interrupt boundary for threads running on all processors.
1464        Syntax: fullbtall
1465        Example: fullbtall
1466    """
1467    for processor in IterateLinkedList(kern.globals.processor_list, 'processor_list') :
1468        print "\n" + GetProcessorSummary(processor)
1469        active_thread = processor.active_thread
1470        if unsigned(active_thread) != 0 :
1471            task_val = active_thread.t_tro.tro_task
1472            proc_val = Cast(task_val.bsd_info, 'proc *')
1473            print GetTaskSummary.header + " " + GetProcSummary.header
1474            print GetTaskSummary(task_val) + " " + GetProcSummary(proc_val)
1475            print "\t" + GetThreadSummary.header
1476            print "\t" + GetThreadSummary(active_thread)
1477            print "\tBacktrace:"
1478
1479            ThreadVal = GetLLDBThreadForKernelThread(active_thread)
1480
1481            FramePtr = ThreadVal.frames[0].GetFP()
1482
1483            print GetFullBackTrace(unsigned(FramePtr), prefix="\t")
1484
1485
1486@lldb_command('symbolicate')
1487def SymbolicateAddress(cmd_args=[]):
1488    """ Symbolicate an address for symbol information from loaded symbols
1489        Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr"
1490    """
1491    if len(cmd_args) < 1:
1492        print "Invalid address.\nSyntax: symbolicate <address>"
1493        return False
1494    print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args[0]))
1495    return True
1496
1497@lldb_command('showinitchild')
1498def ShowInitChild(cmd_args=None):
1499    """ Routine to print out all processes in the system
1500        which are children of init process
1501    """
1502    headp = kern.globals.initproc.p_children
1503    for pp in IterateListEntry(headp, 'struct proc *', 'p_sibling'):
1504        print GetProcInfo(pp)
1505    return
1506
1507@lldb_command('showproctree')
1508def ShowProcTree(cmd_args=None):
1509    """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes.
1510        If no argument is given, showproctree will print all the processes in the system.
1511        If pid is specified, showproctree prints all the descendants of the indicated process
1512    """
1513    search_pid = 0
1514    if cmd_args:
1515        search_pid = ArgumentStringToInt(cmd_args[0])
1516
1517    if search_pid < 0:
1518        print "pid specified must be a positive number"
1519        print ShowProcTree.__doc__
1520        return
1521
1522    hdr_format = "{0: <6s} {1: <14s} {2: <9s}\n"
1523    out_string = hdr_format.format("PID", "PROCESS", "POINTER")
1524    out_string += hdr_format.format('='*3, '='*7, '='*7)
1525    proc = GetProcForPid(search_pid)
1526    out_string += "{0: <6d} {1: <32s} [ {2: #019x} ]\n".format(proc.p_ppid, GetProcName(proc.p_pptr), unsigned(proc.p_pptr))
1527    out_string += "|--{0: <6d} {1: <32s} [ {2: #019x} ]\n".format(GetProcPID(proc), GetProcName(proc), unsigned(proc))
1528    print out_string
1529    ShowProcTreeRecurse(proc, "|  ")
1530
1531    return
1532
1533def ShowProcTreeRecurse(proc, prefix=""):
1534    """ Prints descendants of a given proc in hierarchial tree form
1535        params:
1536            proc  : core.value representing a struct proc * in the kernel
1537        returns:
1538            str   : String containing info about a given proc and its descendants in tree form
1539    """
1540    if proc.p_childrencnt > 0:
1541        head_ptr = proc.p_children.lh_first
1542
1543        for p in IterateListEntry(proc.p_children, 'struct proc *', 'p_sibling'):
1544            print prefix + "|--{0: <6d} {1: <32s} [ {2: #019x} ]\n".format(GetProcPID(p), GetProcName(p), unsigned(p))
1545            ShowProcTreeRecurse(p, prefix + "|  ")
1546
1547@lldb_command('showthreadfortid')
1548def ShowThreadForTid(cmd_args=None):
1549    """ The thread structure contains a unique thread_id value for each thread.
1550        This command is used to retrieve the address of the thread structure(thread_t)
1551        corresponding to a given thread_id.
1552    """
1553    if not cmd_args:
1554        print "Please provide thread_t whose tid you'd like to look up"
1555        print ShowThreadForTid.__doc__
1556        return
1557    search_tid = ArgumentStringToInt(cmd_args[0])
1558    for taskp in kern.tasks:
1559        for actp in IterateQueue(taskp.threads, 'struct thread *', 'task_threads'):
1560            if search_tid == int(actp.thread_id):
1561                print "Found {0: #019x}".format(actp)
1562                print GetThreadSummary.header
1563                print GetThreadSummary(actp)
1564                return
1565    print "Not a valid thread_id"
1566
1567def GetProcessorSummary(processor):
1568    """ Internal function to print summary of processor
1569        params: processor - value representing struct processor *
1570        return: str - representing the details of given processor
1571    """
1572
1573    processor_state_str = "INVALID"
1574    processor_state = int(processor.state)
1575
1576    processor_states = {
1577                0: 'OFF_LINE',
1578                1: 'SHUTDOWN',
1579                2: 'START',
1580                # 3 (formerly INACTIVE)
1581                4: 'IDLE',
1582                5: 'DISPATCHING',
1583                6: 'RUNNING'
1584                }
1585
1586    if processor_state in processor_states:
1587        processor_state_str = "{0: <11s} ".format(processor_states[processor_state])
1588
1589    processor_recommended_str = ""
1590    if int(processor.is_recommended) == 0:
1591        processor_recommended_str = " (not recommended)"
1592
1593    ast = 0
1594    preemption_disable = 0
1595    preemption_disable_str = ""
1596
1597    if kern.arch == 'x86_64':
1598        cpu_data = kern.globals.cpu_data_ptr[processor.cpu_id]
1599        if (cpu_data != 0) :
1600            ast = cpu_data.cpu_pending_ast
1601            preemption_disable = cpu_data.cpu_preemption_level
1602    # On arm64, it's kern.globals.CpuDataEntries[processor.cpu_id].cpu_data_vaddr
1603    # but LLDB can't find CpuDataEntries...
1604
1605    ast_str = GetASTSummary(ast)
1606
1607    if (preemption_disable != 0) :
1608        preemption_disable_str = "Preemption Disabled"
1609
1610    out_str = "Processor {: <#018x} cpu_id {:>#4x} AST: {:<6s} State {:<s}{:<s} {:<s}\n".format(
1611            processor, int(processor.cpu_id), ast_str, processor_state_str, processor_recommended_str,
1612            preemption_disable_str)
1613    return out_str
1614
1615ledger_limit_infinity = (uint64_t(0x1).value << 63) - 1
1616
1617def GetLedgerEntryIndex(template, name):
1618    i = 0
1619    while i != template.lt_cnt:
1620        if str(template.lt_entries[i].et_key) == name:
1621            return i
1622        i = i + 1
1623    return -1
1624
1625def GetLedgerEntryWithTemplate(ledger_template, ledgerp, i):
1626    """ Internal function to get internals of a ledger entry (*not* a ledger itself)
1627        params: ledger_template - value representing struct ledger_template_t for the task or thread
1628                ledgerp - value representing ledger pointer
1629                i - index in ledger
1630        return: entry - entry dictionary
1631    """
1632    lf_refill_scheduled = 0x0400
1633    lf_tracking_max = 0x4000
1634
1635    now = unsigned(kern.globals.sched_tick) / 20
1636    lim_pct = 0
1637
1638    entry = {}
1639
1640    et = ledger_template.lt_entries[i]
1641    entry["key"] = str(et.et_key)
1642    if et.et_size == sizeof("struct ledger_entry_small"):
1643        les = ledgerp.l_entries[et.et_offset]
1644        entry["credit"] = unsigned(les.les_credit)
1645        entry["debit"] = 0
1646        entry["flags"] = int(les.les_flags)
1647        entry["limit"] = ledger_limit_infinity
1648    elif et.et_size == sizeof("struct ledger_entry"):
1649        le = Cast(addressof(ledgerp.l_entries[et.et_offset]), "struct ledger_entry *")
1650        entry["credit"] = unsigned(le.le_credit)
1651        entry["debit"] = unsigned(le.le_debit)
1652        if (le.le_flags & lf_tracking_max):
1653            if hasattr(le._le._le_max, "le_interval_max"):
1654                entry["interval_max"] = unsigned(le._le._le_max.le_interval_max)
1655            entry["lifetime_max"] = unsigned(le._le._le_max.le_lifetime_max)
1656
1657        entry["limit"] = unsigned(le.le_limit)
1658
1659        if (le.le_flags & lf_refill_scheduled):
1660            entry["refill_period"] = unsigned (le._le.le_refill.le_refill_period)
1661
1662        if (unsigned(le.le_warn_percent) < 65535):
1663            entry["warn_percent"] = unsigned (le.le_warn_percent * 100 / 65536)
1664        entry["flags"] = int(le.le_flags)
1665    else:
1666        return None
1667
1668    entry["balance"] = entry["credit"] - entry["debit"]
1669    return entry
1670
1671def GetLedgerEntryWithName(ledger_template, ledger, name):
1672    idx = GetLedgerEntryIndex(ledger_template, name)
1673    assert(idx != -1)
1674    return GetLedgerEntryWithTemplate(ledger_template, ledger, idx)
1675
1676def FormatLedgerEntrySummary(entry, i, show_footprint_interval_max=False):
1677    """ internal function to format a ledger entry into a string
1678        params: entry - A python dictionary containing the ledger entry
1679        return: str - formatted output information of ledger entries
1680    """
1681    out_str = ''
1682    out_str += "{: >32s} {:<2d}:".format(entry["key"], i)
1683    out_str += "{: >15d} ".format(entry["balance"])
1684
1685    if (show_footprint_interval_max):
1686        if entry.has_key("interval_max"):
1687            out_str += "{:12d} ".format(entry["interval_max"])
1688        else:
1689            out_str += "           - "
1690
1691    if entry.has_key("lifetime_max"):
1692        out_str += "{:14d} ".format(entry["lifetime_max"])
1693    else:
1694        out_str += "             - "
1695
1696    out_str += "{:12d} {:12d} ".format(entry["credit"], entry["debit"])
1697    if entry.has_key("limit") and entry['limit'] != unsigned(ledger_limit_infinity):
1698        out_str += "{:12d} ".format(unsigned(entry["limit"]))
1699    else:
1700        out_str += "           - "
1701
1702    if entry.has_key("refill_period"):
1703        out_str += "{:15d} ".format(entry["refill_period"])
1704        if entry["refill_period"] != 0:
1705            out_str += "{:9d} ".format((entry["limit"] * 100) / entry["refill_period"])
1706        else:
1707            out_str += "XXXXX     - "
1708    else:
1709        out_str += "              - "
1710        out_str += "        - "
1711
1712    if entry.has_key("warn_percent"):
1713        out_str += "{:9d} ".format(entry["warn_percent"])
1714    else:
1715        out_str += "        - "
1716
1717    if entry.has_key("limit"):
1718        if entry["balance"] > entry["limit"]:
1719            out_str += "    X "
1720        else:
1721            out_str += "      "
1722    else:
1723        out_str += "      "
1724
1725    out_str += "{:#8x}\n".format(entry["flags"])
1726    return out_str
1727
1728def GetLedgerEntrySummary(ledger_template, ledger, i, show_footprint_interval_max=False):
1729    """ internal function to get internals of a ledger entry (*not* a ledger itself)
1730        params: ledger_template - value representing struct ledger_template_t for the task or thread
1731                ledger - value representing ledger pointer
1732        return: str - formatted output information of ledger entries
1733    """
1734    entry = GetLedgerEntryWithTemplate(ledger_template, ledger, i)
1735    return FormatLedgerEntrySummary(entry, i)
1736
1737
1738def GetThreadLedgers(thread_val):
1739    """ Internal function to get a summary of ledger entries for the given thread
1740        params: thread_val - value representing struct thread *
1741        return: thread - python dictionary containing threads's ledger entries. This can
1742        be printed directly with FormatThreadLedgerSummmary or outputted as json.
1743    """
1744    thread = {}
1745    thread["address"] = unsigned(thread_val)
1746    ledgerp = thread_val.t_threadledger
1747    thread["entries"] = []
1748    if ledgerp:
1749        i = 0
1750        while i != ledgerp.l_template.lt_cnt:
1751            thread["entries"].append(GetLedgerEntryWithTemplate(kern.globals.thread_ledger_template,
1752                ledgerp, i))
1753            i = i + 1
1754    return thread
1755
1756def FormatThreadLedgerSummary(thread):
1757    """ Internal function to print a thread's ledger entries
1758        params: thread - python dictionary containing thread's ledger entries
1759        return: str - formatted output information for ledger entries of the input thread
1760    """
1761    out_str = "   [{:#08x}]\n".format(thread["address"])
1762    entries = thread["entries"]
1763    for i, entry in enumerate(entries):
1764        out_str += FormatLedgerEntrySummary(entry, i)
1765    return out_str
1766
1767def GetTaskLedgers(task_val):
1768    """ Internal function to get summary of ledger entries from the task and its threads
1769        params: task_val - value representing struct task *
1770        return: task - python dictionary containing tasks's ledger entries. This can
1771        be printed directly with FormatTaskLedgerSummary or outputted as json.
1772    """
1773    task_ledgerp = task_val.ledger
1774    i = 0
1775    tasks = []
1776    task = {}
1777    task["address"] = unsigned(task_val)
1778
1779    pval = Cast(task_val.bsd_info, 'proc *')
1780    if pval:
1781        task["name"] = GetProcName(pval)
1782        task["pid"] = int(GetProcPID(pval))
1783
1784    task["entries"] = []
1785    while i != task_ledgerp.l_template.lt_cnt:
1786        task["entries"].append(GetLedgerEntryWithTemplate(kern.globals.task_ledger_template, task_ledgerp, i))
1787        i = i + 1
1788
1789    # Now walk threads
1790    task["threads"] = []
1791    for thval in IterateQueue(task_val.threads, 'thread *', 'task_threads'):
1792        task["threads"].append(GetThreadLedgers(thval))
1793
1794    return task
1795
1796@header("{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >14s} {5: >12s} {6: >12s} {7: >12s}   {8: <15s} {9: <8s} {10: <9s} {11: <6s} {12: >6s}".format(
1797            "task [thread]", "entry", "#", "balance", "lifetime_max", "credit",
1798            "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags"))
1799def FormatTaskLedgerSummary(task, show_footprint_interval_max=False):
1800    """ Internal function to get summary of ledger entries from the task and its threads
1801        params: task_val - value representing struct task *
1802        return: str - formatted output information for ledger entries of the input task
1803    """
1804    out_str = ''
1805    out_str += "{: #08x} ".format(task["address"])
1806    if task.has_key("name"):
1807        out_str += "{: <5s}:\n".format(task["name"])
1808    else:
1809        out_str += "Invalid process\n"
1810
1811    for i, entry in enumerate(task["entries"]):
1812        out_str += FormatLedgerEntrySummary(entry, i, show_footprint_interval_max)
1813
1814    for thread in task["threads"]:
1815        out_str += FormatThreadLedgerSummary(thread)
1816    return out_str
1817
1818
1819# Macro: showtaskledgers
1820
1821@lldb_command('showtaskledgers', 'JF:I')
1822def ShowTaskLedgers(cmd_args=None, cmd_options={}):
1823    """  Routine to print a summary  of ledger entries for the task and all of its threads
1824         or   : showtaskledgers [ -I ] [-J] [ -F ] <task>
1825         options:
1826            -I: show footprint interval max (DEV/DEBUG only)
1827            -F: specify task via name instead of address
1828            -J: output json
1829        -
1830    """
1831    print_json = False
1832    if "-F" in cmd_options:
1833        task_list = FindTasksByName(cmd_options["-F"])
1834        for tval in task_list:
1835            print FormatTaskLedgerSummary.header
1836            ledgers = GetTaskLedgers(tval)
1837            print FormatTaskLedgerSummary(ledgers)
1838        return
1839    if "-J" in cmd_options:
1840        print_json = True
1841
1842    if not cmd_args:
1843        raise ArgumentError("No arguments passed.")
1844    show_footprint_interval_max = False
1845    if "-I" in cmd_options:
1846        show_footprint_interval_max = True
1847    tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
1848    if not tval:
1849        raise ArgumentError("unknown arguments: %r" %cmd_args)
1850    ledgers = GetTaskLedgers(tval)
1851    if print_json:
1852        print json.dumps(ledgers)
1853    else:
1854        if (show_footprint_interval_max):
1855            print "{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >12s} {5: >14s} {6: >12s} {7: >12s} {8: >12s}   {9: <15s} {10: <8s} {11: <9s} {12: <6s} {13: >6s}".format(
1856            "task [thread]", "entry", "#", "balance", "intrvl_max", "lifetime_max", "credit",
1857            "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")
1858        else:
1859            print FormatTaskLedgerSummary.header
1860        print FormatTaskLedgerSummary(ledgers, show_footprint_interval_max)
1861
1862# EndMacro: showtaskledgers
1863
1864# Macro: showalltaskledgers
1865
1866@lldb_command('showalltaskledgers', "J")
1867def ShowAllTaskLedgers(cmd_args=None, cmd_options={}):
1868    """  Routine to print a summary  of ledger entries for all tasks and respective threads
1869         Usage: showalltaskledgers [-J]
1870            -J      : Output json
1871    """
1872    print_json = False
1873    if "-J" in cmd_options:
1874        print_json = True
1875    tasks = []
1876    for t in kern.tasks:
1877        task_val = unsigned(t)
1878        if not print_json:
1879            ShowTaskLedgers([task_val], cmd_options=cmd_options)
1880        else:
1881            tasks.append(GetTaskLedgers(t))
1882    if print_json:
1883        print json.dumps(tasks)
1884
1885# EndMacro: showalltaskledgers
1886
1887# Macro: showprocuuidpolicytable
1888
1889@lldb_type_summary(['proc_uuid_policy_entry'])
1890@header("{0: <36s} {1: <10s}".format("uuid", "flags"))
1891def GetProcUUIDPolicyEntrySummary(entry):
1892    """ Summarizes the important fields in proc_uuid_policy_entry structure.
1893        params: entry: value - value object representing an entry
1894        returns: str - summary of the entry
1895    """
1896    data = []
1897    for i in range(16):
1898        data.append(int(entry.uuid[i]))
1899    flags = unsigned(entry.flags)
1900    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)
1901    return out_string
1902
1903@lldb_command('showprocuuidpolicytable')
1904def ShowProcUUIDPolicyTable(cmd_args=None):
1905    """ Routine to print the proc UUID policy table
1906        Usage: showprocuuidpolicytable
1907    """
1908    hashslots = unsigned(kern.globals.proc_uuid_policy_hash_mask)
1909    print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary.header
1910    for i in range(0, hashslots+1):
1911        headp = addressof(kern.globals.proc_uuid_policy_hashtbl[i])
1912        entrynum = 0
1913        for entry in IterateListEntry(headp, 'struct proc_uuid_policy_entry *', 'entries'):
1914            print "{0: >2d}.{1: <5d} ".format(i, entrynum) + GetProcUUIDPolicyEntrySummary(entry)
1915            entrynum += 1
1916
1917
1918# EndMacro: showprocuuidpolicytable
1919
1920@lldb_command('showalltaskpolicy')
1921def ShowAllTaskPolicy(cmd_args=None):
1922    """
1923         Routine to print a summary listing of all the tasks
1924         wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1925         if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1926         io_policy -> RAGE  - rapid aging of vnodes requested
1927                     NORM  - normal I/O explicitly requested (this is the default)
1928                     PASS  - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1929                     THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1930    """
1931    global kern
1932    print GetTaskSummary.header + " " + GetProcSummary.header
1933    for t in kern.tasks:
1934        pval = Cast(t.bsd_info, 'proc *')
1935        print GetTaskSummary(t) +" "+ GetProcSummary(pval)
1936        requested_strings = [
1937                ["int_darwinbg",        "DBG-int"],
1938                ["ext_darwinbg",        "DBG-ext"],
1939                ["int_iotier",          "iotier-int"],
1940                ["ext_iotier",          "iotier-ext"],
1941                ["int_iopassive",       "passive-int"],
1942                ["ext_iopassive",       "passive-ext"],
1943                ["bg_iotier",           "bg-iotier"],
1944                ["terminated",          "terminated"],
1945                ["th_pidbind_bg",       "bg-pidbind"],
1946                ["t_apptype",           "apptype"],
1947                ["t_boosted",           "boosted"],
1948                ["t_role",              "role"],
1949                ["t_tal_enabled",       "tal-enabled"],
1950                ["t_base_latency_qos",  "latency-base"],
1951                ["t_over_latency_qos",  "latency-override"],
1952                ["t_base_through_qos",  "throughput-base"],
1953                ["t_over_through_qos",  "throughput-override"]
1954                ]
1955
1956        requested=""
1957        for value in requested_strings:
1958            if t.requested_policy.__getattr__(value[0]) :
1959                requested+=value[1] + ": " + str(t.requested_policy.__getattr__(value[0])) + " "
1960            else:
1961                requested+=""
1962
1963        suppression_strings = [
1964                ["t_sup_active",        "active"],
1965                ["t_sup_lowpri_cpu",    "lowpri-cpu"],
1966                ["t_sup_timer",         "timer-throttling"],
1967                ["t_sup_disk",          "disk-throttling"],
1968                ["t_sup_cpu_limit",     "cpu-limits"],
1969                ["t_sup_suspend",       "suspend"],
1970                ["t_sup_bg_sockets",    "bg-sockets"]
1971                ]
1972
1973        suppression=""
1974        for value in suppression_strings:
1975            if t.requested_policy.__getattr__(value[0]) :
1976                suppression+=value[1] + ": " + str(t.requested_policy.__getattr__(value[0])) + " "
1977            else:
1978                suppression+=""
1979
1980        effective_strings = [
1981                ["darwinbg",        "background"],
1982                ["lowpri_cpu",      "lowpri-cpu"],
1983                ["io_tier",         "iotier"],
1984                ["io_passive",      "passive"],
1985                ["all_sockets_bg",  "bg-allsockets"],
1986                ["new_sockets_bg",  "bg-newsockets"],
1987                ["bg_iotier",       "bg-iotier"],
1988                ["terminated",      "terminated"],
1989                ["t_gpu_deny",      "gpu-deny"],
1990                ["t_tal_engaged",   "tal-engaged"],
1991                ["t_suspended",     "suspended"],
1992                ["t_watchers_bg",   "bg-watchers"],
1993                ["t_latency_qos",   "latency-qos"],
1994                ["t_through_qos",   "throughput-qos"],
1995                ["t_sup_active",    "suppression-active"],
1996                ["t_role",          "role"]
1997                ]
1998
1999        effective=""
2000        for value in effective_strings:
2001            if t.effective_policy.__getattr__(value[0]) :
2002                effective+=value[1] + ": " + str(t.effective_policy.__getattr__(value[0])) + " "
2003            else:
2004                effective+=""
2005
2006        print "requested: " + requested
2007        print "suppression: " + suppression
2008        print "effective: " + effective
2009
2010
2011@lldb_type_summary(['wait_queue', 'wait_queue_t'])
2012@header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask"))
2013def GetWaitQSummary(waitq):
2014    """ Summarizes the important fields in task structure.
2015        params: task: value - value object representing a task in kernel
2016        returns: str - summary of the task
2017    """
2018    out_string = ""
2019    format_string = '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
2020
2021    wqtype = ""
2022
2023    if (waitq.wq_fifo == 1) :
2024        wqtype += "FIFO"
2025    else :
2026        wqtype += "PRIO"
2027
2028    if (waitq.wq_prepost == 1) :
2029        wqtype += "Prepost"
2030
2031    if (waitq.wq_type == 0x3) :
2032        wqtype += "Set"
2033    elif (waitq.wq_type == 0x2) :
2034        wqtype += "Queue"
2035    else :
2036        wqtype += "INVALID"
2037
2038    out_string += format_string.format(waitq, unsigned(waitq.wq_interlock.lock_data), policy, 0, 0, unsigned(waitq.wq_eventmask))
2039
2040    out_string += "\n" + GetThreadSummary.header
2041
2042    for thread in IterateQueue(waitq.wq_queue, "thread_t", "links"):
2043        out_string += "\n" + GetThreadSummary(thread)
2044
2045    return out_string
2046
2047
2048@lldb_command('showallsuspendedtasks', '')
2049def ShowSuspendedTasks(cmd_args=[], options={}):
2050    """ Show a list of suspended tasks with their process name summary.
2051    """
2052    print GetTaskSummary.header + ' ' + GetProcSummary.header
2053    for t in kern.tasks:
2054        if t.suspend_count > 0:
2055            print GetTaskSummary(t) + ' ' + GetProcSummary(Cast(t.bsd_info, 'proc *'))
2056    return True
2057
2058# Macro: showallpte
2059@lldb_command('showallpte')
2060def ShowAllPte(cmd_args=None):
2061    """ Prints out the physical address of the pte for all tasks
2062    """
2063    head_taskp = addressof(kern.globals.tasks)
2064    taskp = Cast(head_taskp.next, 'task *')
2065    while taskp != head_taskp:
2066        procp = Cast(taskp.bsd_info, 'proc *')
2067        out_str = "task = {:#x} pte = {:#x}\t".format(taskp, taskp.map.pmap.ttep)
2068        if procp != 0:
2069            out_str += "{:s}\n".format(GetProcName(procp))
2070        else:
2071            out_str += "\n"
2072        print out_str
2073        taskp = Cast(taskp.tasks.next, 'struct task *')
2074
2075# EndMacro: showallpte
2076
2077# Macro: showallrefcounts
2078@lldb_command('showallrefcounts')
2079@header("{0: <20s} {1: ^10s}".format("task", "ref_count"))
2080def ShowAllRefCounts(cmd_args=None):
2081    """ Prints the ref_count of all tasks
2082    """
2083    out_str = ''
2084    head_taskp = addressof(kern.globals.tasks)
2085    taskp = Cast(head_taskp.next, 'task *')
2086    print ShowAllRefCounts.header
2087    while taskp != head_taskp:
2088        out_str += "{: <#20x}".format(taskp)
2089        out_str += "{: ^10d}\n".format(taskp.ref_count)
2090        taskp = Cast(taskp.tasks.next, 'task *')
2091    print out_str
2092# EndMacro: showallrefcounts
2093
2094# Macro: showallrunnablethreads
2095@lldb_command('showallrunnablethreads')
2096def ShowAllRunnableThreads(cmd_args=None):
2097    """ Prints the sched usage information for all threads of each task
2098    """
2099    out_str = ''
2100    for taskp in kern.tasks:
2101        for actp in IterateQueue(taskp.threads, 'thread *', 'task_threads'):
2102            if int(actp.state & 0x4):
2103                ShowActStack([unsigned(actp)])
2104
2105# EndMacro: showallrunnablethreads
2106
2107# Macro: showallschedusage
2108@lldb_command('showallschedusage')
2109@header("{0:<20s} {1:^10s} {2:^10s} {3:^15s}".format("Thread", "Priority", "State", "sched_usage"))
2110def ShowAllSchedUsage(cmd_args=None):
2111    """ Prints the sched usage information for all threads of each task
2112    """
2113    out_str = ''
2114    for taskp in kern.tasks:
2115        ShowTask([unsigned(taskp)])
2116        print ShowAllSchedUsage.header
2117        for actp in IterateQueue(taskp.threads, 'thread *', 'task_threads'):
2118            out_str = "{: <#20x}".format(actp)
2119            out_str += "{: ^10s}".format(str(int(actp.sched_pri)))
2120            state = int(actp.state)
2121            thread_state_chars = {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'}
2122            state_str = ''
2123            state_str += thread_state_chars[int(state & 0x1)]
2124            state_str += thread_state_chars[int(state & 0x2)]
2125            state_str += thread_state_chars[int(state & 0x4)]
2126            state_str += thread_state_chars[int(state & 0x8)]
2127            state_str += thread_state_chars[int(state & 0x10)]
2128            state_str += thread_state_chars[int(state & 0x20)]
2129            state_str += thread_state_chars[int(state & 0x40)]
2130            state_str += thread_state_chars[int(state & 0x80)]
2131            out_str += "{: ^10s}".format(state_str)
2132            out_str += "{: >15d}".format(actp.sched_usage)
2133            print out_str + "\n"
2134        print "\n\n"
2135
2136# EndMacro: showallschedusage
2137
2138#Macro: showprocfilessummary
2139@lldb_command('showprocfilessummary')
2140@header("{0: <20s} {1: <20s} {2: >10s}".format("Process", "Name", "Number of Open Files"))
2141def ShowProcFilesSummary(cmd_args=None):
2142    """ Display the summary of open file descriptors for all processes in task list
2143        Usage: showprocfilessummary
2144    """
2145    print ShowProcFilesSummary.header
2146    for proc in kern.procs:
2147        proc_filedesc = addressof(proc.p_fd)
2148        proc_ofiles = proc_filedesc.fd_ofiles
2149        proc_file_count = 0
2150        for fd in xrange(0, proc_filedesc.fd_first_allfree):
2151            if unsigned(proc_ofiles[fd]) != 0:
2152                proc_file_count += 1
2153        print "{0: <#020x} {1: <32s} {2: >10d}".format(proc, GetProcName(proc), proc_file_count)
2154
2155#EndMacro: showprocfilessummary
2156
2157@lldb_command('workinguserstacks')
2158def WorkingUserStacks(cmd_args=None):
2159    """ Print out the user stack for each thread in a task, followed by the user libraries.
2160        Syntax: (lldb) workinguserstacks <task_t>
2161    """
2162    if not cmd_args:
2163        print "Insufficient arguments" + ShowTaskUserStacks.__doc__
2164        return False
2165    task = kern.GetValueFromAddress(cmd_args[0], 'task *')
2166    print GetTaskSummary.header + " " + GetProcSummary.header
2167    pval = Cast(task.bsd_info, 'proc *')
2168    print GetTaskSummary(task) + " " + GetProcSummary(pval) + "\n \n"
2169    for thval in IterateQueue(task.threads, 'thread *', 'task_threads'):
2170        print "For thread 0x{0:x}".format(thval)
2171        try:
2172            ShowThreadUserStack([hex(thval)])
2173        except Exception as exc_err:
2174            print "Failed to show user stack for thread 0x{0:x}".format(thval)
2175            if config['debug']:
2176                raise exc_err
2177            else:
2178                print "Enable debugging ('(lldb) xnudebug debug') to see detailed trace."
2179    WorkingUserLibraries([hex(task)])
2180    return
2181
2182@static_var("exec_load_path", 0)
2183@lldb_command("workingkuserlibraries")
2184def WorkingUserLibraries(cmd_args=None):
2185    """ Show binary images known by dyld in target task
2186        For a given user task, inspect the dyld shared library state and print information about all Mach-O images.
2187        Syntax: (lldb)workinguserlibraries <task_t>
2188    """
2189    if not cmd_args:
2190        print "Insufficient arguments"
2191        print ShowTaskUserLibraries.__doc__
2192        return False
2193
2194    print "{0: <18s} {1: <12s} {2: <36s} {3: <50s}".format('address','type','uuid','path')
2195    out_format = "0x{0:0>16x} {1: <12s} {2: <36s} {3: <50s}"
2196    task = kern.GetValueFromAddress(cmd_args[0], 'task_t')
2197    is_task_64 = int(task.t_flags) & 0x1
2198    dyld_all_image_infos_address = unsigned(task.all_image_info_addr)
2199    cur_data_offset = 0
2200    if dyld_all_image_infos_address == 0:
2201        print "No dyld shared library information available for task"
2202        return False
2203    vers_info_data = GetUserDataAsString(task, dyld_all_image_infos_address, 112)
2204    version = _ExtractDataFromString(vers_info_data, cur_data_offset, "uint32_t")
2205    cur_data_offset += 4
2206    if version > 12:
2207        print "Unknown dyld all_image_infos version number %d" % version
2208    image_info_count = _ExtractDataFromString(vers_info_data, cur_data_offset, "uint32_t")
2209    WorkingUserLibraries.exec_load_path = 0
2210    if is_task_64:
2211        image_info_size = 24
2212        image_info_array_address = _ExtractDataFromString(vers_info_data, 8, "uint64_t")
2213        dyld_load_address = _ExtractDataFromString(vers_info_data, 8*4, "uint64_t")
2214        dyld_all_image_infos_address_from_struct = _ExtractDataFromString(vers_info_data, 8*13, "uint64_t")
2215    else:
2216        image_info_size = 12
2217        image_info_array_address = _ExtractDataFromString(vers_info_data, 4*2, "uint32_t")
2218        dyld_load_address = _ExtractDataFromString(vers_info_data, 4*5, "uint32_t")
2219        dyld_all_image_infos_address_from_struct = _ExtractDataFromString(vers_info_data, 4*14, "uint32_t")
2220    # Account for ASLR slide before dyld can fix the structure
2221    dyld_load_address = dyld_load_address + (dyld_all_image_infos_address - dyld_all_image_infos_address_from_struct)
2222
2223    i = 0
2224    while i < image_info_count:
2225        image_info_address = image_info_array_address + i * image_info_size
2226        img_data = GetUserDataAsString(task, image_info_address, image_info_size)
2227        if is_task_64:
2228            image_info_addr = _ExtractDataFromString(img_data, 0, "uint64_t")
2229            image_info_path = _ExtractDataFromString(img_data, 8, "uint64_t")
2230        else:
2231            image_info_addr = _ExtractDataFromString(img_data, 0, "uint32_t")
2232            image_info_path = _ExtractDataFromString(img_data, 4, "uint32_t")
2233        PrintImageInfo(task, image_info_addr, image_info_path)
2234        i += 1
2235
2236    # load_path might get set when the main executable is processed.
2237    if WorkingUserLibraries.exec_load_path != 0:
2238        PrintImageInfo(task, dyld_load_address, WorkingUserLibraries.exec_load_path)
2239    return
2240
2241# Macro: showstackaftertask
2242@lldb_command('showstackaftertask','F:')
2243def Showstackaftertask(cmd_args=None,cmd_options={}):
2244    """ Routine to print the thread stacks for all tasks succeeding a given task
2245        Usage: showstackaftertask <0xaddress of task>
2246           or: showstackaftertask  -F <taskname>
2247    """
2248    if "-F" in cmd_options:
2249        # Find the task pointer corresponding to its task name
2250        find_task_str = cmd_options["-F"]
2251        task_list = FindTasksByName(find_task_str)
2252
2253        # Iterate through the list of tasks and print all task stacks thereafter
2254        for tval in task_list:
2255            ListTaskStacks(tval)
2256        return
2257
2258    if not cmd_args:
2259        raise ArgumentError("Insufficient arguments")
2260    tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
2261    if not tval:
2262        raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args)))
2263    else:
2264        ListTaskStacks(tval)
2265
2266    ZombStacks()
2267    return
2268# EndMacro: showstackaftertask
2269
2270def ListTaskStacks(task):
2271    """ Search for a given task and print the list of all task stacks thereafter.
2272    """
2273    # Initialize local variable task_flag to mark when a given task is found.
2274    task_flag=0
2275
2276    for t in kern.tasks:
2277        if (task_flag == 1):
2278            ShowTaskStacks(t)
2279            print "\n"
2280        if (t == task):
2281            task_flag = 1
2282
2283# Macro: showstackafterthread
2284@lldb_command('showstackafterthread')
2285def Showstackafterthread(cmd_args = None):
2286    """ Routine to print the stacks of all threads succeeding a given thread.
2287        Usage: Showstackafterthread <0xaddress of thread>
2288    """
2289    # local variable thread_flag is used to mark when a given thread is found.
2290    thread_flag=0
2291    if cmd_args:
2292       threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *')
2293    else:
2294        raise ArgumentError("No arguments passed")
2295    # Iterate through list of all tasks to look up a given thread
2296    for t in kern.tasks:
2297        if(thread_flag==1):
2298            pval = Cast(t.bsd_info, 'proc *')
2299            print GetTaskSummary.header + " "+ GetProcSummary.header
2300            print GetTaskSummary(t) +     " "+ GetProcSummary(pval)
2301            print "\n"
2302         # Look up for a given thread from the the list of threads of a given task
2303        for thval in IterateQueue(t.threads, 'thread *', 'task_threads'):
2304            if (thread_flag==1):
2305               print "\n"
2306               print "  " + GetThreadSummary.header
2307               print "  " + GetThreadSummary(thval)
2308               print GetThreadBackTrace(thval, prefix="\t")+"\n"
2309               print "\n"
2310
2311            if(thval==threadval):
2312               pval = Cast(t.bsd_info, 'proc *')
2313               process_name = "{:s}".format(GetProcName(pval))
2314               print "\n\n"
2315               print " *** Continuing to dump the thread stacks from the process *** :" + " " + process_name
2316               print "\n\n"
2317               thread_flag = 1
2318        print '\n'
2319    return
2320