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 *
12 def GetProcNameForTask(task
):
13 """ returns a string name of the process. if proc is not valid "unknown" is returned
15 task: value object represeting a task in the kernel.
17 str : A string name of the process linked to the task
19 if not task
or not unsigned(task
.bsd_info
):
21 p
= Cast(task
.bsd_info
, 'proc *')
24 def GetProcPIDForTask(task
):
25 """ returns a int pid of the process. if the proc is not valid, val[5] from audit_token is returned.
27 task: value object representing a task in the kernel
29 int : pid of the process or -1 if not found
31 if task
and unsigned(task
.bsd_info
):
32 p
= Cast(task
.bsd_info
, 'proc *')
33 return unsigned(p
.p_pid
)
36 return unsigned(task
.audit_token
.val
[5])
40 def GetProcInfo(proc
):
41 """ returns a string name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields.
43 proc : value object representing a proc in the kernel
45 str : A string describing various information for process.
48 out_string
+= ("Process {p: <#020x}\n\tname {p.p_comm: <20s}\n\tpid:{p.p_pid: <6d} " +
49 "task:{p.task: <#020x} p_stat:{p.p_stat: <6d} parent pid: {p.p_ppid: <6d}\n"
54 out_string
+= "Cred: euid {:d} ruid {:d} svuid {:d}\n".format(ucred
.cr_posix
.cr_uid
,
55 ucred
.cr_posix
.cr_ruid
,
56 ucred
.cr_posix
.cr_svuid
)
58 flags
= int(proc
.p_flag
)
59 out_string
+= "Flags: {0: <#020x}\n".format(flags
)
64 out_string
+= "\t" + xnudefines
.proc_flag_explain_strings
[i
] + "\n"
65 elif num
== 0x4: #special case for 32bit flag
66 out_string
+= "\t" + xnudefines
.proc_flag_explain_strings
[0] + "\n"
69 out_string
+= "State: "
70 state_val
= proc
.p_stat
71 if state_val
< 1 or state_val
> len(xnudefines
.proc_state_strings
) :
72 out_string
+= "(Unknown)"
74 out_string
+= xnudefines
.proc_state_strings
[int(state_val
)]
78 def GetProcNameForPid(pid
):
79 """ Finds the name of the process corresponding to a given pid
81 pid : int, pid you want to find the procname for
83 str : Name of the process corresponding to the pid, "Unknown" if not found
86 if int(p
.p_pid
) == int(pid
):
90 def GetProcForPid(search_pid
):
91 """ Finds the value object representing a proc in the kernel based on its pid
93 search_pid : int, pid whose proc structure you want to find
95 value : The value object representing the proc, if a proc corresponding
96 to the given pid is found. Returns None otherwise
99 return kern
.globals.initproc
101 headp
= kern
.globals.allproc
102 for proc
in IterateListEntry(headp
, 'struct proc *', 'p_list'):
103 if proc
.p_pid
== search_pid
:
107 @lldb_command('allproc')
108 def AllProc(cmd_args
=None):
109 """ Walk through the allproc structure and print procinfo for each process structure.
111 cmd_args - [] : array of strings passed from lldb command prompt
113 for proc
in kern
.procs
:
114 print GetProcInfo(proc
)
117 @lldb_command('zombproc')
118 def ZombProc(cmd_args
=None):
119 """ Routine to print out all procs in the zombie list
121 cmd_args - [] : array of strings passed from lldb command prompt
123 if len(kern
.zombprocs
) != 0:
124 print "\nZombie Processes:"
125 for proc
in kern
.zombprocs
:
126 print GetProcInfo(proc
) + "\n\n"
128 @lldb_command('zombtasks')
129 def ZombTasks(cmd_args
=None):
130 """ Routine to print out all tasks in the zombie list
134 if len(kern
.zombprocs
) != 0:
135 header
= "\nZombie Tasks:\n"
136 header
+= GetTaskSummary
.header
+ " " + GetProcSummary
.header
137 for proc
in kern
.zombprocs
:
139 t
= Cast(proc
.task
, 'task *')
140 out_str
+= GetTaskSummary(t
) +" "+ GetProcSummary(proc
) + "\n"
145 @lldb_command('zombstacks')
146 def ZombStacks(cmd_args
=None):
147 """ Routine to print out all stacks of tasks that are exiting
150 for proc
in kern
.zombprocs
:
153 print "\nZombie Stacks:"
155 t
= Cast(proc
.task
, 'task *')
159 def GetASTSummary(ast
):
160 """ Summarizes an AST field
175 T - AST_TELEMETRY_USER
176 T - AST_TELEMETRY_KERNEL
177 T - AST_TELEMETRY_WINDOWED
182 thread_state_chars
= {0x0:'', 0x1:'P', 0x2:'Q', 0x4:'U', 0x8:'H', 0x10:'Y', 0x20:'A',
183 0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M', 0x400:'C', 0x800:'C',
184 0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S'}
187 while mask
<= 0x10000 :
188 state_str
+= thread_state_chars
[int(state
& mask
)]
194 @lldb_type_summary(['task', 'task_t'])
195 @header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags"))
196 def GetTaskSummary(task
):
197 """ Summarizes the important fields in task structure.
198 params: task: value - value object representing a task in kernel
199 returns: str - summary of the task
202 format_string
= '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}'
203 thread_count
= int(task
.thread_count
)
205 if hasattr(task
, "suppression_generation") and (int(task
.suppression_generation
) & 0x1) == 0x1:
207 if hasattr(task
, "suspend_count") and int(task
.suspend_count
) > 0:
209 if hasattr(task
, 'task_imp_base') and unsigned(task
.task_imp_base
):
210 tib
= task
.task_imp_base
211 if int(tib
.iit_receiver
) == 1:
213 if int(tib
.iit_donor
) == 1:
215 if int(tib
.iit_assertcnt
) > 0:
217 out_string
+= format_string
.format(task
, task
.map, task
.itk_space
, thread_count
, task_flags
)
220 @lldb_type_summary(['thread *', 'thread_t'])
221 @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', 'wait_queue', 'wait_event', 'wmesg', 'thread_name'))
222 def GetThreadSummary(thread
):
223 """ Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct.
224 params: thread: value - value objecte representing a thread in kernel
225 returns: str - summary of a thread
233 A - Terminated and on termination queue
244 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}"
245 thread_ptr_str
= str("{0: <#020x}".format(thread
))
246 if int(thread
.static_param
) :
247 thread_ptr_str
+="[WQ]"
248 thread_id
= hex(thread
.thread_id
)
250 processor
= hex(thread
.last_processor
)
251 base_priority
= str(int(thread
.priority
))
252 sched_priority
= str(int(thread
.sched_pri
))
254 mode
= str(thread
.sched_mode
)
255 if "TIMESHARE" in mode
:
256 sched_mode
+="timeshare"
257 elif "FIXED" in mode
:
259 elif "REALTIME" in mode
:
260 sched_mode
+="realtime"
262 if (unsigned(thread
.bound_processor
) != 0):
266 if (unsigned(thread
.sched_flags
) & 0x0004):
270 if int(thread
.uthread
) != 0:
271 uthread
= Cast(thread
.uthread
, 'uthread *')
272 #check for thread name
273 if int(uthread
.pth_name
) != 0 :
274 th_name_strval
= Cast(uthread
.pth_name
, 'char *')
275 if len(str(th_name_strval
)) > 0 :
276 thread_name
= str(th_name_strval
)
278 #check for io_policy flags
279 if int(uthread
.uu_flag
) & 0x400:
280 io_policy_str
+='RAGE '
282 #now flags for task_policy
286 if int(thread
.effective_policy
.darwinbg
) != 0:
288 if int(thread
.effective_policy
.lowpri_cpu
) != 0:
291 if int(thread
.effective_policy
.io_tier
) != 0:
293 if int(thread
.effective_policy
.io_passive
) != 0:
295 if int(thread
.effective_policy
.terminated
) != 0:
298 state
= int(thread
.state
)
299 thread_state_chars
= {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
303 state_str
+= thread_state_chars
[int(state
& mask
)]
306 ast
= int(thread
.ast
) |
int(thread
.reason
)
307 ast_str
= GetASTSummary(ast
)
309 #wait queue information
313 if ( state
& 0x1 ) != 0:
314 #we need to look at the waitqueue as well
315 wait_queue_str
= str("{0: <#020x}".format(int(hex(thread
.wait_queue
), 16)))
316 wait_event_str
= str("{0: <#020x}".format(int(hex(thread
.wait_event
), 16)))
317 wait_event_str_sym
= kern
.Symbolicate(int(hex(thread
.wait_event
), 16))
318 if len(wait_event_str_sym
) > 0:
319 wait_event_str
= wait_event_str
.strip() + " <" + wait_event_str_sym
+ ">"
320 if int(thread
.uthread
) != 0 :
321 uthread
= Cast(thread
.uthread
, 'uthread *')
322 if int(uthread
.uu_wmesg
) != 0:
323 wait_message
= str(Cast(uthread
.uu_wmesg
, 'char *'))
325 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
)
329 @lldb_type_summary(['coalition_t', 'coalition'])
330 @header("type coalition summary (header tbw)")
331 def GetCoalitionSummary(coal
):
333 format_string
= '{0: <#020x} {1: <d} {2: <d} {3: <d}'
335 if (coal
.terminated
):
336 flags_string
+= ' terminated'
338 flags_string
+= ' reaped'
339 out_string
+= format_string
.format(coal
, coal
.id, coal
.ref_count
, coal
.active_count
, )
342 @lldb_type_summary(['proc', 'proc *'])
343 @header("{0: >6s} {1: ^20s} {2: >14s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command"))
344 def GetProcSummary(proc
):
345 """ Summarize the process data.
347 proc : value - value representaitng a proc * in kernel
349 str - string summary of the process.
352 format_string
= "{0: >6d} {1: >#020x} {2: >14s} {3: >2d} {4: >2d} {5: >2d} {6: <20s}"
353 pval
= proc
.GetSBValue()
354 #code.interact(local=locals())
355 if str(pval
.GetType()) != str(gettype('proc *')) :
356 return "Unknown type " + str(pval
.GetType()) + " " + str(hex(proc
))
358 out_string
+= "Process " + hex(proc
) + " is not valid."
360 pid
= int(proc
.p_pid
)
361 proc_addr
= int(hex(proc
), 16)
363 if int(proc
.p_lflag
) & 0x400000 :
364 proc_rage_str
= "RAGE"
366 task
= Cast(proc
.task
, 'task *')
370 if int(task
.effective_policy
.darwinbg
) != 0:
372 if int(task
.effective_policy
.lowpri_cpu
) != 0:
375 if int(task
.effective_policy
.io_tier
) != 0:
377 if int(task
.effective_policy
.io_passive
) != 0:
379 if int(task
.effective_policy
.terminated
) != 0:
382 if int(task
.effective_policy
.t_suspended
) != 0:
384 if int(task
.effective_policy
.t_latency_qos
) != 0:
386 if int(task
.effective_policy
.t_sup_active
) != 0:
391 work_queue
= Cast(proc
.p_wqptr
, 'workqueue *')
392 if proc
.p_wqptr
!= 0 :
393 wq_num_threads
= int(work_queue
.wq_nthreads
)
394 wq_idle_threads
= int(work_queue
.wq_thidlecount
)
395 wq_req_threads
= int(work_queue
.wq_reqcount
)
404 process_name
= str(proc
.p_comm
)
405 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
)
408 @lldb_type_summary(['tty_dev_t', 'tty_dev_t *'])
409 @header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","master", "slave", "open", "free", "name", "revoke"))
410 def GetTTYDevSummary(tty_dev
):
411 """ Summarizes the important fields in tty_dev_t structure.
412 params: tty_dev: value - value object representing a tty_dev_t in kernel
413 returns: str - summary of the tty_dev
416 format_string
= "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"
417 open_fn
= kern
.Symbolicate(int(hex(tty_dev
.open), 16))
418 free_fn
= kern
.Symbolicate(int(hex(tty_dev
.free
), 16))
419 name_fn
= kern
.Symbolicate(int(hex(tty_dev
.name
), 16))
420 revoke_fn
= kern
.Symbolicate(int(hex(tty_dev
.revoke
), 16))
421 out_string
+= format_string
.format(tty_dev
, tty_dev
.master
, tty_dev
.slave
, open_fn
, free_fn
, name_fn
, revoke_fn
)
424 @lldb_type_summary(['kqueue *'])
425 @header("{: <20s} {: <20s} {: <6s} {: <20s} {: <10s}".format('kqueue', 'process', '#events', 'wqs', 'state'))
426 def GetKQueueSummary(kq
):
427 """ summarizes kqueue information
428 returns: str - summary of kqueue
431 format_string
= "{o: <#020x} {o.kq_p: <#020x} {o.kq_count: <6d} {o.kq_wqs: <#020x} {st_str: <10s}"
432 state
= int(kq
.kq_state
)
436 if int(state
& mask
):
437 state_str
+= ' ' + xnudefines
.kq_state_strings
[int(state
& mask
)]
439 out_string
+= format_string
.format(o
=kq
, st_str
=state_str
)
442 @lldb_type_summary(['knote *'])
443 @header("{0: <20s}".format('knote'))
444 def GetKnoteSummary(kn
):
445 """ Summarizes a knote and related information
446 returns: str - summary of knote
449 format_string
= "{o: <#020x}"
450 out_string
+= format_string
.format(o
=kn
)
455 @lldb_command('showtask', 'F:')
456 def ShowTask(cmd_args
=None, cmd_options
={}):
457 """ Routine to print a summary listing of given task
458 Usage: showtask <address of task>
459 or : showtask -F <name of task>
462 if "-F" in cmd_options
:
463 task_list
= FindTasksByName(cmd_options
['-F'])
466 raise ArgumentError("Invalid arguments passed.")
468 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
470 raise ("Unknown arguments: %r" % cmd_args
)
471 task_list
.append(tval
)
473 for tval
in task_list
:
474 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
475 pval
= Cast(tval
.bsd_info
, 'proc *')
476 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
482 @lldb_command('showpid')
483 def ShowPid(cmd_args
=None):
484 """ Routine to print a summary listing of task corresponding to given pid
485 Usage: showpid <pid value>
488 print "No arguments passed"
489 print ShowPid
.__doc
__
491 pidval
= ArgumentStringToInt(cmd_args
[0])
493 pval
= Cast(t
.bsd_info
, 'proc *')
494 if pval
and pval
.p_pid
== pidval
:
495 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
496 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
503 @lldb_command('showproc')
504 def ShowProc(cmd_args
=None):
505 """ Routine to print a summary listing of task corresponding to given proc
506 Usage: showproc <address of proc>
509 print "No arguments passed"
510 print ShowProc
.__doc
__
512 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
514 print "unknown arguments:", str(cmd_args
)
516 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
517 tval
= Cast(pval
.task
, 'task *')
518 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
522 # Macro: showprocinfo
524 @lldb_command('showprocinfo')
525 def ShowProcInfo(cmd_args
=None):
526 """ Routine to display name, pid, parent & task for the given proc address
527 It also shows the Cred, Flags and state of the process
528 Usage: showprocinfo <address of proc>
531 print "No arguments passed"
532 print ShowProcInfo
.__doc
__
534 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
536 print "unknown arguments:", str(cmd_args
)
538 print GetProcInfo(pval
)
540 # EndMacro: showprocinfo
542 #Macro: showprocfiles
544 @lldb_command('showprocfiles')
545 def ShowProcFiles(cmd_args
=None):
546 """ Given a proc_t pointer, display the list of open file descriptors for the referenced process.
547 Usage: showprocfiles <proc_t>
550 print ShowProcFiles
.__doc
__
552 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t')
553 proc_filedesc
= proc
.p_fd
554 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
555 proc_ofiles
= proc_filedesc
.fd_ofiles
556 if unsigned(proc_ofiles
) == 0:
557 print 'No open files for proc {0: <s}'.format(cmd_args
[0])
559 print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')
560 print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")
574 while count
<= proc_lastfile
:
575 if unsigned(proc_ofiles
[count
]) != 0:
577 proc_fd_flags
= proc_ofiles
[count
].f_flags
578 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
579 out_str
+= "{0: <5d} ".format(count
)
580 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
))
581 out_str
+= "0x{0:0>8x} ".format(unsigned(proc_fd_flags
))
582 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
583 if proc_fd_ftype
in filetype_dict
:
584 out_str
+= "{0: <8s} ".format(filetype_dict
[proc_fd_ftype
])
586 out_str
+= "?: {0: <5d} ".format(proc_fd_ftype
)
587 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
.fg_data
))
588 if proc_fd_ftype
== 1:
589 fd_name
= Cast(proc_fd_fglob
.fg_data
, 'struct vnode *').v_name
590 out_str
+= "{0: <64s}".format(fd_name
)
595 #EndMacro: showprocfiles
598 @lldb_command('showkqueue' ,'')
599 def ShowKQueue(cmd_args
=[], cmd_options
={}):
600 """ Given a struct kqueue pointer, display the summary of the kqueue
601 Usage: (lldb) showkqueue <struct kqueue *>
604 raise ArgumentError('Invalid arguments')
606 kq
= kern
.GetValueFromAddress(cmd_args
[0], 'struct kqueue *')
607 print GetKQueueSummary
.header
608 print GetKQueueSummary(kq
)
610 #EndMacro: showkqueue
614 @lldb_command('showtty')
615 def ShowTTY(cmd_args
=None):
616 """ Display information about a struct tty
617 Usage: showtty <tty struct>
620 print ShowTTY
.__doc
__
623 tty
= kern
.GetValueFromAddress(cmd_args
[0], 'struct tty *')
624 print "TTY structure at: {0: <s}".format(cmd_args
[0])
625 print "Last input to raw queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_rawq
.c_cs
), tty
.t_rawq
.c_cs
)
626 print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_canq
.c_cs
), tty
.t_canq
.c_cs
)
627 print "Last output data: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_outq
.c_cs
), tty
.t_outq
.c_cs
)
629 ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'],
630 ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'],
631 ['', 'TS_BUSY (Draining output)'],
632 ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'],
633 ['', 'TS_FLUSH (Outq has been flushed during DMA)'],
634 ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'],
635 ['', 'TS_TBLOCK (Further input blocked)'],
636 ['', 'TS_TIMEOUT (Wait for output char processing)'],
637 ['', 'TS_TTSTOP (Output paused)'],
638 ['', 'TS_WOPEN (Open in progress)'],
639 ['', 'TS_XCLUDE (Tty requires exclusivity)'],
640 ['', 'TS_BKSL (State for lowercase \\ work)'],
641 ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'],
642 ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'],
643 ['', 'TS_LNCH (Next character is literal)'],
644 ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'],
645 ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'],
646 ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'],
647 ['', 'TS_SNOOP (Device is being snooped on)'],
648 ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'],
649 ['', 'TS_ZOMBIE (Connection lost)'],
650 ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'],
651 ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'],
652 ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)']
656 tty_state
= unsigned(tty
.t_state
)
659 if tty_state
& mask
!= 0:
660 if len(tty_state_info
[index
][1]) > 0:
661 print '\t' + tty_state_info
[index
][1]
663 if len(tty_state_info
[index
][0]) > 0:
664 print '\t' + tty_state_info
[index
][0]
667 print "Flags: 0x{0:0>8x}".format(unsigned(tty
.t_flags
))
668 print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty
.t_pgrp
))
669 print "Enclosing session: 0x{0:0>16x}".format(unsigned(tty
.t_session
))
671 print "\tInput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_iflag
))
672 print "\tOutput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_oflag
))
673 print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_cflag
))
674 print "\tLocal Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_lflag
))
675 print "\tInput Speed: {0: <8d}".format(tty
.t_termios
.c_ispeed
)
676 print "\tOutput Speed: {0: <8d}".format(tty
.t_termios
.c_ospeed
)
677 print "High Watermark: {0: <d} bytes".format(tty
.t_hiwat
)
678 print "Low Watermark : {0: <d} bytes".format(tty
.t_lowat
)
682 #Macro showallttydevs
684 @lldb_command('showallttydevs')
685 def ShowAllTTYDevs(cmd_args
=[], cmd_options
={}):
686 """ Show a list of ttydevs registered in the system.
690 tty_dev_head
= kern
.globals.tty_dev_head
691 tty_dev
= tty_dev_head
692 print GetTTYDevSummary
.header
693 while unsigned(tty_dev
) != 0:
694 print GetTTYDevSummary(tty_dev
)
695 tty_dev
= tty_dev
.next
698 #EndMacro: showallttydevs
700 #Macro: dumpcallqueue
702 @lldb_command('dumpcallqueue')
703 def DumpCallQueue(cmd_args
=None):
704 """ Displays the contents of the specified call_entry queue.
705 Usage: dumpcallqueue <queue_head_t *>
708 print DumpCallQueue
.__doc
__
710 print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
711 callhead
= kern
.GetValueFromAddress(cmd_args
[0], 'queue_head_t *')
713 for callentry
in IterateQueue(callhead
, 'struct call_entry *', 'q_link'):
714 print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format(
715 unsigned(callentry
), unsigned(callentry
.param0
), unsigned(callentry
.param1
),
716 unsigned(callentry
.deadline
), unsigned(callentry
.func
))
718 print "{0: <d} entries!".format(count
)
720 #EndMacro: dumpcallqueue
722 @lldb_command('showallcoalitions')
723 def ShowAllCoalitions(cmd_args
=None):
724 """ Routine to print a summary listing of all the coalitions
727 print GetCoalitionSummary
.header
728 for c
in kern
.coalitions
:
729 print GetCoalitionSummary(c
)
731 @lldb_command('showalltasks')
732 def ShowAllTasks(cmd_args
=None):
733 """ Routine to print a summary listing of all the tasks
734 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
735 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
736 io_policy -> RAGE - rapid aging of vnodes requested
737 NORM - normal I/O explicitly requested (this is the default)
738 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
739 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
742 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
744 pval
= Cast(t
.bsd_info
, 'proc *')
745 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
748 @lldb_command('showterminatedtasks')
749 def ShowTerminatedTasks(cmd_args
=None):
750 """ Routine to print a summary listing of all the terminated tasks
751 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
752 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
753 io_policy -> RAGE - rapid aging of vnodes requested
754 NORM - normal I/O explicitly requested (this is the default)
755 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
756 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
757 syntax: (lldb)showallterminatedtasks
760 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
761 for t
in kern
.terminated_tasks
:
762 pval
= Cast(t
.bsd_info
, 'proc *')
763 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
766 # Macro: showtaskstacks
768 def ShowTaskStacks(task
):
769 """ Print a task with summary and stack information for each of its threads
772 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
773 pval
= Cast(task
.bsd_info
, 'proc *')
774 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
775 for th
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
776 print " " + GetThreadSummary
.header
777 print " " + GetThreadSummary(th
)
778 print GetThreadBackTrace(th
, prefix
=" ") + "\n"
780 def FindTasksByName(searchstr
, ignore_case
=True):
781 """ Search the list of tasks by name.
783 searchstr: str - a regex like string to search for task
784 ignore_case: bool - If False then exact matching will be enforced
786 [] - array of task object. Empty if not found any
790 re_options
= re
.IGNORECASE
791 search_regex
= re
.compile(searchstr
, re_options
)
794 pval
= Cast(t
.bsd_info
, "proc *")
795 process_name
= "{:s}".format(pval
.p_comm
)
796 if search_regex
.search(process_name
):
800 @lldb_command('showtaskstacks', 'F:')
801 def ShowTaskStacksCmdHelper(cmd_args
=None, cmd_options
={}):
802 """ Routine to print out the stack for each thread in a task
803 Usage: showtaskstacks <0xaddress of task>
804 or: showtaskstacks -F launchd
807 if "-F" in cmd_options
:
808 find_task_str
= cmd_options
["-F"]
809 task_list
= FindTasksByName(find_task_str
)
810 for tval
in task_list
:
815 raise ArgumentError("No arguments passed")
817 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
819 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
824 # EndMacro: showtaskstacks
826 @lldb_command('showallthreads')
827 def ShowAllThreads(cmd_args
= None):
828 """ Display info about all threads in the system
831 ShowTaskThreads([str(int(t
))])
834 for t
in kern
.terminated_tasks
:
835 print "Terminated: \n"
836 ShowTaskThreads([str(int(t
))])
841 @lldb_command('showtaskthreads', "F:")
842 def ShowTaskThreads(cmd_args
= None, cmd_options
={}):
843 """ Display thread information for a given task
844 Usage: showtaskthreads <0xaddress of task>
845 or: showtaskthreads -F <name>
848 if "-F" in cmd_options
:
849 task_list
= FindTasksByName(cmd_options
["-F"])
851 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
854 raise ArgumentError("No arguments passed")
856 for task
in task_list
:
857 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
858 pval
= Cast(task
.bsd_info
, 'proc *')
859 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
860 print "\t" + GetThreadSummary
.header
861 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
862 print "\t" + GetThreadSummary(thval
)
865 @lldb_command('showact')
866 def ShowAct(cmd_args
=None):
867 """ Routine to print out the state of a specific thread.
868 usage: showact <activation>
870 if cmd_args
== None or len(cmd_args
) < 1:
871 print "No arguments passed"
872 print ShowAct
.__doc
__
874 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
875 print GetThreadSummary
.header
876 print GetThreadSummary(threadval
)
878 @lldb_command('showactstack')
879 def ShowActStack(cmd_args
=None):
880 """ Routine to print out the stack of a specific thread.
881 usage: showactstack <activation>
883 if cmd_args
== None or len(cmd_args
) < 1:
884 print "No arguments passed"
885 print ShowAct
.__doc
__.strip()
887 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
888 print GetThreadSummary
.header
889 print GetThreadSummary(threadval
)
890 print GetThreadBackTrace(threadval
, prefix
="\t")
893 @lldb_command('switchtoact')
894 def SwitchToAct(cmd_args
=None):
895 """ Switch to different context specified by activation
896 This command allows gdb to examine the execution context and call
897 stack for the specified activation. For example, to view the backtrace
898 for an activation issue "switchtoact <address>", followed by "bt".
899 Before resuming execution, issue a "resetctx" command, to
900 return to the original execution context.
902 if cmd_args
== None or len(cmd_args
) < 1:
903 print "No arguments passed"
904 print SwitchToAct
.__doc
__.strip()
906 thval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
907 lldbthread
= GetLLDBThreadForKernelThread(thval
)
908 print GetThreadSummary
.header
909 print GetThreadSummary(thval
)
910 LazyTarget
.GetProcess().selected_thread
= lldbthread
911 if not LazyTarget
.GetProcess().SetSelectedThread(lldbthread
):
912 print "Failed to switch thread."
914 # Macro: showallstacks
915 @lldb_command('showallstacks')
916 def ShowAllStacks(cmd_args
=None):
917 """Routine to print out the stack for each thread in the system.
925 # EndMacro: showallstacks
927 # Macro: showcurrentstacks
928 @lldb_command('showcurrentstacks')
929 def ShowCurrentStacks(cmd_args
=None):
930 """ Routine to print out the thread running on each cpu (incl. its stack)
932 processor_list
= kern
.GetGlobalVariable('processor_list')
933 current_processor
= processor_list
934 while unsigned(current_processor
) > 0:
935 print "\n" + GetProcessorSummary(current_processor
)
936 active_thread
= current_processor
.active_thread
937 if unsigned(active_thread
) != 0 :
938 task_val
= active_thread
.task
939 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
940 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
941 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
942 print "\t" + GetThreadSummary
.header
943 print "\t" + GetThreadSummary(active_thread
)
945 print GetThreadBackTrace(active_thread
, prefix
="\t")
946 current_processor
= current_processor
.processor_list
948 # EndMacro: showcurrentstacks
950 @lldb_command('showcurrentthreads')
951 def ShowCurrentThreads(cmd_args
=None):
952 """ Display info about threads running on each cpu """
953 processor_list
= kern
.GetGlobalVariable('processor_list')
954 current_processor
= processor_list
955 while unsigned(current_processor
) > 0:
956 print GetProcessorSummary(current_processor
)
957 active_thread
= current_processor
.active_thread
958 if unsigned(active_thread
) != 0 :
959 task_val
= active_thread
.task
960 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
961 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
962 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
963 print "\t" + GetThreadSummary
.header
964 print "\t" + GetThreadSummary(active_thread
)
965 current_processor
= current_processor
.processor_list
968 def GetFullBackTrace(frame_addr
, verbosity
= vHUMAN
, prefix
= ""):
969 """ Get backtrace across interrupt context.
970 params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7)
971 prefix - str - prefix for each line of output.
976 frame_ptr
= frame_addr
977 previous_frame_ptr
= 0
978 # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
979 mh_execute_addr
= int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
980 while frame_ptr
and frame_ptr
!= previous_frame_ptr
and bt_count
< 128:
981 if (kern
.arch
!= 'arm' and frame_ptr
< mh_execute_addr
) or (kern
.arch
== 'arm' and frame_ptr
> mh_execute_addr
):
983 pc_val
= kern
.GetValueFromAddress(frame_ptr
+ kern
.ptrsize
,'uintptr_t *')
984 pc_val
= unsigned(dereference(pc_val
))
985 out_string
+= prefix
+ GetSourceInformationForAddress(pc_val
) + "\n"
987 previous_frame_ptr
= frame_ptr
988 frame_val
= kern
.GetValueFromAddress((frame_ptr
), 'uintptr_t *')
989 if unsigned(frame_val
) == 0:
991 frame_ptr
= unsigned(dereference(frame_val
))
995 @lldb_command('fullbt')
996 def FullBackTrace(cmd_args
=[]):
997 """ Show full backtrace across the interrupt boundary.
998 Syntax: fullbt <frame ptr>
999 Example: fullbt `$rbp`
1001 if len(cmd_args
) < 1:
1002 print FullBackTrace
.__doc
__
1004 print GetFullBackTrace(ArgumentStringToInt(cmd_args
[0]), prefix
="\t")
1006 @lldb_command('fullbtall')
1007 def FullBackTraceAll(cmd_args
=[]):
1008 """ Show full backtrace across the interrupt boundary for threads running on all processors.
1012 for processor
in IterateLinkedList(kern
.globals.processor_list
, 'processor_list') :
1013 print "\n" + GetProcessorSummary(processor
)
1014 active_thread
= processor
.active_thread
1015 if unsigned(active_thread
) != 0 :
1016 task_val
= active_thread
.task
1017 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1018 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1019 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1020 print "\t" + GetThreadSummary
.header
1021 print "\t" + GetThreadSummary(active_thread
)
1022 print "\tBacktrace:"
1024 ThreadVal
= GetLLDBThreadForKernelThread(active_thread
)
1026 FramePtr
= ThreadVal
.frames
[0].GetFP()
1028 print GetFullBackTrace(unsigned(FramePtr
), prefix
="\t")
1031 @lldb_command('symbolicate')
1032 def SymbolicateAddress(cmd_args
=[]):
1033 """ Symbolicate an address for symbol information from loaded symbols
1034 Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr"
1036 if len(cmd_args
) < 1:
1037 print "Invalid address.\nSyntax: symbolicate <address>"
1039 print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args
[0]))
1042 @lldb_command('showinitchild')
1043 def ShowInitChild(cmd_args
=None):
1044 """ Routine to print out all processes in the system
1045 which are children of init process
1047 headp
= kern
.globals.initproc
.p_children
1048 for pp
in IterateListEntry(headp
, 'struct proc *', 'p_sibling'):
1049 print GetProcInfo(pp
)
1052 @lldb_command('showproctree')
1053 def ShowProcTree(cmd_args
=None):
1054 """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes.
1055 If no argument is given, showproctree will print all the processes in the system.
1056 If pid is specified, showproctree prints all the descendants of the indicated process
1060 search_pid
= ArgumentStringToInt(cmd_args
[0])
1063 print "pid specified must be a positive number"
1064 print ShowProcTree
.__doc
__
1067 hdr_format
= "{0: <6s} {1: <14s} {2: <9s}\n"
1068 out_string
= hdr_format
.format("PID", "PROCESS", "POINTER")
1069 out_string
+= hdr_format
.format('='*3, '='*7, '='*7)
1070 proc
= GetProcForPid(search_pid
)
1071 out_string
+= "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc
.p_ppid
, proc
.p_pptr
.p_comm
, unsigned(proc
.p_pptr
))
1072 out_string
+= "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc
.p_pid
, proc
.p_comm
, unsigned(proc
))
1074 ShowProcTreeRecurse(proc
, "| ")
1078 def ShowProcTreeRecurse(proc
, prefix
=""):
1079 """ Prints descendants of a given proc in hierarchial tree form
1081 proc : core.value representing a struct proc * in the kernel
1083 str : String containing info about a given proc and its descendants in tree form
1085 if proc
.p_childrencnt
> 0:
1086 head_ptr
= proc
.p_children
.lh_first
1088 for p
in IterateListEntry(proc
.p_children
, 'struct proc *', 'p_sibling'):
1089 print prefix
+ "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p
.p_pid
, p
.p_comm
, unsigned(p
))
1090 ShowProcTreeRecurse(p
, prefix
+ "| ")
1092 @lldb_command('showthreadfortid')
1093 def ShowThreadForTid(cmd_args
=None):
1094 """ The thread structure contains a unique thread_id value for each thread.
1095 This command is used to retrieve the address of the thread structure(thread_t)
1096 corresponding to a given thread_id.
1099 print "Please provide thread_t whose tid you'd like to look up"
1100 print ShowThreadForTid
.__doc
__
1102 search_tid
= ArgumentStringToInt(cmd_args
[0])
1103 for taskp
in kern
.tasks
:
1104 for actp
in IterateQueue(taskp
.threads
, 'struct thread *', 'task_threads'):
1105 if search_tid
== int(actp
.thread_id
):
1106 print "Found {0: #019x}".format(actp
)
1107 print GetThreadSummary
.header
1108 print GetThreadSummary(actp
)
1110 print "Not a valid thread_id"
1112 # Macro: showallprocessors
1114 def GetProcessorSummary(processor
):
1115 """ Internal function to print summary of processor
1116 params: processor - value representing struct processor *
1117 return: str - representing the details of given processor
1120 processor_state_str
= "INVALID"
1121 processor_state
= int(processor
.state
)
1123 processor_states
= {
1127 # 3 (formerly INACTIVE)
1133 if processor_state
in processor_states
:
1134 processor_state_str
= "{0: <11s} ".format(processor_states
[processor_state
])
1136 out_str
= "Processor {: <#018x} cpu_id {:>#4x} State {:<s}\n".format(processor
, int(processor
.cpu_id
), processor_state_str
)
1139 def GetGroupSetSummary(runq
, task_map
):
1140 """ Internal function to print summary of group run queue
1141 params: runq - value representing struct run_queue *
1142 return: str - representing the details of given run_queue
1144 out_str
= " runq: count {: <10d} highq: {: <10d} urgency {: <10d}\n".format(runq
.count
, runq
.highq
, runq
.urgency
)
1147 runq_queue_count
= sizeof(runq
.queues
)/sizeof(runq
.queues
[0])
1149 for runq_queue_i
in range(runq_queue_count
) :
1150 runq_queue_head
= addressof(runq
.queues
[runq_queue_i
])
1151 runq_queue_p
= runq_queue_head
.next
1153 if unsigned(runq_queue_p
) != unsigned(runq_queue_head
):
1154 runq_queue_this_count
= 0
1156 for entry
in IterateQueue(runq_queue_head
, "sched_entry_t", "links"):
1157 runq_queue_this_count
+= 1
1159 out_str
+= " Queue [{: <#012x}] Priority {: <3d} count {:d}\n".format(runq_queue_head
, runq_queue_i
, runq_queue_this_count
)
1160 for entry
in IterateQueue(runq_queue_head
, "sched_entry_t", "links"):
1162 task
= task_map
.get(unsigned(group
), "Unknown task!")
1163 out_str
+= "\tEntry [{: <#012x}] Priority {: <3d} Group {: <#012x} Task {: <#012x}\n".format(unsigned(entry
), entry
.sched_pri
, unsigned(entry
.group
), unsigned(task
))
1167 @lldb_command('showrunq')
1168 def ShowRunq(cmd_args
=None):
1169 """ Routine to print information of a runq
1170 Usage: showrunq <runq>
1173 runq
= kern
.GetValueFromAddress(cmd_args
[0], 'struct run_queue *')
1174 out_str
+= GetRunQSummary(runq
)
1177 def GetRunQSummary(runq
):
1178 """ Internal function to print summary of run_queue
1179 params: runq - value representing struct run_queue *
1180 return: str - representing the details of given run_queue
1182 out_str
= " runq: count {: <10d} highq: {: <10d} urgency {: <10d}\n".format(runq
.count
, runq
.highq
, runq
.urgency
)
1185 runq_queue_count
= sizeof(runq
.queues
)/sizeof(runq
.queues
[0])
1187 for runq_queue_i
in range(runq_queue_count
) :
1188 runq_queue_head
= addressof(runq
.queues
[runq_queue_i
])
1189 runq_queue_p
= runq_queue_head
.next
1191 if unsigned(runq_queue_p
) != unsigned(runq_queue_head
):
1192 runq_queue_this_count
= 0
1194 for thread
in IterateQueue(runq_queue_head
, "thread_t", "links"):
1195 runq_queue_this_count
+= 1
1197 out_str
+= " Queue [{: <#012x}] Priority {: <3d} count {:d}\n".format(runq_queue_head
, runq_queue_i
, runq_queue_this_count
)
1198 out_str
+= "\t" + GetThreadSummary
.header
+ "\n"
1199 for thread
in IterateQueue(runq_queue_head
, "thread_t", "links"):
1200 out_str
+= "\t" + GetThreadSummary(thread
) + "\n"
1201 if config
['verbosity'] > vHUMAN
:
1202 out_str
+= "\t" + GetThreadBackTrace(thread
, prefix
="\t\t") + "\n"
1206 def GetGrrrSummary(grrr_runq
):
1207 """ Internal function to print summary of grrr_run_queue
1208 params: grrr_runq - value representing struct grrr_run_queue *
1209 return: str - representing the details of given grrr_run_queue
1211 out_str
= " GRRR Info: Count {: <10d} Weight {: <10d} Current Group {: <#012x}\n".format(grrr_runq
.count
,
1212 grrr_runq
.weight
, grrr_runq
.current_group
)
1214 grrr_group_count
= sizeof(grrr_runq
.groups
)/sizeof(grrr_runq
.groups
[0])
1215 for grrr_group_i
in range(grrr_group_count
) :
1216 grrr_group
= addressof(grrr_runq
.groups
[grrr_group_i
])
1217 if grrr_group
.count
> 0:
1218 out_str
+= " Group {: <3d} [{: <#012x}] ".format(grrr_group
.index
, grrr_group
)
1219 out_str
+= "Count {:d} Weight {:d}\n".format(grrr_group
.count
, grrr_group
.weight
)
1220 grrr_group_client_head
= addressof(grrr_group
.clients
)
1221 out_str
+= GetThreadSummary
.header
1222 for thread
in IterateQueue(grrr_group_client_head
, "thread_t", "links"):
1223 out_str
+= "\t" + GetThreadSummary(thread
) + "\n"
1224 if config
['verbosity'] > vHUMAN
:
1225 out_str
+= "\t" + GetThreadBackTrace(thread
, prefix
="\t\t") + "\n"
1228 @lldb_command('showallprocessors')
1229 def ShowAllProcessors(cmd_args
=None):
1230 """ Routine to print information of all psets and processors
1231 Usage: showallprocessors
1233 pset
= addressof(kern
.globals.pset0
)
1235 show_priority_runq
= 0
1236 show_priority_pset_runq
= 0
1237 show_group_pset_runq
= 0
1238 show_fairshare_grrr
= 0
1239 show_fairshare_list
= 0
1240 sched_enum_val
= kern
.globals._sched
_enum
1242 if sched_enum_val
== 1:
1243 show_priority_runq
= 1
1244 show_fairshare_list
= 1
1245 elif sched_enum_val
== 2:
1246 show_priority_pset_runq
= 1
1247 show_fairshare_list
= 1
1248 elif sched_enum_val
== 4:
1250 show_fairshare_grrr
= 1
1251 elif sched_enum_val
== 5:
1252 show_priority_runq
= 1
1253 show_group_pset_runq
= 1
1254 show_fairshare_list
= 1
1255 elif sched_enum_val
== 6:
1256 show_priority_pset_runq
= 1
1257 show_priority_runq
= 1
1258 show_fairshare_list
= 1
1262 out_str
+= "Scheduler: {:s} ({:s}, {:d})\n".format(kern
.globals.sched_string
,
1263 kern
.Symbolicate(unsigned(kern
.globals.sched_current_dispatch
)),
1266 out_str
+= "Runnable threads: {:d} Timeshare threads: {:d} Background threads {:d}\n".format(
1267 kern
.globals.sched_run_count
, kern
.globals.sched_share_count
, kern
.globals.sched_background_count
)
1269 if show_group_pset_runq
:
1270 # Create a group->task mapping
1272 for task
in kern
.tasks
:
1273 task_map
[unsigned(task
.sched_group
)] = task
1274 for task
in kern
.terminated_tasks
:
1275 task_map
[unsigned(task
.sched_group
)] = task
1277 while unsigned(pset
) != 0:
1278 out_str
+= "Processor Set {: <#012x} Count {:d} (cpu_id {:<#x}-{:<#x})\n".format(pset
,
1279 pset
.cpu_set_count
, pset
.cpu_set_low
, pset
.cpu_set_hi
)
1281 if show_priority_pset_runq
:
1282 runq
= pset
.pset_runq
1283 out_str
+= GetRunQSummary(runq
)
1285 if show_group_pset_runq
:
1286 out_str
+= "Main Runq:\n"
1287 runq
= pset
.pset_runq
1288 out_str
+= GetGroupSetSummary(runq
, task_map
)
1289 out_str
+= "All Groups:\n"
1290 # TODO: Possibly output task header for each group
1291 for group
in IterateQueue(kern
.globals.sched_groups
, "sched_group_t", "sched_groups"):
1292 if (group
.runq
.count
!= 0) :
1293 task
= task_map
.get(unsigned(group
), "Unknown task!")
1294 out_str
+= "Group {: <#012x} Task {: <#012x}\n".format(unsigned(group
), unsigned(task
))
1295 out_str
+= GetRunQSummary(group
.runq
)
1297 out_str
+= " Active Processors:\n"
1298 for processor
in IterateQueue(pset
.active_queue
, "processor_t", "processor_queue"):
1300 out_str
+= GetProcessorSummary(processor
)
1301 if show_priority_runq
:
1302 runq
= processor
.runq
1303 out_str
+= GetRunQSummary(runq
)
1305 grrr_runq
= processor
.grrr_runq
1306 out_str
+= GetGrrrSummary(grrr_runq
)
1308 out_str
+= " Idle Processors:\n"
1309 for processor
in IterateQueue(pset
.idle_queue
, "processor_t", "processor_queue"):
1310 out_str
+= " " + GetProcessorSummary(processor
)
1311 if show_priority_runq
:
1312 out_str
+= GetRunQSummary(processor
.runq
)
1314 out_str
+= " Idle Secondary Processors:\n"
1315 for processor
in IterateQueue(pset
.idle_secondary_queue
, "processor_t", "processor_queue"):
1316 out_str
+= " " + GetProcessorSummary(processor
)
1317 if show_priority_runq
:
1318 out_str
+= GetRunQSummary(processor
.runq
)
1320 pset
= pset
.pset_list
1322 out_str
+= "\nRealtime Queue Count {:d}\n".format(kern
.globals.rt_runq
.count
)
1323 for rt_runq_thread
in IterateQueue(kern
.globals.rt_runq
.queue
, "thread_t", "links"):
1324 out_str
+= ShowTask([unsigned(rt_runq_thread
.task
)])
1325 out_str
+= ShowAct([unsigned(rt_runq_thread
)])
1328 if show_fairshare_list
:
1329 out_str
+= "Fair Share Queue Count {:d}\n".format(kern
.globals.fs_runq
.count
)
1330 for fs_runq_thread
in IterateQueue(kern
.globals.fs_runq
.queue
, "thread_t", "links"):
1331 out_str
+= ShowTask([unsigned(fs_runq_thread
.task
)])
1332 out_str
+= ShowAct([unsigned(rt_runq_thread
)])
1333 if show_fairshare_grrr
:
1334 out_str
+= "Fair Share Queue Count {:d}\n".format(kern
.globals.fs_grrr_runq
.count
)
1335 fs_grrr
= addressof(kern
.globals.fs_grrr_runq
)
1336 out_str
+= GetGrrrSummary(fs_grrr
)
1339 # EndMacro: showallprocessors
1341 def GetLedgerEntrySummary(ledger_template
, ledger
, i
):
1342 """ Internal function to get internals of a ledger entry (*not* a ledger itself)
1343 params: ledger_template - value representing struct ledger_template_t for the task or thread
1344 ledger - value representing struct ledger_entry *
1345 return: str - formatted output information of ledger entries
1347 ledger_limit_infinity
= (uint64_t(0x1).value
<< 63) - 1
1348 lf_refill_scheduled
= 0x0400
1349 lf_tracking_max
= 0x4000
1352 now
= unsigned(kern
.globals.sched_tick
) / 20
1355 out_str
+= "{: >32s} {:<2d}:".format(ledger_template
.lt_entries
[i
].et_key
, i
)
1356 out_str
+= "{: >15d} ".format(unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
))
1357 if (ledger
.le_flags
& lf_tracking_max
):
1358 out_str
+= "{:9d} {:5d} ".format(ledger
._le
.le_peaks
[0].le_max
, now
- unsigned(ledger
._le
.le_peaks
[0].le_time
))
1359 out_str
+= "{:9d} {:4d} ".format(ledger
._le
.le_peaks
[1].le_max
, now
- unsigned(ledger
._le
.le_peaks
[1].le_time
))
1361 out_str
+= " - - - - "
1363 out_str
+= "{:12d} {:12d} ".format(unsigned(ledger
.le_credit
), unsigned(ledger
.le_debit
))
1364 if (unsigned(ledger
.le_limit
) != ledger_limit_infinity
):
1365 out_str
+= "{:12d} ".format(unsigned(ledger
.le_limit
))
1369 if (ledger
.le_flags
& lf_refill_scheduled
):
1370 out_str
+= "{:15d} ".format(ledger
._le
.le_refill
.le_refill_period
)
1374 if (ledger
.le_flags
& lf_refill_scheduled
):
1375 out_str
+= "{:9d} ".format((unsigned(ledger
.le_limit
) * 100) / ledger
._le
.le_refill
.le_refill_period
)
1379 if (unsigned(ledger
.le_warn_level
) != ledger_limit_infinity
):
1380 out_str
+= "{:9d} ".format((unsigned(ledger
.le_warn_level
) * 100) / unsigned(ledger
.le_limit
))
1384 if ((unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
)) > unsigned(ledger
.le_limit
)):
1389 out_str
+= "{:#8x}\n".format(ledger
.le_flags
)
1392 def GetThreadLedgerSummary(thread_val
):
1393 """ Internal function to get a summary of ledger entries for the given thread
1394 params: thread - value representing struct thread *
1395 return: str - formatted output information for ledger entries of the input thread
1397 out_str
= " [{:#08x}]\n".format(thread_val
)
1398 ledgerp
= thread_val
.t_threadledger
1401 while i
!= ledgerp
.l_template
.lt_cnt
:
1402 out_str
+= GetLedgerEntrySummary(kern
.globals.thread_ledger_template
,
1403 ledgerp
.l_entries
[i
], i
)
1407 @header("{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >9s} {5: >6s} {6: >8s} {7: <10s} {8: <9s} \
1408 {9: <12s} {10: <7s} {11: <15s} {12: <8s} {13: <9s} {14: <6s} {15: >6s}".format(
1409 "task [thread]", "entry", "#", "balance", "peakA", "(age)", "peakB", "(age)", "credit",
1410 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags"))
1411 def GetTaskLedgers(task_val
):
1412 """ Internal function to get summary of ledger entries from the task and its threads
1413 params: task_val - value representing struct task *
1414 return: str - formatted output information for ledger entries of the input task
1417 task_ledgerp
= task_val
.ledger
1419 out_str
+= "{: #08x} ".format(task_val
)
1420 pval
= Cast(task_val
.bsd_info
, 'proc *')
1422 out_str
+= "{: <5s}:\n".format(pval
.p_comm
)
1424 out_str
+= "Invalid process:\n"
1425 while i
!= task_ledgerp
.l_template
.lt_cnt
:
1426 out_str
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, task_ledgerp
.l_entries
[i
], i
)
1430 for thval
in IterateQueue(task_val
.threads
, 'thread *', 'task_threads'):
1431 out_str
+= GetThreadLedgerSummary(thval
)
1435 # Macro: showtaskledgers
1437 @lldb_command('showtaskledgers', 'F:')
1438 def ShowTaskLedgers(cmd_args
=None, cmd_options
={}):
1439 """ Routine to print a summary of ledger entries for the task and all of its threads
1440 Usage: showtaskledgers <address of task>
1441 or : showtaskledgers -F <name of task>
1443 if "-F" in cmd_options
:
1444 task_list
= FindTasksByName(cmd_options
["-F"])
1445 for tval
in task_list
:
1446 print GetTaskLedgers
.header
1447 print GetTaskLedgers(tval
)
1451 raise ArgumentError("No arguments passed.")
1452 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1454 raise ArgumentError("unknown arguments: %r" %cmd
_args
)
1455 print GetTaskLedgers
.header
1456 print GetTaskLedgers(tval
)
1458 # EndMacro: showtaskledgers
1460 # Macro: showalltaskledgers
1462 @lldb_command('showalltaskledgers')
1463 def ShowAllTaskLedgers(cmd_args
=None):
1464 """ Routine to print a summary of ledger entries for all tasks and respective threads
1465 Usage: showalltaskledgers
1467 for t
in kern
.tasks
:
1468 task_val
= unsigned(t
)
1469 ShowTaskLedgers([task_val
])
1471 # EndMacro: showalltaskledgers
1473 # Macro: showprocuuidpolicytable
1475 @lldb_type_summary(['proc_uuid_policy_entry'])
1476 @header("{0: <36s} {1: <10s}".format("uuid", "flags"))
1477 def GetProcUUIDPolicyEntrySummary(entry
):
1478 """ Summarizes the important fields in proc_uuid_policy_entry structure.
1479 params: entry: value - value object representing an entry
1480 returns: str - summary of the entry
1484 data
.append(int(entry
.uuid
[i
]))
1485 flags
= unsigned(entry
.flags
)
1486 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
)
1489 @lldb_command('showprocuuidpolicytable')
1490 def ShowProcUUIDPolicyTable(cmd_args
=None):
1491 """ Routine to print the proc UUID policy table
1492 Usage: showprocuuidpolicytable
1494 hashslots
= unsigned(kern
.globals.proc_uuid_policy_hash_mask
)
1495 print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary
.header
1496 for i
in range(0, hashslots
+1):
1497 headp
= addressof(kern
.globals.proc_uuid_policy_hashtbl
[i
])
1499 for entry
in IterateListEntry(headp
, 'struct proc_uuid_policy_entry *', 'entries'):
1500 print "{0: >2d}.{1: <5d} ".format(i
, entrynum
) + GetProcUUIDPolicyEntrySummary(entry
)
1504 # EndMacro: showprocuuidpolicytable
1506 @lldb_command('showalltaskpolicy')
1507 def ShowAllTaskPolicy(cmd_args
=None):
1509 Routine to print a summary listing of all the tasks
1510 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1511 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1512 io_policy -> RAGE - rapid aging of vnodes requested
1513 NORM - normal I/O explicitly requested (this is the default)
1514 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1515 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1518 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1519 for t
in kern
.tasks
:
1520 pval
= Cast(t
.bsd_info
, 'proc *')
1521 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1522 requested_strings
= [
1523 ["int_darwinbg", "DBG-int"],
1524 ["ext_darwinbg", "DBG-ext"],
1525 ["int_iotier", "iotier-int"],
1526 ["ext_iotier", "iotier-ext"],
1527 ["int_iopassive", "passive-int"],
1528 ["ext_iopassive", "passive-ext"],
1529 ["bg_iotier", "bg-iotier"],
1530 ["terminated", "terminated"],
1531 ["th_pidbind_bg", "bg-pidbind"],
1532 ["th_workq_bg", "bg-workq"],
1533 ["t_apptype", "apptype"],
1534 ["t_boosted", "boosted"],
1535 ["t_int_gpu_deny", "gpudeny-int"],
1536 ["t_ext_gpu_deny", "gpudeny-ext"],
1538 ["t_tal_enabled", "tal-enabled"],
1539 ["t_base_latency_qos", "latency-base"],
1540 ["t_over_latency_qos", "latency-override"],
1541 ["t_base_through_qos", "throughput-base"],
1542 ["t_over_through_qos", "throughput-override"]
1546 for value
in requested_strings
:
1547 if t
.requested_policy
.__getattr
__(value
[0]) :
1548 requested
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1552 suppression_strings
= [
1553 ["t_sup_active", "active"],
1554 ["t_sup_lowpri_cpu", "lowpri-cpu"],
1555 ["t_sup_timer", "timer-throttling"],
1556 ["t_sup_disk", "disk-throttling"],
1557 ["t_sup_cpu_limit", "cpu-limits"],
1558 ["t_sup_suspend", "suspend"],
1559 ["t_sup_bg_sockets", "bg-sockets"]
1563 for value
in suppression_strings
:
1564 if t
.requested_policy
.__getattr
__(value
[0]) :
1565 suppression
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1569 effective_strings
= [
1570 ["darwinbg", "background"],
1571 ["lowpri_cpu", "lowpri-cpu"],
1572 ["io_tier", "iotier"],
1573 ["io_passive", "passive"],
1574 ["all_sockets_bg", "bg-allsockets"],
1575 ["new_sockets_bg", "bg-newsockets"],
1576 ["bg_iotier", "bg-iotier"],
1577 ["terminated", "terminated"],
1578 ["t_gpu_deny", "gpu-deny"],
1579 ["t_tal_engaged", "tal-engaged"],
1580 ["t_suspended", "suspended"],
1581 ["t_watchers_bg", "bg-watchers"],
1582 ["t_latency_qos", "latency-qos"],
1583 ["t_through_qos", "throughput-qos"],
1584 ["t_sup_active", "suppression-active"],
1589 for value
in effective_strings
:
1590 if t
.effective_policy
.__getattr
__(value
[0]) :
1591 effective
+=value
[1] + ": " + str(t
.effective_policy
.__getattr
__(value
[0])) + " "
1597 ["t_updating_policy", "updating"],
1598 ["update_sockets", "update_sockets"],
1599 ["t_update_timers", "update_timers"],
1600 ["t_update_watchers", "update_watchers"]
1604 for value
in pended_strings
:
1605 if t
.pended_policy
.__getattr
__(value
[0]) :
1606 pended
+=value
[1] + ": " + str(t
.pended_policy
.__getattr
__(value
[0])) + " "
1610 print "requested: " + requested
1611 print "suppression: " + suppression
1612 print "effective: " + effective
1613 print "pended: " + pended
1616 @lldb_type_summary(['wait_queue', 'wait_queue_t'])
1617 @header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask"))
1618 def GetWaitQSummary(waitq
):
1619 """ Summarizes the important fields in task structure.
1620 params: task: value - value object representing a task in kernel
1621 returns: str - summary of the task
1624 format_string
= '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
1628 if (waitq
.wq_fifo
== 1) :
1633 if (waitq
.wq_prepost
== 1) :
1636 if (waitq
.wq_type
== 0x3) :
1638 elif (waitq
.wq_type
== 0x2) :
1643 out_string
+= format_string
.format(waitq
, unsigned(waitq
.wq_interlock
.lock_data
), policy
, 0, 0, unsigned(waitq
.wq_eventmask
))
1645 out_string
+= "\n" + GetThreadSummary
.header
1647 for thread
in IterateQueue(waitq
.wq_queue
, "thread_t", "links"):
1648 out_string
+= "\n" + GetThreadSummary(thread
)
1653 @lldb_command('showallsuspendedtasks', '')
1654 def ShowSuspendedTasks(cmd_args
=[], options
={}):
1655 """ Show a list of suspended tasks with their process name summary.
1657 print GetTaskSummary
.header
+ ' ' + GetProcSummary
.header
1658 for t
in kern
.tasks
:
1659 if t
.suspend_count
> 0:
1660 print GetTaskSummary(t
) + ' ' + GetProcSummary(Cast(t
.bsd_info
, 'proc *'))