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. 
   9 from core
.lazytarget 
import * 
  14 def GetProcNameForTask(task
): 
  15     """ returns a string name of the process. if proc is not valid "unknown" is returned 
  17             task: value object represeting a task in the kernel. 
  19             str : A string name of the process linked to the task 
  21     if not task 
or not unsigned(task
.bsd_info
): 
  23     p 
= Cast(task
.bsd_info
, 'proc *') 
  26 def GetProcPIDForTask(task
): 
  27     """ returns a int pid of the process. if the proc is not valid, val[5] from audit_token is returned. 
  29             task: value object representing a task in the kernel 
  31             int : pid of the process or -1 if not found 
  33     if task 
and unsigned(task
.bsd_info
): 
  34         p 
= Cast(task
.bsd_info
, 'proc *') 
  35         return unsigned(p
.p_pid
) 
  38         return unsigned(task
.audit_token
.val
[5]) 
  42 def GetProcInfo(proc
): 
  43     """ returns a string name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields. 
  45             proc : value object representing a proc in the kernel 
  47             str : A string describing various information for process. 
  50     out_string 
+= ("Process {p: <#020x}\n\tname {p.p_comm: <20s}\n\tpid:{p.p_pid: <6d} " +  
  51                    "task:{p.task: <#020x} p_stat:{p.p_stat: <6d} parent pid: {p.p_ppid: <6d}\n" 
  56         out_string 
+= "Cred: euid {:d} ruid {:d} svuid {:d}\n".format(ucred
.cr_posix
.cr_uid
, 
  57                                                                       ucred
.cr_posix
.cr_ruid
, 
  58                                                                       ucred
.cr_posix
.cr_svuid 
) 
  60     flags 
= int(proc
.p_flag
) 
  61     out_string 
+= "Flags: {0: <#020x}\n".format(flags
) 
  66             out_string 
+= "\t" + xnudefines
.proc_flag_explain_strings
[i
] + "\n" 
  67         elif num 
== 0x4: #special case for 32bit flag 
  68             out_string 
+= "\t" + xnudefines
.proc_flag_explain_strings
[0] + "\n" 
  71     out_string 
+= "State: " 
  72     state_val 
= proc
.p_stat
 
  73     if state_val 
< 1 or state_val 
> len(xnudefines
.proc_state_strings
) : 
  74         out_string 
+= "(Unknown)" 
  76         out_string 
+= xnudefines
.proc_state_strings
[int(state_val
)] 
  80 def GetProcNameForPid(pid
): 
  81     """ Finds the name of the process corresponding to a given pid 
  83             pid     : int, pid you want to find the procname for 
  85             str     : Name of the process corresponding to the pid, "Unknown" if not found 
  88         if int(p
.p_pid
) == int(pid
): 
  92 def GetProcForPid(search_pid
): 
  93     """ Finds the value object representing a proc in the kernel based on its pid 
  95             search_pid  : int, pid whose proc structure you want to find 
  97             value       : The value object representing the proc, if a proc corresponding 
  98                           to the given pid is found. Returns None otherwise 
 101         return kern
.globals.initproc
 
 103         headp 
= kern
.globals.allproc
 
 104         for proc 
in IterateListEntry(headp
, 'struct proc *', 'p_list'): 
 105             if proc
.p_pid 
== search_pid
: 
 109 @lldb_command('allproc') 
 110 def AllProc(cmd_args
=None): 
 111     """ Walk through the allproc structure and print procinfo for each process structure.  
 113             cmd_args - [] : array of strings passed from lldb command prompt 
 115     for proc 
in kern
.procs 
: 
 116         print GetProcInfo(proc
) 
 119 @lldb_command('zombproc') 
 120 def ZombProc(cmd_args
=None): 
 121     """ Routine to print out all procs in the zombie list 
 123             cmd_args - [] : array of strings passed from lldb command prompt 
 125     if len(kern
.zombprocs
) != 0: 
 126         print "\nZombie Processes:" 
 127         for proc 
in kern
.zombprocs
: 
 128             print GetProcInfo(proc
) + "\n\n" 
 130 @lldb_command('zombtasks') 
 131 def ZombTasks(cmd_args
=None): 
 132     """ Routine to print out all tasks in the zombie list 
 136     if len(kern
.zombprocs
) != 0: 
 137         header 
= "\nZombie Tasks:\n" 
 138         header 
+= GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
 139         for proc 
in kern
.zombprocs
: 
 141                 t 
= Cast(proc
.task
, 'task *') 
 142                 out_str 
+= GetTaskSummary(t
) +" "+ GetProcSummary(proc
) + "\n" 
 147 @lldb_command('zombstacks') 
 148 def ZombStacks(cmd_args
=None): 
 149     """ Routine to print out all stacks of tasks that are exiting 
 152     for proc 
in kern
.zombprocs
: 
 155                 print "\nZombie Stacks:" 
 157             t 
= Cast(proc
.task
, 'task *') 
 161 def GetASTSummary(ast
): 
 162     """ Summarizes an AST field 
 177         T - AST_TELEMETRY_USER 
 178         T - AST_TELEMETRY_KERNEL 
 179         T - AST_TELEMETRY_WINDOWED 
 187     thread_state_chars 
= {0x0:'', 0x1:'P', 0x2:'Q', 0x4:'U', 0x8:'H', 0x10:'Y', 0x20:'A', 
 188                           0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M', 0x400:'C', 0x800:'C', 
 189                           0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S', 
 190                           0x20000: 'D', 0x40000: 'I', 0x80000: 'E'} 
 193     while mask 
<= 0x80000: 
 194         state_str 
+= thread_state_chars
[int(state 
& mask
)] 
 200 @lldb_type_summary(['kcdata_descriptor *', 'kcdata_descriptor_t']) 
 201 @header("{0: <20s} {1: <20s} {2: <20s} {3: <10s} {4: <5s}".format("kcdata_descriptor", "begin_addr", "cur_pos", "size", "flags")) 
 202 def GetKCDataSummary(kcdata
): 
 203     """ Summarizes kcdata_descriptor structure 
 204         params: kcdata: value - value object representing kcdata_descriptor 
 205         returns: str - summary of the kcdata object 
 207     format_string 
= "{0: <#020x} {1: <#020x} {2: <#020x} {3: <10d} {4: <#05x}" 
 208     return format_string
.format(kcdata
, kcdata
.kcd_addr_begin
, kcdata
.kcd_addr_end
, kcdata
.kcd_length
, kcdata
.kcd_flags
) 
 211 @lldb_type_summary(['task', 'task_t']) 
 212 @header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags")) 
 213 def GetTaskSummary(task
, showcorpse
=False): 
 214     """ Summarizes the important fields in task structure. 
 215         params: task: value - value object representing a task in kernel 
 216         returns: str - summary of the task 
 219     format_string 
= '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}' 
 220     thread_count 
= int(task
.thread_count
) 
 222     if hasattr(task
, "suppression_generation") and (int(task
.suppression_generation
) & 0x1) == 0x1: 
 224     if hasattr(task
, "effective_policy") and int(task
.effective_policy
.tep_sup_active
) == 1: 
 226     if hasattr(task
, "suspend_count") and int(task
.suspend_count
) > 0: 
 228     if hasattr(task
, 'task_imp_base') and unsigned(task
.task_imp_base
): 
 229         tib 
= task
.task_imp_base
 
 230         if int(tib
.iit_receiver
) == 1: 
 232         if int(tib
.iit_donor
) == 1: 
 234         if int(tib
.iit_assertcnt
) > 0: 
 237     # check if corpse flag is set 
 238     if unsigned(task
.t_flags
) & 0x20: 
 240     if unsigned(task
.t_flags
) & 0x40: 
 243     out_string 
+= format_string
.format(task
, task
.map, task
.itk_space
, thread_count
, task_flags
) 
 244     if showcorpse 
is True and unsigned(task
.corpse_info
) != 0: 
 245         out_string 
+= " " + GetKCDataSummary(task
.corpse_info
) 
 248 def GetThreadName(thread
): 
 249     """ Get the name of a thread, if possible.  Returns the empty string 
 252     if int(thread
.uthread
) != 0: 
 253         uthread 
= Cast(thread
.uthread
, 'uthread *') 
 254         if int(uthread
.pth_name
) != 0 : 
 255             th_name_strval 
= Cast(uthread
.pth_name
, 'char *') 
 256             if len(str(th_name_strval
)) > 0 : 
 257                 return str(th_name_strval
) 
 261 @lldb_type_summary(['thread *', 'thread_t']) 
 262 @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')) 
 263 def GetThreadSummary(thread
): 
 264     """ Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct. 
 265         params: thread: value - value objecte representing a thread in kernel 
 266         returns: str - summary of a thread 
 274         A - Terminated and on termination queue 
 285     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}" 
 286     thread_ptr_str 
= str("{0: <#020x}".format(thread
)) 
 287     if int(thread
.static_param
) :  
 288         thread_ptr_str
+="[WQ]" 
 289     thread_id 
= hex(thread
.thread_id
) 
 290     processor 
= hex(thread
.last_processor
) 
 291     base_priority 
= str(int(thread
.base_pri
)) 
 292     sched_priority 
= str(int(thread
.sched_pri
)) 
 294     mode 
= str(thread
.sched_mode
) 
 295     if "TIMESHARE" in mode
: 
 296         sched_mode
+="timeshare" 
 297     elif "FIXED" in mode
: 
 299     elif "REALTIME" in mode
: 
 300         sched_mode
+="realtime" 
 302     if (unsigned(thread
.bound_processor
) != 0): 
 306     if (unsigned(thread
.sched_flags
) & 0x0004): 
 310     thread_name 
= GetThreadName(thread
) 
 311     if int(thread
.uthread
) != 0: 
 312         uthread 
= Cast(thread
.uthread
, 'uthread *') 
 314         #check for io_policy flags  
 315         if int(uthread
.uu_flag
) & 0x400: 
 316             io_policy_str
+='RAGE ' 
 318         #now flags for task_policy 
 322         if int(thread
.effective_policy
.thep_darwinbg
) != 0: 
 324         if int(thread
.effective_policy
.thep_io_tier
) != 0: 
 326         if int(thread
.effective_policy
.thep_io_passive
) != 0: 
 328         if int(thread
.effective_policy
.thep_terminated
) != 0: 
 331     state 
= int(thread
.state
) 
 332     thread_state_chars 
= {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
 
 336         state_str 
+= thread_state_chars
[int(state 
& mask
)] 
 339     if int(thread
.inspection
): 
 342     ast 
= int(thread
.ast
) | 
int(thread
.reason
) 
 343     ast_str 
= GetASTSummary(ast
) 
 345     #wait queue information 
 349     if ( state 
& 0x1 ) != 0: 
 350         #we need to look at the waitqueue as well 
 351         wait_queue_str 
= str("{0: <#020x}".format(int(hex(thread
.waitq
), 16))) 
 352         wait_event_str 
= str("{0: <#020x}".format(int(hex(thread
.wait_event
), 16))) 
 353         wait_event_str_sym 
= kern
.Symbolicate(int(hex(thread
.wait_event
), 16)) 
 354         if len(wait_event_str_sym
) > 0: 
 355             wait_event_str 
= wait_event_str
.strip() + " <" + wait_event_str_sym 
+ ">" 
 356         if int(thread
.uthread
) != 0 : 
 357             uthread 
= Cast(thread
.uthread
, 'uthread *') 
 358             if int(uthread
.uu_wmesg
) != 0: 
 359                 wait_message 
= str(Cast(uthread
.uu_wmesg
, 'char *')) 
 361     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
) 
 365 def GetTaskRoleString(role
): 
 367                  0 : "TASK_UNSPECIFIED", 
 368                  1 : "TASK_FOREGROUND_APPLICATION", 
 369                  2 : "TASK_BACKGROUND_APPLICATION", 
 370                  3 : "TASK_CONTROL_APPLICATION", 
 371                  4 : "TASK_GRAPHICS_SERVER", 
 372                  5 : "TASK_THROTTLE_APPLICATION", 
 373                  6 : "TASK_NONUI_APPLICATION", 
 374                  7 : "TASK_DEFAULT_APPLICATION", 
 376     return role_strs
[int(role
)] 
 378 def GetCoalitionFlagString(coal
): 
 380     if (coal
.privileged
): 
 381         flags
.append('privileged') 
 382     if (coal
.termrequested
): 
 383         flags
.append('termrequested') 
 384     if (coal
.terminated
): 
 385         flags
.append('terminated') 
 387         flags
.append('reaped') 
 389         flags
.append('notified') 
 391         flags
.append('efficient') 
 392     return "|".join(flags
) 
 394 def GetCoalitionTasks(queue
, coal_type
, thread_details
=False): 
 396                  0x0  : "SFI_CLASS_UNSPECIFIED", 
 397                  0x1  : "SFI_CLASS_DARWIN_BG", 
 398                  0x2  : "SFI_CLASS_APP_NAP", 
 399                  0x3  : "SFI_CLASS_MANAGED_FOCAL", 
 400                  0x4  : "SFI_CLASS_MANAGED_NONFOCAL", 
 401                  0x5  : "SFI_CLASS_DEFAULT_FOCAL", 
 402                  0x6  : "SFI_CLASS_DEFAULT_NONFOCAL", 
 403                  0x7  : "SFI_CLASS_KERNEL", 
 404                  0x8  : "SFI_CLASS_OPTED_OUT", 
 405                  0x9  : "SFI_CLASS_UTILITY", 
 406                  0xA  : "SFI_CLASS_LEGACY_FOCAL", 
 407                  0xB  : "SFI_CLASS_LEGACY_NONFOCAL", 
 408                  0xC  : "SFI_CLASS_USER_INITIATED_FOCAL", 
 409                  0xD  : "SFI_CLASS_USER_INITIATED_NONFOCAL", 
 410                  0xE  : "SFI_CLASS_USER_INTERACTIVE_FOCAL", 
 411                  0xF  : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL", 
 412                  0x10 : "SFI_CLASS_MAINTENANCE", 
 415     field_name 
= 'task_coalition' 
 416     for task 
in IterateLinkageChain(queue
, 'task *', field_name
, coal_type 
* sizeof('queue_chain_t')): 
 417         task_str 
= "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task
),task
,GetProcNameForTask(task
),GetTaskRoleString(task
.effective_policy
.tep_role
)) 
 419             for thread 
in IterateQueue(task
.threads
, "thread_t", "task_threads"): 
 420                 task_str 
+= "\n\t\t\t|-> thread:" + hex(thread
) + ", " + sfi_strs
[int(thread
.sfi_class
)] 
 421         tasks
.append(task_str
) 
 424 def GetCoalitionTypeString(type): 
 425     """ Convert a coalition type field into a string 
 426     Currently supported types (from <mach/coalition.h>): 
 427         COALITION_TYPE_RESOURCE 
 428         COALITION_TYPE_JETSAM 
 430     if type == 0: # COALITION_TYPE_RESOURCE 
 436 def GetResourceCoalitionSummary(coal
, verbose
=False): 
 437     """ Summarize a resource coalition 
 439     out_string 
= "Resource Coalition:\n\t  Ledger:\n" 
 440     thread_details 
= False 
 441     if config
['verbosity'] > vSCRIPT
: 
 442         thread_details 
= True 
 443     ledgerp 
= coal
.r
.ledger
 
 444     if verbose 
and unsigned(ledgerp
) != 0: 
 446         while i 
!= ledgerp
.l_template
.lt_cnt
: 
 448             out_string 
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, ledgerp
.l_entries
[i
], i
) 
 450     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
) 
 451     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
) 
 452     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
) 
 453     out_string 
+= "\n\t  cpu_ptime {0: <d}".format(coal
.r
.cpu_ptime
) 
 454     out_string 
+= "\n\t  Tasks:\n\t\t" 
 455     tasks 
= GetCoalitionTasks(addressof(coal
.r
.tasks
), 0, thread_details
) 
 456     out_string 
+= "\n\t\t".join(tasks
) 
 459 def GetJetsamCoalitionSummary(coal
, verbose
=False): 
 460     out_string 
= "Jetsam Coalition:" 
 461     thread_details 
= False 
 462     if config
['verbosity'] > vSCRIPT
: 
 463         thread_details 
= True 
 464     if unsigned(coal
.j
.leader
) == 0: 
 465         out_string 
+= "\n\t  NO Leader!" 
 467         out_string 
+= "\n\t  Leader:\n\t\t" 
 468         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
)) 
 469     out_string 
+= "\n\t  Extensions:\n\t\t" 
 470     tasks 
= GetCoalitionTasks(addressof(coal
.j
.extensions
), 1, thread_details
) 
 471     out_string 
+= "\n\t\t".join(tasks
) 
 472     out_string 
+= "\n\t  XPC Services:\n\t\t" 
 473     tasks 
= GetCoalitionTasks(addressof(coal
.j
.services
), 1, thread_details
) 
 474     out_string 
+= "\n\t\t".join(tasks
) 
 475     out_string 
+= "\n\t  Other Tasks:\n\t\t" 
 476     tasks 
= GetCoalitionTasks(addressof(coal
.j
.other
), 1, thread_details
) 
 477     out_string 
+= "\n\t\t".join(tasks
) 
 478     out_string 
+= "\n\t  Thread Group: {0: <#020x}\n".format(coal
.j
.thread_group
) 
 481 @lldb_type_summary(['coalition_t', 'coalition *']) 
 482 @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")) 
 483 def GetCoalitionSummary(coal
): 
 484     if unsigned(coal
) == 0: 
 485         return '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'.format(0, "", -1, -1, -1, -1, -1, "") 
 487     format_string 
= '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}' 
 488     type_string 
= GetCoalitionTypeString(coal
.type) 
 489     flag_string 
= GetCoalitionFlagString(coal
) 
 490     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
) 
 493 def GetCoalitionInfo(coal
, verbose
=False): 
 494     """ returns a string describing a coalition, including details about the particular coalition type. 
 496             coal : value object representing a coalition in the kernel 
 498             str : A string describing the coalition. 
 500     if unsigned(coal
) == 0: 
 501         return "<null coalition>" 
 502     typestr 
= GetCoalitionTypeString(coal
.type) 
 503     flagstr 
= GetCoalitionFlagString(coal
) 
 505     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
) 
 506     if coal
.type == 0: # COALITION_TYPE_RESOURCE 
 507         out_string 
+= GetResourceCoalitionSummary(coal
, verbose
) 
 508     elif coal
.type == 1: # COALITION_TYPE_JETSAM 
 509         out_string 
+= GetJetsamCoalitionSummary(coal
, verbose
) 
 511         out_string 
+= "Unknown Type" 
 515 # Macro: showcoalitioninfo 
 517 @lldb_command('showcoalitioninfo') 
 518 def ShowCoalitionInfo(cmd_args
=None, cmd_options
={}): 
 519     """  Display more detailed information about a coalition 
 520          Usage: showcoalitioninfo <address of coalition> 
 523     if config
['verbosity'] > vHUMAN
: 
 526         raise ArgumentError("No arguments passed") 
 527     coal 
= kern
.GetValueFromAddress(cmd_args
[0], 'coalition *') 
 529         print "unknown arguments:", str(cmd_args
) 
 531     print GetCoalitionInfo(coal
, verbose
) 
 533 # EndMacro: showcoalitioninfo 
 535 # Macro: showallcoalitions 
 537 @lldb_command('showallcoalitions') 
 538 def ShowAllCoalitions(cmd_args
=None): 
 539     """  Print a summary listing of all the coalitions 
 542     print GetCoalitionSummary
.header
 
 543     for c 
in kern
.coalitions
: 
 544         print GetCoalitionSummary(c
) 
 546 # EndMacro: showallcoalitions 
 548 # Macro: showallthreadgroups 
 550 @lldb_type_summary(['thread_group_t', 'thread_group *']) 
 551 @header("{0: <20s} {1: <5s} {2: <16s} {3: <5s} {4: <8s} {5: <20s}".format("thread_group", "id", "name", "refc", "flags", "recommendation")) 
 552 def GetThreadGroupSummary(tg
): 
 553     if unsigned(tg
) == 0: 
 554         return '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'.format(0, -1, "", -1, "", -1) 
 556     format_string 
= '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}' 
 558     if (tg
.tg_flags 
& 0x1): 
 560     if (tg
.tg_flags 
& 0x2): 
 562     out_string 
+= format_string
.format(tg
, tg
.tg_id
, tg
.tg_name
, tg
.tg_refcount
, tg_flags
, tg
.tg_recommendation
) 
 565 @lldb_command('showallthreadgroups') 
 566 def ShowAllThreadGroups(cmd_args
=None): 
 567     """  Print a summary listing of all thread groups 
 570     print GetThreadGroupSummary
.header
 
 571     for tg 
in kern
.thread_groups
: 
 572         print GetThreadGroupSummary(tg
) 
 574 # EndMacro: showallthreadgroups 
 576 # Macro: showtaskcoalitions 
 578 @lldb_command('showtaskcoalitions', 'F:') 
 579 def ShowTaskCoalitions(cmd_args
=None, cmd_options
={}): 
 583     if "-F" in cmd_options
: 
 584         task_list 
= FindTasksByName(cmd_options
["-F"]) 
 586         t 
= kern
.GetValueFromAddress(cmd_args
[0], 'task *') 
 589         raise ArgumentError("No arguments passed") 
 591     if len(task_list
) > 0: 
 592         print GetCoalitionSummary
.header
 
 593     for task 
in task_list
: 
 594         print GetCoalitionSummary(task
.coalition
[0]) 
 595         print GetCoalitionSummary(task
.coalition
[1]) 
 597 # EndMacro: showtaskcoalitions 
 599 @lldb_type_summary(['proc', 'proc *']) 
 600 @header("{0: >6s} {1: ^20s} {2: >14s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command")) 
 601 def GetProcSummary(proc
): 
 602     """ Summarize the process data.  
 604           proc : value - value representaitng a proc * in kernel 
 606           str - string summary of the process. 
 609     format_string
= "{0: >6d} {1: >#020x} {2: >14s} {3: >2d} {4: >2d} {5: >2d}    {6: <20s}" 
 610     pval 
= proc
.GetSBValue() 
 611     #code.interact(local=locals()) 
 612     if str(pval
.GetType()) != str(gettype('proc *')) : 
 613         return "Unknown type " + str(pval
.GetType()) + " " + str(hex(proc
)) 
 615         out_string 
+= "Process " + hex(proc
) + " is not valid." 
 617     pid 
= int(proc
.p_pid
) 
 618     proc_addr 
= int(hex(proc
), 16) 
 620     if int(proc
.p_lflag
) & 0x400000 : 
 621         proc_rage_str 
= "RAGE" 
 623     task 
= Cast(proc
.task
, 'task *') 
 627     if int(task
.effective_policy
.tep_darwinbg
) != 0: 
 629     if int(task
.effective_policy
.tep_lowpri_cpu
) != 0: 
 632     if int(task
.effective_policy
.tep_io_tier
) != 0: 
 634     if int(task
.effective_policy
.tep_io_passive
) != 0: 
 636     if int(task
.effective_policy
.tep_terminated
) != 0: 
 639     if int(task
.effective_policy
.tep_latency_qos
) != 0: 
 641     if int(task
.effective_policy
.tep_sup_active
) != 0: 
 646         work_queue 
= Cast(proc
.p_wqptr
, 'workqueue *') 
 647         if proc
.p_wqptr 
!= 0 : 
 648             wq_num_threads 
= int(work_queue
.wq_nthreads
) 
 649             wq_idle_threads 
= int(work_queue
.wq_thidlecount
) 
 650             wq_req_threads 
= int(work_queue
.wq_reqcount
) 
 659     process_name 
= str(proc
.p_comm
) 
 660     if process_name 
== 'xpcproxy': 
 661         for thread 
in IterateQueue(task
.threads
, 'thread *', 'task_threads'): 
 662             thread_name 
= GetThreadName(thread
) 
 664                 process_name 
+= ' (' + thread_name 
+ ')' 
 666     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
) 
 669 @lldb_type_summary(['tty_dev_t', 'tty_dev_t *']) 
 670 @header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","master", "slave", "open", "free", "name", "revoke")) 
 671 def GetTTYDevSummary(tty_dev
): 
 672     """ Summarizes the important fields in tty_dev_t structure. 
 673         params: tty_dev: value - value object representing a tty_dev_t in kernel 
 674         returns: str - summary of the tty_dev 
 677     format_string 
= "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"  
 678     open_fn 
= kern
.Symbolicate(int(hex(tty_dev
.open), 16)) 
 679     free_fn 
= kern
.Symbolicate(int(hex(tty_dev
.free
), 16)) 
 680     name_fn 
= kern
.Symbolicate(int(hex(tty_dev
.name
), 16)) 
 681     revoke_fn 
= kern
.Symbolicate(int(hex(tty_dev
.revoke
), 16)) 
 682     out_string 
+= format_string
.format(tty_dev
, tty_dev
.master
, tty_dev
.slave
, open_fn
, free_fn
, name_fn
, revoke_fn
) 
 687 @lldb_command('showtask', 'F:')  
 688 def ShowTask(cmd_args
=None, cmd_options
={}): 
 689     """  Routine to print a summary listing of given task 
 690          Usage: showtask <address of task> 
 691          or   : showtask -F <name of task>   
 694     if "-F" in cmd_options
: 
 695         task_list 
= FindTasksByName(cmd_options
['-F']) 
 698             raise ArgumentError("Invalid arguments passed.") 
 700         tval 
= kern
.GetValueFromAddress(cmd_args
[0], 'task *') 
 702             raise ("Unknown arguments: %r" % cmd_args
) 
 703         task_list
.append(tval
) 
 705     for tval 
in task_list
: 
 706         print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
 707         pval 
= Cast(tval
.bsd_info
, 'proc *') 
 708         print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
) 
 714 @lldb_command('showpid')  
 715 def ShowPid(cmd_args
=None): 
 716     """  Routine to print a summary listing of task corresponding to given pid 
 717          Usage: showpid <pid value> 
 720         raise ArgumentError("No arguments passed") 
 721     pidval 
= ArgumentStringToInt(cmd_args
[0]) 
 723         pval 
= Cast(t
.bsd_info
, 'proc *') 
 724         if pval 
and pval
.p_pid 
== pidval
: 
 725             print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
 726             print GetTaskSummary(t
) + " " + GetProcSummary(pval
) 
 733 @lldb_command('showproc')  
 734 def ShowProc(cmd_args
=None): 
 735     """  Routine to print a summary listing of task corresponding to given proc 
 736          Usage: showproc <address of proc> 
 739         raise ArgumentError("No arguments passed") 
 740     pval 
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *') 
 742         print "unknown arguments:", str(cmd_args
) 
 744     print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
 745     tval 
= Cast(pval
.task
, 'task *') 
 746     print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
) 
 750 # Macro: showprocinfo 
 752 @lldb_command('showprocinfo')  
 753 def ShowProcInfo(cmd_args
=None): 
 754     """  Routine to display name, pid, parent & task for the given proc address 
 755          It also shows the Cred, Flags and state of the process 
 756          Usage: showprocinfo <address of proc> 
 759         raise ArgumentError("No arguments passed") 
 760     pval 
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *') 
 762         print "unknown arguments:", str(cmd_args
) 
 764     print GetProcInfo(pval
) 
 766 # EndMacro: showprocinfo 
 768 #Macro: showprocfiles 
 770 @lldb_command('showprocfiles') 
 771 def ShowProcFiles(cmd_args
=None): 
 772     """ Given a proc_t pointer, display the list of open file descriptors for the referenced process. 
 773         Usage: showprocfiles <proc_t> 
 776         print ShowProcFiles
.__doc
__ 
 778     proc 
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t') 
 779     proc_filedesc 
= proc
.p_fd
 
 780     proc_lastfile 
= unsigned(proc_filedesc
.fd_lastfile
) 
 781     proc_ofiles 
= proc_filedesc
.fd_ofiles
 
 782     if unsigned(proc_ofiles
) == 0: 
 783         print 'No open files for proc {0: <s}'.format(cmd_args
[0]) 
 785     print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO') 
 786     print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("") 
 789     while count 
<= proc_lastfile
: 
 790         if unsigned(proc_ofiles
[count
]) != 0: 
 792             proc_fd_flags 
= proc_ofiles
[count
].f_flags
 
 793             proc_fd_fglob 
= proc_ofiles
[count
].f_fglob
 
 794             out_str 
+= "{0: <5d} ".format(count
) 
 795             out_str 
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
)) 
 796             out_str 
+= "0x{0:0>8x} ".format(unsigned(proc_fd_flags
)) 
 797             proc_fd_ftype 
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
) 
 798             if proc_fd_ftype 
in xnudefines
.filetype_strings
: 
 799                 out_str 
+= "{0: <8s} ".format(xnudefines
.filetype_strings
[proc_fd_ftype
]) 
 801                 out_str 
+= "?: {0: <5d} ".format(proc_fd_ftype
) 
 802             out_str 
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
.fg_data
)) 
 803             if proc_fd_ftype 
== 1: 
 804                 fd_name 
= Cast(proc_fd_fglob
.fg_data
, 'struct vnode *').v_name
 
 805                 out_str 
+= "{0: <64s}".format(fd_name
) 
 810 #EndMacro: showprocfiles 
 814 @lldb_command('showtty') 
 815 def ShowTTY(cmd_args
=None): 
 816     """ Display information about a struct tty 
 817         Usage: showtty <tty struct> 
 820         print ShowTTY
.__doc
__ 
 823     tty 
= kern
.GetValueFromAddress(cmd_args
[0], 'struct tty *') 
 824     print "TTY structure at:              {0: <s}".format(cmd_args
[0]) 
 825     print "Last input to raw queue:       {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_rawq
.c_cs
), tty
.t_rawq
.c_cs
) 
 826     print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_canq
.c_cs
), tty
.t_canq
.c_cs
) 
 827     print "Last output data:              {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_outq
.c_cs
), tty
.t_outq
.c_cs
) 
 829                   ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'], 
 830                   ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'], 
 831                   ['', 'TS_BUSY (Draining output)'], 
 832                   ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'], 
 833                   ['', 'TS_FLUSH (Outq has been flushed during DMA)'], 
 834                   ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'], 
 835                   ['', 'TS_TBLOCK (Further input blocked)'], 
 836                   ['', 'TS_TIMEOUT (Wait for output char processing)'], 
 837                   ['', 'TS_TTSTOP (Output paused)'], 
 838                   ['', 'TS_WOPEN (Open in progress)'], 
 839                   ['', 'TS_XCLUDE (Tty requires exclusivity)'], 
 840                   ['', 'TS_BKSL (State for lowercase \\ work)'], 
 841                   ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'], 
 842                   ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'], 
 843                   ['', 'TS_LNCH (Next character is literal)'], 
 844                   ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'], 
 845                   ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'], 
 846                   ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'], 
 847                   ['', 'TS_SNOOP (Device is being snooped on)'], 
 848                   ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'], 
 849                   ['', 'TS_ZOMBIE (Connection lost)'], 
 850                   ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'], 
 851                   ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'], 
 852                   ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)'] 
 856     tty_state 
= unsigned(tty
.t_state
) 
 859         if tty_state 
& mask 
!= 0: 
 860             if len(tty_state_info
[index
][1]) > 0: 
 861                 print '\t' + tty_state_info
[index
][1] 
 863             if len(tty_state_info
[index
][0]) > 0: 
 864                 print '\t' + tty_state_info
[index
][0] 
 867     print "Flags:                    0x{0:0>8x}".format(unsigned(tty
.t_flags
)) 
 868     print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty
.t_pgrp
)) 
 869     print "Enclosing session:        0x{0:0>16x}".format(unsigned(tty
.t_session
)) 
 871     print "\tInput Flags:   0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_iflag
)) 
 872     print "\tOutput Flags:  0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_oflag
)) 
 873     print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_cflag
)) 
 874     print "\tLocal Flags:   0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_lflag
)) 
 875     print "\tInput Speed:   {0: <8d}".format(tty
.t_termios
.c_ispeed
) 
 876     print "\tOutput Speed:  {0: <8d}".format(tty
.t_termios
.c_ospeed
) 
 877     print "High Watermark: {0: <d} bytes".format(tty
.t_hiwat
) 
 878     print "Low Watermark : {0: <d} bytes".format(tty
.t_lowat
) 
 882 #Macro showallttydevs 
 884 @lldb_command('showallttydevs') 
 885 def ShowAllTTYDevs(cmd_args
=[], cmd_options
={}): 
 886     """ Show a list of ttydevs registered in the system. 
 890     tty_dev_head 
= kern
.globals.tty_dev_head
 
 891     tty_dev 
= tty_dev_head
 
 892     print GetTTYDevSummary
.header
 
 893     while unsigned(tty_dev
) != 0: 
 894         print GetTTYDevSummary(tty_dev
) 
 895         tty_dev 
= tty_dev
.next
 
 898 #EndMacro: showallttydevs 
 900 #Macro: dumpthread_terminate_queue 
 902 @lldb_command('dumpthread_terminate_queue') 
 903 def DumpThreadTerminateQueue(cmd_args
=None): 
 904     """ Displays the contents of the specified call_entry queue. 
 905         Usage: dumpthread_terminate_queue  
 909     print GetThreadSummary
.header
 
 910     for th 
in IterateQueue(addressof(kern
.globals.thread_terminate_queue
), 'struct thread *',  'q_link'): 
 911         print GetThreadSummary(th
) 
 913     print "{0: <d} entries!".format(count
) 
 915 #EndMacro: dumpthread_terminate_queue 
 917 #Macro: dumpcrashed_thread_queue 
 919 @lldb_command('dumpcrashed_thread_queue') 
 920 def DumpCrashedThreadsQueue(cmd_args
=None): 
 921     """ Displays the contents of the specified call_entry queue. 
 922         Usage: dumpcrashed_thread_queue  
 926     print GetThreadSummary
.header
 
 927     for th 
in IterateQueue(addressof(kern
.globals.crashed_threads_queue
), 'struct thread *',  'q_link'): 
 928         print GetThreadSummary(th
) 
 930     print "{0: <d} entries!".format(count
) 
 932 #EndMacro: dumpcrashed_thread_queue 
 934 #Macro: dumpcallqueue 
 936 @lldb_command('dumpcallqueue') 
 937 def DumpCallQueue(cmd_args
=None): 
 938     """ Displays the contents of the specified call_entry queue. 
 939         Usage: dumpcallqueue <queue_head_t *> 
 942         raise ArgumentError("Invalid arguments") 
 944     print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC') 
 945     callhead 
= kern
.GetValueFromAddress(cmd_args
[0], 'queue_head_t *') 
 947     for callentry 
in IterateQueue(callhead
, 'struct call_entry *',  'q_link'): 
 948         print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format( 
 949               unsigned(callentry
), unsigned(callentry
.param0
), unsigned(callentry
.param1
),  
 950               unsigned(callentry
.deadline
), unsigned(callentry
.func
)) 
 952     print "{0: <d} entries!".format(count
) 
 954 #EndMacro: dumpcallqueue 
 956 @lldb_command('showalltasklogicalwrites') 
 957 def ShowAllTaskIOStats(cmd_args
=None): 
 958     """ Commad to print I/O stats for all tasks 
 960     print "{0: <20s} {1: <20s} {2: <20s} {3: <20s} {4: <20s} {5: <20s}".format("task", "Immediate Writes", "Deferred Writes", "Invalidated Writes", "Metadata Writes", "name") 
 962         pval 
= Cast(t
.bsd_info
, 'proc *') 
 963         print "{0: <#18x} {1: >20d} {2: >20d} {3: >20d} {4: >20d} {5: <20s}".format(t
, 
 964             t
.task_immediate_writes
,  
 965             t
.task_deferred_writes
, 
 966             t
.task_invalidated_writes
, 
 967             t
.task_metadata_writes
, 
 971 @lldb_command('showalltasks','C') 
 972 def ShowAllTasks(cmd_args
=None, cmd_options
={}): 
 973     """  Routine to print a summary listing of all the tasks 
 974          wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items" 
 975          if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung 
 976          io_policy -> RAGE  - rapid aging of vnodes requested 
 977                      NORM  - normal I/O explicitly requested (this is the default) 
 978                      PASS  - passive I/O requested (i.e. I/Os do not affect throttling decisions) 
 979                      THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes) 
 980          Usage: (lldb) showalltasks -C  : describe the corpse structure 
 985     if '-C' in cmd_options
: 
 987         extra_hdr 
+= " " + GetKCDataSummary
.header
 
 989     print GetTaskSummary
.header 
+ extra_hdr 
+ " " + GetProcSummary
.header
 
 991         pval 
= Cast(t
.bsd_info
, 'proc *') 
 992         out_str 
= GetTaskSummary(t
, showcorpse
) + " " + GetProcSummary(pval
) 
 996 @lldb_command('taskforpmap') 
 997 def TaskForPmap(cmd_args
=None): 
 998     """ Find the task whose pmap corresponds to <pmap>. 
 999         Syntax: (lldb) taskforpmap <pmap> 
1000             Multiple -v's can be specified for increased verbosity 
1002     if cmd_args 
== None or len(cmd_args
) < 1: 
1003         raise ArgumentError("Too few arguments to taskforpmap.") 
1004     pmap 
= kern
.GetValueFromAddress(cmd_args
[0], 'pmap_t') 
1005     print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
1006     for tasklist 
in [kern
.tasks
, kern
.terminated_tasks
]: 
1008             if t
.map.pmap 
== pmap
: 
1009                 pval 
= Cast(t
.bsd_info
, 'proc *') 
1010                 out_str 
= GetTaskSummary(t
) + " " + GetProcSummary(pval
) 
1013 @lldb_command('showterminatedtasks')  
1014 def ShowTerminatedTasks(cmd_args
=None): 
1015     """  Routine to print a summary listing of all the terminated tasks 
1016          wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items" 
1017          if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung 
1018          io_policy -> RAGE  - rapid aging of vnodes requested 
1019                      NORM  - normal I/O explicitly requested (this is the default) 
1020                      PASS  - passive I/O requested (i.e. I/Os do not affect throttling decisions) 
1021                      THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes) 
1022         syntax: (lldb)showallterminatedtasks 
1025     print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
1026     for t 
in kern
.terminated_tasks
: 
1027         pval 
= Cast(t
.bsd_info
, 'proc *') 
1028         print GetTaskSummary(t
) +" "+ GetProcSummary(pval
) 
1031 # Macro: showtaskstacks 
1033 def ShowTaskStacks(task
): 
1034     """ Print a task with summary and stack information for each of its threads  
1037     print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
1038     pval 
= Cast(task
.bsd_info
, 'proc *') 
1039     print GetTaskSummary(task
) + " " + GetProcSummary(pval
) 
1040     for th 
in IterateQueue(task
.threads
, 'thread *', 'task_threads'): 
1041         print "  " + GetThreadSummary
.header
 
1042         print "  " + GetThreadSummary(th
) 
1043         print GetThreadBackTrace(th
, prefix
="    ") + "\n" 
1045 def FindTasksByName(searchstr
, ignore_case
=True): 
1046     """ Search the list of tasks by name.  
1048             searchstr: str - a regex like string to search for task 
1049             ignore_case: bool - If False then exact matching will be enforced 
1051             [] - array of task object. Empty if not found any 
1055         re_options 
= re
.IGNORECASE
 
1056     search_regex 
= re
.compile(searchstr
, re_options
) 
1058     for t 
in kern
.tasks
:  
1059         pval 
= Cast(t
.bsd_info
, "proc *") 
1060         process_name 
= "{:s}".format(pval
.p_comm
) 
1061         if search_regex
.search(process_name
): 
1065 @lldb_command('showtaskstacks', 'F:') 
1066 def ShowTaskStacksCmdHelper(cmd_args
=None, cmd_options
={}): 
1067     """ Routine to print out the stack for each thread in a task 
1068         Usage: showtaskstacks <0xaddress of task> 
1069            or: showtaskstacks -F launchd    
1072     if "-F" in cmd_options
: 
1073         find_task_str 
= cmd_options
["-F"] 
1074         task_list 
= FindTasksByName(find_task_str
) 
1075         for tval 
in task_list
: 
1076             ShowTaskStacks(tval
) 
1080         raise ArgumentError("No arguments passed") 
1082     tval 
= kern
.GetValueFromAddress(cmd_args
[0], 'task *') 
1084         raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
))) 
1086         ShowTaskStacks(tval
) 
1089 # EndMacro: showtaskstacks 
1091 def CheckTaskProcRefs(task
, proc
): 
1092     for thread 
in IterateQueue(task
.threads
, 'thread *', 'task_threads'): 
1093         if int(thread
.uthread
) == 0: 
1095         uthread 
= Cast(thread
.uthread
, 'uthread *') 
1096         refcount 
= int(uthread
.uu_proc_refcount
) 
1097         uu_ref_index 
= int(uthread
.uu_pindex
) 
1100         for ref 
in range(0, uu_ref_index
): 
1101             if unsigned(uthread
.uu_proc_ps
[ref
]) == unsigned(proc
): 
1102                 print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
1103                 pval 
= Cast(task
.bsd_info
, 'proc *') 
1104                 print GetTaskSummary(task
) + " " + GetProcSummary(pval
) 
1105                 print "\t" + GetThreadSummary
.header
 
1106                 print "\t" + GetThreadSummary(thread
) + "\n" 
1108                 for frame 
in range (0, 10): 
1109                     trace_addr 
= unsigned(uthread
.uu_proc_pcs
[ref
][frame
]) 
1110                     symbol_arr 
= kern
.SymbolicateFromAddress(unsigned(trace_addr
)) 
1112                         symbol_str 
= str(symbol_arr
[0].addr
) 
1115                     print '{0: <#x} {1: <s}'.format(trace_addr
, symbol_str
) 
1118 @lldb_command('showprocrefs') 
1119 def ShowProcRefs(cmd_args 
= None): 
1120     """ Display information on threads/BTs that could be holding a reference on the specified proc 
1121         NOTE: We can't say affirmatively if any of these references are still held since 
1122               there's no way to pair references with drop-refs in the current infrastructure. 
1123         Usage: showprocrefs <proc> 
1125     if cmd_args 
== None or len(cmd_args
) < 1: 
1126          raise ArgumentError("No arguments passed") 
1128     proc 
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *') 
1130     for t 
in kern
.tasks
: 
1131         CheckTaskProcRefs(t
, proc
) 
1132     for t 
in kern
.terminated_tasks
: 
1133         CheckTaskProcRefs(t
, proc
) 
1137 @lldb_command('showallthreads') 
1138 def ShowAllThreads(cmd_args 
= None): 
1139     """ Display info about all threads in the system 
1141     for t 
in kern
.tasks
: 
1142         ShowTaskThreads([str(int(t
))]) 
1145     for t 
in kern
.terminated_tasks
: 
1146         print "Terminated: \n" 
1147         ShowTaskThreads([str(int(t
))]) 
1152 @lldb_command('showtaskthreads', "F:") 
1153 def ShowTaskThreads(cmd_args 
= None, cmd_options
={}): 
1154     """ Display thread information for a given task 
1155         Usage: showtaskthreads <0xaddress of task> 
1156            or: showtaskthreads -F <name> 
1159     if "-F" in cmd_options
: 
1160         task_list 
= FindTasksByName(cmd_options
["-F"]) 
1162         t 
= kern
.GetValueFromAddress(cmd_args
[0], 'task *') 
1165         raise ArgumentError("No arguments passed") 
1167     for task 
in task_list
: 
1168         print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
1169         pval 
= Cast(task
.bsd_info
, 'proc *') 
1170         print GetTaskSummary(task
) + " " + GetProcSummary(pval
) 
1171         print "\t" + GetThreadSummary
.header
 
1172         for thval 
in IterateQueue(task
.threads
, 'thread *', 'task_threads'): 
1173             print "\t" + GetThreadSummary(thval
) 
1176 @lldb_command('showact') 
1177 def ShowAct(cmd_args
=None): 
1178     """ Routine to print out the state of a specific thread. 
1179         usage: showact <activation>  
1182         raise ArgumentError("No arguments passed") 
1183     threadval 
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *') 
1184     print GetThreadSummary
.header
 
1185     print GetThreadSummary(threadval
) 
1187 @lldb_command('showactstack') 
1188 def ShowActStack(cmd_args
=None): 
1189     """ Routine to print out the stack of a specific thread. 
1190         usage:  showactstack <activation>  
1193         raise ArgumentError("No arguments passed") 
1194     threadval 
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *') 
1195     print GetThreadSummary
.header
 
1196     print GetThreadSummary(threadval
) 
1197     print GetThreadBackTrace(threadval
, prefix
="\t") 
1200 @lldb_command('switchtoact') 
1201 def SwitchToAct(cmd_args
=None): 
1202     """ Switch to different context specified by activation 
1203     This command allows gdb to examine the execution context and call 
1204     stack for the specified activation. For example, to view the backtrace 
1205     for an activation issue "switchtoact <address>", followed by "bt". 
1206     Before resuming execution, issue a "resetctx" command, to 
1207     return to the original execution context. 
1209     if cmd_args 
is None or len(cmd_args
) < 1: 
1210         raise ArgumentError("No arguments passed") 
1211     thval 
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *') 
1212     lldbthread 
= GetLLDBThreadForKernelThread(thval
) 
1213     print GetThreadSummary
.header
 
1214     print GetThreadSummary(thval
) 
1215     LazyTarget
.GetProcess().selected_thread 
= lldbthread
 
1216     if not LazyTarget
.GetProcess().SetSelectedThread(lldbthread
): 
1217         print "Failed to switch thread." 
1220 @lldb_command('switchtoregs') 
1221 def SwitchToRegs(cmd_args
=None): 
1222     """ Routine to switch to a register state. 
1223         Usage: (lldb) switchtoregs <struct arm_saved_state[64] *> 
1224         This command creates a fake thread in lldb with the saved register state. 
1225         Note: This command ONLY works for ARM based kernel setup. 
1228     if cmd_args 
== None or len(cmd_args
) < 1: 
1229         raise ArgumentError("No arguments passed") 
1231     lldb_process 
= LazyTarget
.GetProcess() 
1233     saved_state 
= ArgumentStringToInt(cmd_args
[0]) 
1234     # any change to this logic requires change in operating_system.py as well 
1235     fake_thread_id 
= 0xdead0000 | 
(saved_state 
& ~
0xffff0000) 
1236     fake_thread_id 
= fake_thread_id 
& 0xdeadffff 
1237     lldb_process
.CreateOSPluginThread(0xdeadbeef, saved_state
) 
1238     lldbthread 
= lldb_process
.GetThreadByID(int(fake_thread_id
)) 
1240     if not lldbthread
.IsValid(): 
1241         print "Failed to create thread" 
1244     lldb_process
.selected_thread 
= lldbthread
 
1245     if not lldb_process
.SetSelectedThread(lldbthread
): 
1246         print "Failed to switch thread" 
1247     print "Switched to Fake thread created from register state at 0x%x" % saved_state
 
1251 # Macro: showallstacks 
1252 @lldb_command('showallstacks') 
1253 def ShowAllStacks(cmd_args
=None): 
1254     """Routine to print out the stack for each thread in the system. 
1256     for t 
in kern
.tasks
: 
1262 # EndMacro: showallstacks 
1264 # Macro: showcurrentstacks 
1265 @lldb_command('showcurrentstacks') 
1266 def ShowCurrentStacks(cmd_args
=None): 
1267     """ Routine to print out the thread running on each cpu (incl. its stack) 
1269     processor_list 
= kern
.GetGlobalVariable('processor_list') 
1270     current_processor 
= processor_list
 
1271     while unsigned(current_processor
) > 0: 
1272         print "\n" + GetProcessorSummary(current_processor
) 
1273         active_thread 
= current_processor
.active_thread
 
1274         if unsigned(active_thread
) != 0 : 
1275             task_val 
= active_thread
.task
 
1276             proc_val 
= Cast(task_val
.bsd_info
, 'proc *') 
1277             print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
1278             print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
) 
1279             print "\t" + GetThreadSummary
.header
 
1280             print "\t" + GetThreadSummary(active_thread
) 
1281             print "\tBacktrace:" 
1282             print GetThreadBackTrace(active_thread
, prefix
="\t") 
1283         current_processor 
= current_processor
.processor_list
 
1285 # EndMacro: showcurrentstacks 
1287 @lldb_command('showcurrentthreads') 
1288 def ShowCurrentThreads(cmd_args
=None): 
1289     """ Display info about threads running on each cpu """ 
1290     processor_list 
= kern
.GetGlobalVariable('processor_list') 
1291     current_processor 
= processor_list
 
1292     while unsigned(current_processor
) > 0: 
1293         print GetProcessorSummary(current_processor
) 
1294         active_thread 
= current_processor
.active_thread
 
1295         if unsigned(active_thread
) != 0 : 
1296             task_val 
= active_thread
.task
 
1297             proc_val 
= Cast(task_val
.bsd_info
, 'proc *') 
1298             print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
1299             print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
) 
1300             print "\t" + GetThreadSummary
.header
 
1301             print "\t" + GetThreadSummary(active_thread
) 
1302         current_processor 
= current_processor
.processor_list
 
1305 def GetFullBackTrace(frame_addr
, verbosity 
= vHUMAN
, prefix 
= ""): 
1306     """ Get backtrace across interrupt context.  
1307         params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7) 
1308                 prefix - str - prefix for each line of output. 
1313     frame_ptr 
= frame_addr
 
1314     previous_frame_ptr 
= 0 
1315     # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header 
1316     mh_execute_addr 
= int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16) 
1317     while frame_ptr 
and frame_ptr 
!= previous_frame_ptr 
and bt_count 
< 128: 
1318         if (not kern
.arch
.startswith('arm') and frame_ptr 
< mh_execute_addr
) or (kern
.arch
.startswith('arm') and frame_ptr 
> mh_execute_addr
): 
1320         pc_val 
= kern
.GetValueFromAddress(frame_ptr 
+ kern
.ptrsize
,'uintptr_t *') 
1321         pc_val 
= unsigned(dereference(pc_val
)) 
1322         out_string 
+= prefix 
+ GetSourceInformationForAddress(pc_val
) + "\n" 
1324         previous_frame_ptr 
= frame_ptr
 
1325         frame_val 
= kern
.GetValueFromAddress((frame_ptr
), 'uintptr_t *') 
1326         if unsigned(frame_val
) == 0: 
1328         frame_ptr 
= unsigned(dereference(frame_val
)) 
1332 @lldb_command('fullbt') 
1333 def FullBackTrace(cmd_args
=[]): 
1334     """ Show full backtrace across the interrupt boundary. 
1335         Syntax: fullbt <frame ptr> 
1336         Example: fullbt  `$rbp`  
1338     if len(cmd_args
) < 1: 
1339         print FullBackTrace
.__doc
__ 
1341     print GetFullBackTrace(ArgumentStringToInt(cmd_args
[0]), prefix
="\t") 
1343 @lldb_command('fullbtall') 
1344 def FullBackTraceAll(cmd_args
=[]): 
1345     """ Show full backtrace across the interrupt boundary for threads running on all processors. 
1349     for processor 
in IterateLinkedList(kern
.globals.processor_list
, 'processor_list') : 
1350         print "\n" + GetProcessorSummary(processor
) 
1351         active_thread 
= processor
.active_thread
 
1352         if unsigned(active_thread
) != 0 : 
1353             task_val 
= active_thread
.task
 
1354             proc_val 
= Cast(task_val
.bsd_info
, 'proc *') 
1355             print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
1356             print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
) 
1357             print "\t" + GetThreadSummary
.header
 
1358             print "\t" + GetThreadSummary(active_thread
) 
1359             print "\tBacktrace:" 
1361             ThreadVal 
= GetLLDBThreadForKernelThread(active_thread
) 
1363             FramePtr 
= ThreadVal
.frames
[0].GetFP() 
1365             print GetFullBackTrace(unsigned(FramePtr
), prefix
="\t") 
1368 @lldb_command('symbolicate') 
1369 def SymbolicateAddress(cmd_args
=[]): 
1370     """ Symbolicate an address for symbol information from loaded symbols 
1371         Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr" 
1373     if len(cmd_args
) < 1: 
1374         print "Invalid address.\nSyntax: symbolicate <address>" 
1376     print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args
[0])) 
1379 @lldb_command('showinitchild') 
1380 def ShowInitChild(cmd_args
=None): 
1381     """ Routine to print out all processes in the system 
1382         which are children of init process 
1384     headp 
= kern
.globals.initproc
.p_children
 
1385     for pp 
in IterateListEntry(headp
, 'struct proc *', 'p_sibling'): 
1386         print GetProcInfo(pp
) 
1389 @lldb_command('showproctree') 
1390 def ShowProcTree(cmd_args
=None): 
1391     """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes. 
1392         If no argument is given, showproctree will print all the processes in the system. 
1393         If pid is specified, showproctree prints all the descendants of the indicated process 
1397         search_pid 
= ArgumentStringToInt(cmd_args
[0]) 
1400         print "pid specified must be a positive number" 
1401         print ShowProcTree
.__doc
__ 
1404     hdr_format 
= "{0: <6s} {1: <14s} {2: <9s}\n" 
1405     out_string 
= hdr_format
.format("PID", "PROCESS", "POINTER") 
1406     out_string 
+= hdr_format
.format('='*3, '='*7, '='*7) 
1407     proc 
= GetProcForPid(search_pid
) 
1408     out_string 
+= "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc
.p_ppid
, proc
.p_pptr
.p_comm
, unsigned(proc
.p_pptr
)) 
1409     out_string 
+= "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc
.p_pid
, proc
.p_comm
, unsigned(proc
)) 
1411     ShowProcTreeRecurse(proc
, "|  ") 
1415 def ShowProcTreeRecurse(proc
, prefix
=""): 
1416     """ Prints descendants of a given proc in hierarchial tree form 
1418             proc  : core.value representing a struct proc * in the kernel 
1420             str   : String containing info about a given proc and its descendants in tree form 
1422     if proc
.p_childrencnt 
> 0: 
1423         head_ptr 
= proc
.p_children
.lh_first
 
1425         for p 
in IterateListEntry(proc
.p_children
, 'struct proc *', 'p_sibling'): 
1426             print prefix 
+ "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p
.p_pid
, p
.p_comm
, unsigned(p
)) 
1427             ShowProcTreeRecurse(p
, prefix 
+ "|  ") 
1429 @lldb_command('showthreadfortid') 
1430 def ShowThreadForTid(cmd_args
=None): 
1431     """ The thread structure contains a unique thread_id value for each thread. 
1432         This command is used to retrieve the address of the thread structure(thread_t) 
1433         corresponding to a given thread_id. 
1436         print "Please provide thread_t whose tid you'd like to look up" 
1437         print ShowThreadForTid
.__doc
__ 
1439     search_tid 
= ArgumentStringToInt(cmd_args
[0]) 
1440     for taskp 
in kern
.tasks
: 
1441         for actp 
in IterateQueue(taskp
.threads
, 'struct thread *', 'task_threads'): 
1442             if search_tid 
== int(actp
.thread_id
): 
1443                 print "Found {0: #019x}".format(actp
) 
1444                 print GetThreadSummary
.header
 
1445                 print GetThreadSummary(actp
) 
1447     print "Not a valid thread_id" 
1449 def GetProcessorSummary(processor
): 
1450     """ Internal function to print summary of processor 
1451         params: processor - value representing struct processor *  
1452         return: str - representing the details of given processor 
1455     processor_state_str 
= "INVALID"  
1456     processor_state 
= int(processor
.state
) 
1458     processor_states 
= { 
1462                 # 3 (formerly INACTIVE) 
1468     if processor_state 
in processor_states
: 
1469         processor_state_str 
= "{0: <11s} ".format(processor_states
[processor_state
]) 
1471     processor_recommended_str 
= "" 
1472     if int(processor
.is_recommended
) == 0: 
1473         processor_recommended_str 
= " (not recommended)" 
1476     preemption_disable 
= 0 
1477     preemption_disable_str 
= "" 
1479     if kern
.arch 
== 'x86_64': 
1480         cpu_data 
= kern
.globals.cpu_data_ptr
[processor
.cpu_id
] 
1481         if (cpu_data 
!= 0) : 
1482             ast 
= cpu_data
.cpu_pending_ast
 
1483             preemption_disable 
= cpu_data
.cpu_preemption_level
 
1484     # On arm64, it's kern.globals.CpuDataEntries[processor.cpu_id].cpu_data_vaddr 
1485     # but LLDB can't find CpuDataEntries... 
1487     ast_str 
= GetASTSummary(ast
) 
1489     if (preemption_disable 
!= 0) : 
1490         preemption_disable_str 
= "Preemption Disabled" 
1492     out_str 
= "Processor {: <#018x} cpu_id {:>#4x} AST: {:<6s} State {:<s}{:<s} {:<s}\n".format( 
1493             processor
, int(processor
.cpu_id
), ast_str
, processor_state_str
, processor_recommended_str
, 
1494             preemption_disable_str
) 
1497 def GetLedgerEntrySummary(ledger_template
, ledger
, i
): 
1498     """ Internal function to get internals of a ledger entry (*not* a ledger itself) 
1499         params: ledger_template - value representing struct ledger_template_t for the task or thread 
1500                 ledger - value representing struct ledger_entry * 
1501         return: str - formatted output information of ledger entries 
1503     ledger_limit_infinity 
= (uint64_t(0x1).value 
<< 63) - 1 
1504     lf_refill_scheduled 
= 0x0400 
1505     lf_tracking_max 
= 0x4000 
1508     now 
= unsigned(kern
.globals.sched_tick
) / 20 
1511     out_str 
+= "{: >32s} {:<2d}:".format(ledger_template
.lt_entries
[i
].et_key
, i
) 
1512     out_str 
+= "{: >15d} ".format(unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
)) 
1513     if (ledger
.le_flags 
& lf_tracking_max
): 
1514         out_str 
+= "{:9d} {:5d} ".format(ledger
._le
.le_maxtracking
.le_peaks
[0].le_max
, now 
- unsigned(ledger
._le
.le_maxtracking
.le_peaks
[0].le_time
)) 
1518     if (ledger
.le_flags 
& lf_tracking_max
): 
1519         out_str 
+= "{:12d} ".format(ledger
._le
.le_maxtracking
.le_lifetime_max
) 
1522     out_str 
+= "{:12d} {:12d} ".format(unsigned(ledger
.le_credit
), unsigned(ledger
.le_debit
)) 
1523     if (unsigned(ledger
.le_limit
) != ledger_limit_infinity
): 
1524         out_str 
+= "{:12d} ".format(unsigned(ledger
.le_limit
)) 
1528     if (ledger
.le_flags 
& lf_refill_scheduled
): 
1529         out_str 
+= "{:15d} ".format(ledger
._le
.le_refill
.le_refill_period
) 
1533     if (ledger
.le_flags 
& lf_refill_scheduled
): 
1534         out_str 
+= "{:9d} ".format((unsigned(ledger
.le_limit
) * 100) / ledger
._le
.le_refill
.le_refill_period
) 
1538     if (unsigned(ledger
.le_warn_level
) != ledger_limit_infinity
): 
1539         out_str 
+= "{:9d} ".format((unsigned(ledger
.le_warn_level
) * 100) / unsigned(ledger
.le_limit
)) 
1543     if ((unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
)) > unsigned(ledger
.le_limit
)): 
1548     out_str 
+= "{:#8x}\n".format(ledger
.le_flags
) 
1551 def GetThreadLedgerSummary(thread_val
): 
1552     """ Internal function to get a summary of ledger entries for the given thread 
1553         params: thread - value representing struct thread * 
1554         return: str - formatted output information for ledger entries of the input thread 
1556     out_str 
= "   [{:#08x}]\n".format(thread_val
) 
1557     ledgerp 
= thread_val
.t_threadledger
 
1560         while i 
!= ledgerp
.l_template
.lt_cnt
: 
1561             out_str 
+= GetLedgerEntrySummary(kern
.globals.thread_ledger_template
, 
1562                 ledgerp
.l_entries
[i
], i
) 
1566 @header("{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >9s} {5: >6s} {6: >12s} {7: >11s} \ 
1567     {8: >7s} {9: >13s}   {10: <15s} {11: <8s} {12: <9s} {13: <6s} {14: >6s}".format( 
1568     "task [thread]", "entry", "#", "balance", "peakA", "(age)", "lifemax", "credit", 
1569      "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")) 
1570 def GetTaskLedgers(task_val
): 
1571     """ Internal function to get summary of ledger entries from the task and its threads 
1572         params: task_val - value representing struct task * 
1573         return: str - formatted output information for ledger entries of the input task 
1576     task_ledgerp 
= task_val
.ledger
 
1578     out_str 
+= "{: #08x} ".format(task_val
) 
1579     pval 
= Cast(task_val
.bsd_info
, 'proc *') 
1581         out_str 
+= "{: <5s}:\n".format(pval
.p_comm
) 
1583         out_str 
+= "Invalid process:\n" 
1584     while i 
!= task_ledgerp
.l_template
.lt_cnt
: 
1585         out_str 
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, task_ledgerp
.l_entries
[i
], i
) 
1589     for thval 
in IterateQueue(task_val
.threads
, 'thread *', 'task_threads'): 
1590         out_str 
+= GetThreadLedgerSummary(thval
) 
1594 # Macro: showtaskledgers 
1596 @lldb_command('showtaskledgers', 'F:')  
1597 def ShowTaskLedgers(cmd_args
=None, cmd_options
={}): 
1598     """  Routine to print a summary  of ledger entries for the task and all of its threads 
1599          Usage: showtaskledgers <address of task> 
1600          or   : showtaskledgers -F <name of task> 
1602     if "-F" in cmd_options
: 
1603         task_list 
= FindTasksByName(cmd_options
["-F"]) 
1604         for tval 
in task_list
: 
1605             print GetTaskLedgers
.header
 
1606             print GetTaskLedgers(tval
) 
1610         raise ArgumentError("No arguments passed.") 
1611     tval 
= kern
.GetValueFromAddress(cmd_args
[0], 'task *') 
1613         raise ArgumentError("unknown arguments: %r" %cmd
_args
) 
1614     print GetTaskLedgers
.header
 
1615     print GetTaskLedgers(tval
) 
1617 # EndMacro: showtaskledgers 
1619 # Macro: showalltaskledgers 
1621 @lldb_command('showalltaskledgers')  
1622 def ShowAllTaskLedgers(cmd_args
=None): 
1623     """  Routine to print a summary  of ledger entries for all tasks and respective threads 
1624          Usage: showalltaskledgers 
1626     for t 
in kern
.tasks
: 
1627         task_val 
= unsigned(t
) 
1628         ShowTaskLedgers([task_val
]) 
1630 # EndMacro: showalltaskledgers 
1632 # Macro: showprocuuidpolicytable 
1634 @lldb_type_summary(['proc_uuid_policy_entry']) 
1635 @header("{0: <36s} {1: <10s}".format("uuid", "flags")) 
1636 def GetProcUUIDPolicyEntrySummary(entry
): 
1637     """ Summarizes the important fields in proc_uuid_policy_entry structure. 
1638         params: entry: value - value object representing an entry 
1639         returns: str - summary of the entry 
1643         data
.append(int(entry
.uuid
[i
])) 
1644     flags 
= unsigned(entry
.flags
) 
1645     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
) 
1648 @lldb_command('showprocuuidpolicytable') 
1649 def ShowProcUUIDPolicyTable(cmd_args
=None): 
1650     """ Routine to print the proc UUID policy table 
1651         Usage: showprocuuidpolicytable 
1653     hashslots 
= unsigned(kern
.globals.proc_uuid_policy_hash_mask
) 
1654     print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary
.header
 
1655     for i 
in range(0, hashslots
+1): 
1656         headp 
= addressof(kern
.globals.proc_uuid_policy_hashtbl
[i
]) 
1658         for entry 
in IterateListEntry(headp
, 'struct proc_uuid_policy_entry *', 'entries'): 
1659             print "{0: >2d}.{1: <5d} ".format(i
, entrynum
) + GetProcUUIDPolicyEntrySummary(entry
) 
1663 # EndMacro: showprocuuidpolicytable 
1665 @lldb_command('showalltaskpolicy')  
1666 def ShowAllTaskPolicy(cmd_args
=None): 
1668          Routine to print a summary listing of all the tasks 
1669          wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items" 
1670          if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung 
1671          io_policy -> RAGE  - rapid aging of vnodes requested 
1672                      NORM  - normal I/O explicitly requested (this is the default) 
1673                      PASS  - passive I/O requested (i.e. I/Os do not affect throttling decisions) 
1674                      THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes) 
1677     print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
1678     for t 
in kern
.tasks
: 
1679         pval 
= Cast(t
.bsd_info
, 'proc *') 
1680         print GetTaskSummary(t
) +" "+ GetProcSummary(pval
) 
1681         requested_strings 
= [ 
1682                 ["int_darwinbg",        "DBG-int"], 
1683                 ["ext_darwinbg",        "DBG-ext"], 
1684                 ["int_iotier",          "iotier-int"], 
1685                 ["ext_iotier",          "iotier-ext"], 
1686                 ["int_iopassive",       "passive-int"], 
1687                 ["ext_iopassive",       "passive-ext"], 
1688                 ["bg_iotier",           "bg-iotier"], 
1689                 ["terminated",          "terminated"], 
1690                 ["th_pidbind_bg",       "bg-pidbind"], 
1691                 ["t_apptype",           "apptype"], 
1692                 ["t_boosted",           "boosted"], 
1694                 ["t_tal_enabled",       "tal-enabled"], 
1695                 ["t_base_latency_qos",  "latency-base"], 
1696                 ["t_over_latency_qos",  "latency-override"], 
1697                 ["t_base_through_qos",  "throughput-base"], 
1698                 ["t_over_through_qos",  "throughput-override"] 
1702         for value 
in requested_strings
: 
1703             if t
.requested_policy
.__getattr
__(value
[0]) : 
1704                 requested
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " " 
1708         suppression_strings 
= [ 
1709                 ["t_sup_active",        "active"], 
1710                 ["t_sup_lowpri_cpu",    "lowpri-cpu"], 
1711                 ["t_sup_timer",         "timer-throttling"], 
1712                 ["t_sup_disk",          "disk-throttling"], 
1713                 ["t_sup_cpu_limit",     "cpu-limits"], 
1714                 ["t_sup_suspend",       "suspend"], 
1715                 ["t_sup_bg_sockets",    "bg-sockets"] 
1719         for value 
in suppression_strings
: 
1720             if t
.requested_policy
.__getattr
__(value
[0]) : 
1721                 suppression
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " " 
1725         effective_strings 
= [ 
1726                 ["darwinbg",        "background"], 
1727                 ["lowpri_cpu",      "lowpri-cpu"], 
1728                 ["io_tier",         "iotier"], 
1729                 ["io_passive",      "passive"], 
1730                 ["all_sockets_bg",  "bg-allsockets"], 
1731                 ["new_sockets_bg",  "bg-newsockets"], 
1732                 ["bg_iotier",       "bg-iotier"], 
1733                 ["terminated",      "terminated"], 
1734                 ["t_gpu_deny",      "gpu-deny"], 
1735                 ["t_tal_engaged",   "tal-engaged"], 
1736                 ["t_suspended",     "suspended"], 
1737                 ["t_watchers_bg",   "bg-watchers"], 
1738                 ["t_latency_qos",   "latency-qos"], 
1739                 ["t_through_qos",   "throughput-qos"], 
1740                 ["t_sup_active",    "suppression-active"], 
1745         for value 
in effective_strings
: 
1746             if t
.effective_policy
.__getattr
__(value
[0]) : 
1747                 effective
+=value
[1] + ": " + str(t
.effective_policy
.__getattr
__(value
[0])) + " " 
1751         print "requested: " + requested
 
1752         print "suppression: " + suppression
 
1753         print "effective: " + effective
 
1756 @lldb_type_summary(['wait_queue', 'wait_queue_t']) 
1757 @header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask")) 
1758 def GetWaitQSummary(waitq
): 
1759     """ Summarizes the important fields in task structure. 
1760         params: task: value - value object representing a task in kernel 
1761         returns: str - summary of the task 
1764     format_string 
= '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}' 
1768     if (waitq
.wq_fifo 
== 1) : 
1773     if (waitq
.wq_prepost 
== 1) : 
1776     if (waitq
.wq_type 
== 0x3) : 
1778     elif (waitq
.wq_type 
== 0x2) : 
1783     out_string 
+= format_string
.format(waitq
, unsigned(waitq
.wq_interlock
.lock_data
), policy
, 0, 0, unsigned(waitq
.wq_eventmask
)) 
1785     out_string 
+= "\n" + GetThreadSummary
.header
 
1787     for thread 
in IterateQueue(waitq
.wq_queue
, "thread_t", "links"): 
1788         out_string 
+= "\n" + GetThreadSummary(thread
) 
1793 @lldb_command('showallsuspendedtasks', '') 
1794 def ShowSuspendedTasks(cmd_args
=[], options
={}): 
1795     """ Show a list of suspended tasks with their process name summary. 
1797     print GetTaskSummary
.header 
+ ' ' + GetProcSummary
.header
 
1798     for t 
in kern
.tasks
: 
1799         if t
.suspend_count 
> 0: 
1800             print GetTaskSummary(t
) + ' ' + GetProcSummary(Cast(t
.bsd_info
, 'proc *')) 
1804 @lldb_command('showallpte') 
1805 def ShowAllPte(cmd_args
=None): 
1806     """ Prints out the physical address of the pte for all tasks 
1808     head_taskp 
= addressof(kern
.globals.tasks
) 
1809     taskp 
= Cast(head_taskp
.next
, 'task *') 
1810     while taskp 
!= head_taskp
: 
1811         procp 
= Cast(taskp
.bsd_info
, 'proc *') 
1812         out_str 
= "task = {:#x} pte = {:#x}\t".format(taskp
, taskp
.map.pmap
.ttep
) 
1814             out_str 
+= "{:s}\n".format(procp
.p_comm
) 
1818         taskp 
= Cast(taskp
.tasks
.next
, 'struct task *') 
1820 # EndMacro: showallpte 
1822 # Macro: showallrefcounts 
1823 @lldb_command('showallrefcounts') 
1824 @header("{0: <20s} {1: ^10s}".format("task", "ref_count")) 
1825 def ShowAllRefCounts(cmd_args
=None): 
1826     """ Prints the ref_count of all tasks 
1829     head_taskp 
= addressof(kern
.globals.tasks
) 
1830     taskp 
= Cast(head_taskp
.next
, 'task *') 
1831     print ShowAllRefCounts
.header
 
1832     while taskp 
!= head_taskp
: 
1833         out_str 
+= "{: <#20x}".format(taskp
) 
1834         out_str 
+= "{: ^10d}\n".format(taskp
.ref_count
) 
1835         taskp 
= Cast(taskp
.tasks
.next
, 'task *') 
1837 # EndMacro: showallrefcounts 
1839 # Macro: showallrunnablethreads 
1840 @lldb_command('showallrunnablethreads') 
1841 def ShowAllRunnableThreads(cmd_args
=None): 
1842     """ Prints the sched usage information for all threads of each task 
1845     for taskp 
in kern
.tasks
: 
1846         for actp 
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'): 
1847             if int(actp
.state 
& 0x4): 
1848                 ShowActStack([unsigned(actp
)]) 
1850 # EndMacro: showallrunnablethreads 
1852 # Macro: showallschedusage 
1853 @lldb_command('showallschedusage') 
1854 @header("{0:<20s} {1:^10s} {2:^10s} {3:^15s}".format("Thread", "Priority", "State", "sched_usage")) 
1855 def ShowAllSchedUsage(cmd_args
=None): 
1856     """ Prints the sched usage information for all threads of each task 
1859     for taskp 
in kern
.tasks
: 
1860         ShowTask([unsigned(taskp
)]) 
1861         print ShowAllSchedUsage
.header
 
1862         for actp 
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'): 
1863             out_str 
= "{: <#20x}".format(actp
) 
1864             out_str 
+= "{: ^10s}".format(str(int(actp
.sched_pri
))) 
1865             state 
= int(actp
.state
) 
1866             thread_state_chars 
= {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'}
 
1868             state_str 
+= thread_state_chars
[int(state 
& 0x1)] 
1869             state_str 
+= thread_state_chars
[int(state 
& 0x2)] 
1870             state_str 
+= thread_state_chars
[int(state 
& 0x4)] 
1871             state_str 
+= thread_state_chars
[int(state 
& 0x8)] 
1872             state_str 
+= thread_state_chars
[int(state 
& 0x10)] 
1873             state_str 
+= thread_state_chars
[int(state 
& 0x20)] 
1874             state_str 
+= thread_state_chars
[int(state 
& 0x40)] 
1875             state_str 
+= thread_state_chars
[int(state 
& 0x80)] 
1876             out_str 
+= "{: ^10s}".format(state_str
) 
1877             out_str 
+= "{: >15d}".format(actp
.sched_usage
) 
1878             print out_str 
+ "\n" 
1881 # EndMacro: showallschedusage 
1883 #Macro: showprocfilessummary 
1884 @lldb_command('showprocfilessummary') 
1885 @header("{0: <20s} {1: <20s} {2: >10s}".format("Process", "Name", "Number of Open Files")) 
1886 def ShowProcFilesSummary(cmd_args
=None): 
1887     """ Display the summary of open file descriptors for all processes in task list 
1888         Usage: showprocfilessummary 
1890     print ShowProcFilesSummary
.header
 
1891     for proc 
in kern
.procs
: 
1892         proc_filedesc 
= proc
.p_fd
 
1893         proc_ofiles 
= proc_filedesc
.fd_ofiles
 
1894         proc_lastfile 
= unsigned(proc_filedesc
.fd_lastfile
) 
1897         if proc_filedesc
.fd_nfiles 
!= 0: 
1898             while count 
<= proc_lastfile
: 
1899                 if unsigned(proc_ofiles
[count
]) != 0: 
1900                     proc_file_count 
+= 1 
1902         print "{0: <#020x} {1: <20s} {2: >10d}".format(proc
, proc
.p_comm
, proc_file_count
) 
1904 #EndMacro: showprocfilessummary 
1906 @lldb_command('workinguserstacks') 
1907 def WorkingUserStacks(cmd_args
=None): 
1908     """ Print out the user stack for each thread in a task, followed by the user libraries. 
1909         Syntax: (lldb) workinguserstacks <task_t> 
1912         print "Insufficient arguments" + ShowTaskUserStacks
.__doc
__ 
1914     task 
= kern
.GetValueFromAddress(cmd_args
[0], 'task *') 
1915     print GetTaskSummary
.header 
+ " " + GetProcSummary
.header
 
1916     pval 
= Cast(task
.bsd_info
, 'proc *') 
1917     print GetTaskSummary(task
) + " " + GetProcSummary(pval
) + "\n \n" 
1918     for thval 
in IterateQueue(task
.threads
, 'thread *', 'task_threads'): 
1919         print "For thread 0x{0:x}".format(thval
) 
1921             ShowThreadUserStack([hex(thval
)]) 
1922         except Exception as exc_err
: 
1923             print "Failed to show user stack for thread 0x{0:x}".format(thval
) 
1927                 print "Enable debugging ('(lldb) xnudebug debug') to see detailed trace." 
1928     WorkingUserLibraries([hex(task
)]) 
1931 @static_var("exec_load_path", 0) 
1932 @lldb_command("workingkuserlibraries") 
1933 def WorkingUserLibraries(cmd_args
=None): 
1934     """ Show binary images known by dyld in target task 
1935         For a given user task, inspect the dyld shared library state and print information about all Mach-O images. 
1936         Syntax: (lldb)workinguserlibraries <task_t> 
1939         print "Insufficient arguments" 
1940         print ShowTaskUserLibraries
.__doc
__ 
1943     print "{0: <18s} {1: <12s} {2: <36s} {3: <50s}".format('address','type','uuid','path') 
1944     out_format 
= "0x{0:0>16x} {1: <12s} {2: <36s} {3: <50s}" 
1945     task 
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t') 
1946     is_task_64 
= int(task
.t_flags
) & 0x1 
1947     dyld_all_image_infos_address 
= unsigned(task
.all_image_info_addr
) 
1949     if dyld_all_image_infos_address 
== 0: 
1950         print "No dyld shared library information available for task" 
1952     vers_info_data 
= GetUserDataAsString(task
, dyld_all_image_infos_address
, 112) 
1953     version 
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t") 
1954     cur_data_offset 
+= 4 
1956         print "Unknown dyld all_image_infos version number %d" % version
 
1957     image_info_count 
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t") 
1958     WorkingUserLibraries
.exec_load_path 
= 0 
1960         image_info_size 
= 24 
1961         image_info_array_address 
= _ExtractDataFromString(vers_info_data
, 8, "uint64_t") 
1962         dyld_load_address 
= _ExtractDataFromString(vers_info_data
, 8*4, "uint64_t") 
1963         dyld_all_image_infos_address_from_struct 
= _ExtractDataFromString(vers_info_data
, 8*13, "uint64_t") 
1965         image_info_size 
= 12 
1966         image_info_array_address 
= _ExtractDataFromString(vers_info_data
, 4*2, "uint32_t") 
1967         dyld_load_address 
= _ExtractDataFromString(vers_info_data
, 4*5, "uint32_t") 
1968         dyld_all_image_infos_address_from_struct 
= _ExtractDataFromString(vers_info_data
, 4*14, "uint32_t") 
1969     # Account for ASLR slide before dyld can fix the structure 
1970     dyld_load_address 
= dyld_load_address 
+ (dyld_all_image_infos_address 
- dyld_all_image_infos_address_from_struct
) 
1973     while i 
< image_info_count
: 
1974         image_info_address 
= image_info_array_address 
+ i 
* image_info_size
 
1975         img_data 
= GetUserDataAsString(task
, image_info_address
, image_info_size
) 
1977             image_info_addr 
= _ExtractDataFromString(img_data
, 0, "uint64_t") 
1978             image_info_path 
= _ExtractDataFromString(img_data
, 8, "uint64_t") 
1980             image_info_addr 
= _ExtractDataFromString(img_data
, 0, "uint32_t") 
1981             image_info_path 
= _ExtractDataFromString(img_data
, 4, "uint32_t") 
1982         PrintImageInfo(task
, image_info_addr
, image_info_path
) 
1985     # load_path might get set when the main executable is processed. 
1986     if WorkingUserLibraries
.exec_load_path 
!= 0: 
1987         PrintImageInfo(task
, dyld_load_address
, WorkingUserLibraries
.exec_load_path
) 
1990 # Macro: showstackaftertask 
1991 @lldb_command('showstackaftertask','F:') 
1992 def Showstackaftertask(cmd_args
=None,cmd_options
={}): 
1993     """ Routine to print the thread stacks for all tasks succeeding a given task 
1994         Usage: showstackaftertask <0xaddress of task> 
1995            or: showstackaftertask  -F <taskname> 
1997     if "-F" in cmd_options
: 
1998         # Find the task pointer corresponding to its task name 
1999         find_task_str 
= cmd_options
["-F"] 
2000         task_list 
= FindTasksByName(find_task_str
) 
2002         # Iterate through the list of tasks and print all task stacks thereafter 
2003         for tval 
in task_list
: 
2004             ListTaskStacks(tval
) 
2008         raise ArgumentError("Insufficient arguments") 
2009     tval 
= kern
.GetValueFromAddress(cmd_args
[0], 'task *') 
2011         raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
))) 
2013         ListTaskStacks(tval
) 
2017 # EndMacro: showstackaftertask 
2019 def ListTaskStacks(task
): 
2020     """ Search for a given task and print the list of all task stacks thereafter. 
2022     # Initialize local variable task_flag to mark when a given task is found. 
2025     for t 
in kern
.tasks
: 
2026         if (task_flag 
== 1): 
2032 # Macro: showstackafterthread 
2033 @lldb_command('showstackafterthread') 
2034 def Showstackafterthread(cmd_args 
= None): 
2035     """ Routine to print the stacks of all threads succeeding a given thread. 
2036         Usage: Showstackafterthread <0xaddress of thread> 
2038     # local variable thread_flag is used to mark when a given thread is found. 
2041        threadval 
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *') 
2043         raise ArgumentError("No arguments passed") 
2044     # Iterate through list of all tasks to look up a given thread 
2045     for t 
in kern
.tasks
: 
2047             pval 
= Cast(t
.bsd_info
, 'proc *') 
2048             print GetTaskSummary
.header 
+ " "+ GetProcSummary
.header
 
2049             print GetTaskSummary(t
) +     " "+ GetProcSummary(pval
) 
2051          # Look up for a given thread from the the list of threads of a given task 
2052         for thval 
in IterateQueue(t
.threads
, 'thread *', 'task_threads'): 
2053             if (thread_flag
==1): 
2055                print "  " + GetThreadSummary
.header
 
2056                print "  " + GetThreadSummary(thval
) 
2057                print GetThreadBackTrace(thval
, prefix
="\t")+"\n" 
2060             if(thval
==threadval
): 
2061                pval 
= Cast(t
.bsd_info
, 'proc *') 
2062                process_name 
= "{:s}".format(pval
.p_comm
) 
2064                print " *** Continuing to dump the thread stacks from the process *** :" + " " + process_name