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("{:>18s} {:>10s} {:>8s} {:>8s} {:>8s} {:>8s}".format("coalition", "id", "refcount", "active", "focal", "nonfocal"))
331 def GetCoalitionSummary(coal
):
333 format_string
= '{:>#018x} {:>10d} {:>8d} {:>8d} {:>8d} {:>8d}'
336 if (coal
.terminated
):
337 flags_string
+= ' terminated'
339 flags_string
+= ' reaped'
340 out_string
+= format_string
.format(coal
, coal
.id, coal
.ref_count
, coal
.active_count
, coal
.focal_tasks_count
, coal
.non_focal_tasks_count
)
344 @lldb_type_summary(['proc', 'proc *'])
345 @header("{0: >6s} {1: ^20s} {2: >14s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command"))
346 def GetProcSummary(proc
):
347 """ Summarize the process data.
349 proc : value - value representaitng a proc * in kernel
351 str - string summary of the process.
354 format_string
= "{0: >6d} {1: >#020x} {2: >14s} {3: >2d} {4: >2d} {5: >2d} {6: <20s}"
355 pval
= proc
.GetSBValue()
356 #code.interact(local=locals())
357 if str(pval
.GetType()) != str(gettype('proc *')) :
358 return "Unknown type " + str(pval
.GetType()) + " " + str(hex(proc
))
360 out_string
+= "Process " + hex(proc
) + " is not valid."
362 pid
= int(proc
.p_pid
)
363 proc_addr
= int(hex(proc
), 16)
365 if int(proc
.p_lflag
) & 0x400000 :
366 proc_rage_str
= "RAGE"
368 task
= Cast(proc
.task
, 'task *')
372 if int(task
.effective_policy
.darwinbg
) != 0:
374 if int(task
.effective_policy
.lowpri_cpu
) != 0:
377 if int(task
.effective_policy
.io_tier
) != 0:
379 if int(task
.effective_policy
.io_passive
) != 0:
381 if int(task
.effective_policy
.terminated
) != 0:
384 if int(task
.effective_policy
.t_suspended
) != 0:
386 if int(task
.effective_policy
.t_latency_qos
) != 0:
388 if int(task
.effective_policy
.t_sup_active
) != 0:
393 work_queue
= Cast(proc
.p_wqptr
, 'workqueue *')
394 if proc
.p_wqptr
!= 0 :
395 wq_num_threads
= int(work_queue
.wq_nthreads
)
396 wq_idle_threads
= int(work_queue
.wq_thidlecount
)
397 wq_req_threads
= int(work_queue
.wq_reqcount
)
406 process_name
= str(proc
.p_comm
)
407 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
)
410 @lldb_type_summary(['tty_dev_t', 'tty_dev_t *'])
411 @header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","master", "slave", "open", "free", "name", "revoke"))
412 def GetTTYDevSummary(tty_dev
):
413 """ Summarizes the important fields in tty_dev_t structure.
414 params: tty_dev: value - value object representing a tty_dev_t in kernel
415 returns: str - summary of the tty_dev
418 format_string
= "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"
419 open_fn
= kern
.Symbolicate(int(hex(tty_dev
.open), 16))
420 free_fn
= kern
.Symbolicate(int(hex(tty_dev
.free
), 16))
421 name_fn
= kern
.Symbolicate(int(hex(tty_dev
.name
), 16))
422 revoke_fn
= kern
.Symbolicate(int(hex(tty_dev
.revoke
), 16))
423 out_string
+= format_string
.format(tty_dev
, tty_dev
.master
, tty_dev
.slave
, open_fn
, free_fn
, name_fn
, revoke_fn
)
426 @lldb_type_summary(['kqueue *'])
427 @header("{: <20s} {: <20s} {: <6s} {: <20s} {: <10s}".format('kqueue', 'process', '#events', 'wqs', 'state'))
428 def GetKQueueSummary(kq
):
429 """ summarizes kqueue information
430 returns: str - summary of kqueue
433 format_string
= "{o: <#020x} {o.kq_p: <#020x} {o.kq_count: <6d} {o.kq_wqs: <#020x} {st_str: <10s}"
434 state
= int(kq
.kq_state
)
438 if int(state
& mask
):
439 state_str
+= ' ' + xnudefines
.kq_state_strings
[int(state
& mask
)]
441 out_string
+= format_string
.format(o
=kq
, st_str
=state_str
)
444 @lldb_type_summary(['knote *'])
445 @header("{0: <20s}".format('knote'))
446 def GetKnoteSummary(kn
):
447 """ Summarizes a knote and related information
448 returns: str - summary of knote
451 format_string
= "{o: <#020x}"
452 out_string
+= format_string
.format(o
=kn
)
457 @lldb_command('showtask', 'F:')
458 def ShowTask(cmd_args
=None, cmd_options
={}):
459 """ Routine to print a summary listing of given task
460 Usage: showtask <address of task>
461 or : showtask -F <name of task>
464 if "-F" in cmd_options
:
465 task_list
= FindTasksByName(cmd_options
['-F'])
468 raise ArgumentError("Invalid arguments passed.")
470 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
472 raise ("Unknown arguments: %r" % cmd_args
)
473 task_list
.append(tval
)
475 for tval
in task_list
:
476 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
477 pval
= Cast(tval
.bsd_info
, 'proc *')
478 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
484 @lldb_command('showpid')
485 def ShowPid(cmd_args
=None):
486 """ Routine to print a summary listing of task corresponding to given pid
487 Usage: showpid <pid value>
490 print "No arguments passed"
491 print ShowPid
.__doc
__
493 pidval
= ArgumentStringToInt(cmd_args
[0])
495 pval
= Cast(t
.bsd_info
, 'proc *')
496 if pval
and pval
.p_pid
== pidval
:
497 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
498 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
505 @lldb_command('showproc')
506 def ShowProc(cmd_args
=None):
507 """ Routine to print a summary listing of task corresponding to given proc
508 Usage: showproc <address of proc>
511 print "No arguments passed"
512 print ShowProc
.__doc
__
514 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
516 print "unknown arguments:", str(cmd_args
)
518 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
519 tval
= Cast(pval
.task
, 'task *')
520 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
524 # Macro: showprocinfo
526 @lldb_command('showprocinfo')
527 def ShowProcInfo(cmd_args
=None):
528 """ Routine to display name, pid, parent & task for the given proc address
529 It also shows the Cred, Flags and state of the process
530 Usage: showprocinfo <address of proc>
533 print "No arguments passed"
534 print ShowProcInfo
.__doc
__
536 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
538 print "unknown arguments:", str(cmd_args
)
540 print GetProcInfo(pval
)
542 # EndMacro: showprocinfo
544 #Macro: showprocfiles
546 @lldb_command('showprocfiles')
547 def ShowProcFiles(cmd_args
=None):
548 """ Given a proc_t pointer, display the list of open file descriptors for the referenced process.
549 Usage: showprocfiles <proc_t>
552 print ShowProcFiles
.__doc
__
554 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t')
555 proc_filedesc
= proc
.p_fd
556 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
557 proc_ofiles
= proc_filedesc
.fd_ofiles
558 if unsigned(proc_ofiles
) == 0:
559 print 'No open files for proc {0: <s}'.format(cmd_args
[0])
561 print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')
562 print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")
576 while count
<= proc_lastfile
:
577 if unsigned(proc_ofiles
[count
]) != 0:
579 proc_fd_flags
= proc_ofiles
[count
].f_flags
580 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
581 out_str
+= "{0: <5d} ".format(count
)
582 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
))
583 out_str
+= "0x{0:0>8x} ".format(unsigned(proc_fd_flags
))
584 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
585 if proc_fd_ftype
in filetype_dict
:
586 out_str
+= "{0: <8s} ".format(filetype_dict
[proc_fd_ftype
])
588 out_str
+= "?: {0: <5d} ".format(proc_fd_ftype
)
589 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
.fg_data
))
590 if proc_fd_ftype
== 1:
591 fd_name
= Cast(proc_fd_fglob
.fg_data
, 'struct vnode *').v_name
592 out_str
+= "{0: <64s}".format(fd_name
)
597 #EndMacro: showprocfiles
600 @lldb_command('showkqueue' ,'')
601 def ShowKQueue(cmd_args
=[], cmd_options
={}):
602 """ Given a struct kqueue pointer, display the summary of the kqueue
603 Usage: (lldb) showkqueue <struct kqueue *>
606 raise ArgumentError('Invalid arguments')
608 kq
= kern
.GetValueFromAddress(cmd_args
[0], 'struct kqueue *')
609 print GetKQueueSummary
.header
610 print GetKQueueSummary(kq
)
612 #EndMacro: showkqueue
616 @lldb_command('showtty')
617 def ShowTTY(cmd_args
=None):
618 """ Display information about a struct tty
619 Usage: showtty <tty struct>
622 print ShowTTY
.__doc
__
625 tty
= kern
.GetValueFromAddress(cmd_args
[0], 'struct tty *')
626 print "TTY structure at: {0: <s}".format(cmd_args
[0])
627 print "Last input to raw queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_rawq
.c_cs
), tty
.t_rawq
.c_cs
)
628 print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_canq
.c_cs
), tty
.t_canq
.c_cs
)
629 print "Last output data: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_outq
.c_cs
), tty
.t_outq
.c_cs
)
631 ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'],
632 ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'],
633 ['', 'TS_BUSY (Draining output)'],
634 ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'],
635 ['', 'TS_FLUSH (Outq has been flushed during DMA)'],
636 ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'],
637 ['', 'TS_TBLOCK (Further input blocked)'],
638 ['', 'TS_TIMEOUT (Wait for output char processing)'],
639 ['', 'TS_TTSTOP (Output paused)'],
640 ['', 'TS_WOPEN (Open in progress)'],
641 ['', 'TS_XCLUDE (Tty requires exclusivity)'],
642 ['', 'TS_BKSL (State for lowercase \\ work)'],
643 ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'],
644 ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'],
645 ['', 'TS_LNCH (Next character is literal)'],
646 ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'],
647 ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'],
648 ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'],
649 ['', 'TS_SNOOP (Device is being snooped on)'],
650 ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'],
651 ['', 'TS_ZOMBIE (Connection lost)'],
652 ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'],
653 ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'],
654 ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)']
658 tty_state
= unsigned(tty
.t_state
)
661 if tty_state
& mask
!= 0:
662 if len(tty_state_info
[index
][1]) > 0:
663 print '\t' + tty_state_info
[index
][1]
665 if len(tty_state_info
[index
][0]) > 0:
666 print '\t' + tty_state_info
[index
][0]
669 print "Flags: 0x{0:0>8x}".format(unsigned(tty
.t_flags
))
670 print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty
.t_pgrp
))
671 print "Enclosing session: 0x{0:0>16x}".format(unsigned(tty
.t_session
))
673 print "\tInput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_iflag
))
674 print "\tOutput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_oflag
))
675 print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_cflag
))
676 print "\tLocal Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_lflag
))
677 print "\tInput Speed: {0: <8d}".format(tty
.t_termios
.c_ispeed
)
678 print "\tOutput Speed: {0: <8d}".format(tty
.t_termios
.c_ospeed
)
679 print "High Watermark: {0: <d} bytes".format(tty
.t_hiwat
)
680 print "Low Watermark : {0: <d} bytes".format(tty
.t_lowat
)
684 #Macro showallttydevs
686 @lldb_command('showallttydevs')
687 def ShowAllTTYDevs(cmd_args
=[], cmd_options
={}):
688 """ Show a list of ttydevs registered in the system.
692 tty_dev_head
= kern
.globals.tty_dev_head
693 tty_dev
= tty_dev_head
694 print GetTTYDevSummary
.header
695 while unsigned(tty_dev
) != 0:
696 print GetTTYDevSummary(tty_dev
)
697 tty_dev
= tty_dev
.next
700 #EndMacro: showallttydevs
702 #Macro: dumpcallqueue
704 @lldb_command('dumpcallqueue')
705 def DumpCallQueue(cmd_args
=None):
706 """ Displays the contents of the specified call_entry queue.
707 Usage: dumpcallqueue <queue_head_t *>
710 print DumpCallQueue
.__doc
__
712 print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
713 callhead
= kern
.GetValueFromAddress(cmd_args
[0], 'queue_head_t *')
715 for callentry
in IterateQueue(callhead
, 'struct call_entry *', 'q_link'):
716 print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format(
717 unsigned(callentry
), unsigned(callentry
.param0
), unsigned(callentry
.param1
),
718 unsigned(callentry
.deadline
), unsigned(callentry
.func
))
720 print "{0: <d} entries!".format(count
)
722 #EndMacro: dumpcallqueue
724 @lldb_command('showallcoalitions')
725 def ShowAllCoalitions(cmd_args
=None):
726 """ Routine to print a summary listing of all the coalitions
731 0 : "TASK_UNSPECIFIED",
732 1 : "TASK_FOREGROUND_APPLICATION",
733 2 : "TASK_BACKGROUND_APPLICATION",
734 3 : "TASK_CONTROL_APPLICATION",
735 4 : "TASK_GRAPHICS_SERVER",
736 5 : "TASK_THROTTLE_APPLICATION",
737 6 : "TASK_NONUI_APPLICATION",
738 7 : "TASK_DEFAULT_APPLICATION",
742 0x0 : "SFI_CLASS_UNSPECIFIED",
743 0x1 : "SFI_CLASS_DARWIN_BG",
744 0x2 : "SFI_CLASS_APP_NAP",
745 0x3 : "SFI_CLASS_MANAGED_FOCAL",
746 0x4 : "SFI_CLASS_MANAGED_NONFOCAL",
747 0x5 : "SFI_CLASS_DEFAULT_FOCAL",
748 0x6 : "SFI_CLASS_DEFAULT_NONFOCAL",
749 0x7 : "SFI_CLASS_KERNEL",
750 0x8 : "SFI_CLASS_OPTED_OUT",
751 0x9 : "SFI_CLASS_UTILITY",
752 0xA : "SFI_CLASS_LEGACY_FOCAL",
753 0xB : "SFI_CLASS_LEGACY_NONFOCAL",
754 0xC : "SFI_CLASS_USER_INITIATED_FOCAL",
755 0xD : "SFI_CLASS_USER_INITIATED_NONFOCAL",
756 0xE : "SFI_CLASS_USER_INTERACTIVE_FOCAL",
757 0xF : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL",
758 0x10 : "SFI_CLASS_MAINTENANCE",
762 print GetCoalitionSummary
.header
763 for c
in kern
.coalitions
:
764 print GetCoalitionSummary(c
)
765 for task
in IterateQueue(c
.tasks
, "task_t", "coalition_tasks"):
766 print "\t" + hex(task
) + " " + GetProcNameForTask(task
) + " " + role_strs
[int(task
.effective_policy
.t_role
)]
767 for thread
in IterateQueue(task
.threads
, "thread_t", "task_threads"):
768 print "\t\t" + hex(thread
) + " " + sfi_strs
[int(thread
.sfi_class
)]
771 @lldb_command('showalltasks')
772 def ShowAllTasks(cmd_args
=None):
773 """ Routine to print a summary listing of all the tasks
774 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
775 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
776 io_policy -> RAGE - rapid aging of vnodes requested
777 NORM - normal I/O explicitly requested (this is the default)
778 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
779 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
782 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
784 pval
= Cast(t
.bsd_info
, 'proc *')
785 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
788 @lldb_command('showterminatedtasks')
789 def ShowTerminatedTasks(cmd_args
=None):
790 """ Routine to print a summary listing of all the terminated tasks
791 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
792 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
793 io_policy -> RAGE - rapid aging of vnodes requested
794 NORM - normal I/O explicitly requested (this is the default)
795 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
796 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
797 syntax: (lldb)showallterminatedtasks
800 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
801 for t
in kern
.terminated_tasks
:
802 pval
= Cast(t
.bsd_info
, 'proc *')
803 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
806 # Macro: showtaskstacks
808 def ShowTaskStacks(task
):
809 """ Print a task with summary and stack information for each of its threads
812 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
813 pval
= Cast(task
.bsd_info
, 'proc *')
814 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
815 for th
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
816 print " " + GetThreadSummary
.header
817 print " " + GetThreadSummary(th
)
818 print GetThreadBackTrace(th
, prefix
=" ") + "\n"
820 def FindTasksByName(searchstr
, ignore_case
=True):
821 """ Search the list of tasks by name.
823 searchstr: str - a regex like string to search for task
824 ignore_case: bool - If False then exact matching will be enforced
826 [] - array of task object. Empty if not found any
830 re_options
= re
.IGNORECASE
831 search_regex
= re
.compile(searchstr
, re_options
)
834 pval
= Cast(t
.bsd_info
, "proc *")
835 process_name
= "{:s}".format(pval
.p_comm
)
836 if search_regex
.search(process_name
):
840 @lldb_command('showtaskstacks', 'F:')
841 def ShowTaskStacksCmdHelper(cmd_args
=None, cmd_options
={}):
842 """ Routine to print out the stack for each thread in a task
843 Usage: showtaskstacks <0xaddress of task>
844 or: showtaskstacks -F launchd
847 if "-F" in cmd_options
:
848 find_task_str
= cmd_options
["-F"]
849 task_list
= FindTasksByName(find_task_str
)
850 for tval
in task_list
:
855 raise ArgumentError("No arguments passed")
857 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
859 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
864 # EndMacro: showtaskstacks
866 @lldb_command('showallthreads')
867 def ShowAllThreads(cmd_args
= None):
868 """ Display info about all threads in the system
871 ShowTaskThreads([str(int(t
))])
874 for t
in kern
.terminated_tasks
:
875 print "Terminated: \n"
876 ShowTaskThreads([str(int(t
))])
881 @lldb_command('showtaskthreads', "F:")
882 def ShowTaskThreads(cmd_args
= None, cmd_options
={}):
883 """ Display thread information for a given task
884 Usage: showtaskthreads <0xaddress of task>
885 or: showtaskthreads -F <name>
888 if "-F" in cmd_options
:
889 task_list
= FindTasksByName(cmd_options
["-F"])
891 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
894 raise ArgumentError("No arguments passed")
896 for task
in task_list
:
897 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
898 pval
= Cast(task
.bsd_info
, 'proc *')
899 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
900 print "\t" + GetThreadSummary
.header
901 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
902 print "\t" + GetThreadSummary(thval
)
905 @lldb_command('showact')
906 def ShowAct(cmd_args
=None):
907 """ Routine to print out the state of a specific thread.
908 usage: showact <activation>
910 if cmd_args
== None or len(cmd_args
) < 1:
911 print "No arguments passed"
912 print ShowAct
.__doc
__
914 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
915 print GetThreadSummary
.header
916 print GetThreadSummary(threadval
)
918 @lldb_command('showactstack')
919 def ShowActStack(cmd_args
=None):
920 """ Routine to print out the stack of a specific thread.
921 usage: showactstack <activation>
923 if cmd_args
== None or len(cmd_args
) < 1:
924 print "No arguments passed"
925 print ShowAct
.__doc
__.strip()
927 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
928 print GetThreadSummary
.header
929 print GetThreadSummary(threadval
)
930 print GetThreadBackTrace(threadval
, prefix
="\t")
933 @lldb_command('switchtoact')
934 def SwitchToAct(cmd_args
=None):
935 """ Switch to different context specified by activation
936 This command allows gdb to examine the execution context and call
937 stack for the specified activation. For example, to view the backtrace
938 for an activation issue "switchtoact <address>", followed by "bt".
939 Before resuming execution, issue a "resetctx" command, to
940 return to the original execution context.
942 if cmd_args
== None or len(cmd_args
) < 1:
943 print "No arguments passed"
944 print SwitchToAct
.__doc
__.strip()
946 thval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
947 lldbthread
= GetLLDBThreadForKernelThread(thval
)
948 print GetThreadSummary
.header
949 print GetThreadSummary(thval
)
950 LazyTarget
.GetProcess().selected_thread
= lldbthread
951 if not LazyTarget
.GetProcess().SetSelectedThread(lldbthread
):
952 print "Failed to switch thread."
954 # Macro: showallstacks
955 @lldb_command('showallstacks')
956 def ShowAllStacks(cmd_args
=None):
957 """Routine to print out the stack for each thread in the system.
965 # EndMacro: showallstacks
967 # Macro: showcurrentstacks
968 @lldb_command('showcurrentstacks')
969 def ShowCurrentStacks(cmd_args
=None):
970 """ Routine to print out the thread running on each cpu (incl. its stack)
972 processor_list
= kern
.GetGlobalVariable('processor_list')
973 current_processor
= processor_list
974 while unsigned(current_processor
) > 0:
975 print "\n" + GetProcessorSummary(current_processor
)
976 active_thread
= current_processor
.active_thread
977 if unsigned(active_thread
) != 0 :
978 task_val
= active_thread
.task
979 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
980 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
981 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
982 print "\t" + GetThreadSummary
.header
983 print "\t" + GetThreadSummary(active_thread
)
985 print GetThreadBackTrace(active_thread
, prefix
="\t")
986 current_processor
= current_processor
.processor_list
988 # EndMacro: showcurrentstacks
990 @lldb_command('showcurrentthreads')
991 def ShowCurrentThreads(cmd_args
=None):
992 """ Display info about threads running on each cpu """
993 processor_list
= kern
.GetGlobalVariable('processor_list')
994 current_processor
= processor_list
995 while unsigned(current_processor
) > 0:
996 print GetProcessorSummary(current_processor
)
997 active_thread
= current_processor
.active_thread
998 if unsigned(active_thread
) != 0 :
999 task_val
= active_thread
.task
1000 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1001 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1002 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1003 print "\t" + GetThreadSummary
.header
1004 print "\t" + GetThreadSummary(active_thread
)
1005 current_processor
= current_processor
.processor_list
1008 def GetFullBackTrace(frame_addr
, verbosity
= vHUMAN
, prefix
= ""):
1009 """ Get backtrace across interrupt context.
1010 params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7)
1011 prefix - str - prefix for each line of output.
1016 frame_ptr
= frame_addr
1017 previous_frame_ptr
= 0
1018 # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
1019 mh_execute_addr
= int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
1020 while frame_ptr
and frame_ptr
!= previous_frame_ptr
and bt_count
< 128:
1021 if (kern
.arch
!= 'arm' and frame_ptr
< mh_execute_addr
) or (kern
.arch
== 'arm' and frame_ptr
> mh_execute_addr
):
1023 pc_val
= kern
.GetValueFromAddress(frame_ptr
+ kern
.ptrsize
,'uintptr_t *')
1024 pc_val
= unsigned(dereference(pc_val
))
1025 out_string
+= prefix
+ GetSourceInformationForAddress(pc_val
) + "\n"
1027 previous_frame_ptr
= frame_ptr
1028 frame_val
= kern
.GetValueFromAddress((frame_ptr
), 'uintptr_t *')
1029 if unsigned(frame_val
) == 0:
1031 frame_ptr
= unsigned(dereference(frame_val
))
1035 @lldb_command('fullbt')
1036 def FullBackTrace(cmd_args
=[]):
1037 """ Show full backtrace across the interrupt boundary.
1038 Syntax: fullbt <frame ptr>
1039 Example: fullbt `$rbp`
1041 if len(cmd_args
) < 1:
1042 print FullBackTrace
.__doc
__
1044 print GetFullBackTrace(ArgumentStringToInt(cmd_args
[0]), prefix
="\t")
1046 @lldb_command('fullbtall')
1047 def FullBackTraceAll(cmd_args
=[]):
1048 """ Show full backtrace across the interrupt boundary for threads running on all processors.
1052 for processor
in IterateLinkedList(kern
.globals.processor_list
, 'processor_list') :
1053 print "\n" + GetProcessorSummary(processor
)
1054 active_thread
= processor
.active_thread
1055 if unsigned(active_thread
) != 0 :
1056 task_val
= active_thread
.task
1057 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1058 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1059 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1060 print "\t" + GetThreadSummary
.header
1061 print "\t" + GetThreadSummary(active_thread
)
1062 print "\tBacktrace:"
1064 ThreadVal
= GetLLDBThreadForKernelThread(active_thread
)
1066 FramePtr
= ThreadVal
.frames
[0].GetFP()
1068 print GetFullBackTrace(unsigned(FramePtr
), prefix
="\t")
1071 @lldb_command('symbolicate')
1072 def SymbolicateAddress(cmd_args
=[]):
1073 """ Symbolicate an address for symbol information from loaded symbols
1074 Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr"
1076 if len(cmd_args
) < 1:
1077 print "Invalid address.\nSyntax: symbolicate <address>"
1079 print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args
[0]))
1082 @lldb_command('showinitchild')
1083 def ShowInitChild(cmd_args
=None):
1084 """ Routine to print out all processes in the system
1085 which are children of init process
1087 headp
= kern
.globals.initproc
.p_children
1088 for pp
in IterateListEntry(headp
, 'struct proc *', 'p_sibling'):
1089 print GetProcInfo(pp
)
1092 @lldb_command('showproctree')
1093 def ShowProcTree(cmd_args
=None):
1094 """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes.
1095 If no argument is given, showproctree will print all the processes in the system.
1096 If pid is specified, showproctree prints all the descendants of the indicated process
1100 search_pid
= ArgumentStringToInt(cmd_args
[0])
1103 print "pid specified must be a positive number"
1104 print ShowProcTree
.__doc
__
1107 hdr_format
= "{0: <6s} {1: <14s} {2: <9s}\n"
1108 out_string
= hdr_format
.format("PID", "PROCESS", "POINTER")
1109 out_string
+= hdr_format
.format('='*3, '='*7, '='*7)
1110 proc
= GetProcForPid(search_pid
)
1111 out_string
+= "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc
.p_ppid
, proc
.p_pptr
.p_comm
, unsigned(proc
.p_pptr
))
1112 out_string
+= "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc
.p_pid
, proc
.p_comm
, unsigned(proc
))
1114 ShowProcTreeRecurse(proc
, "| ")
1118 def ShowProcTreeRecurse(proc
, prefix
=""):
1119 """ Prints descendants of a given proc in hierarchial tree form
1121 proc : core.value representing a struct proc * in the kernel
1123 str : String containing info about a given proc and its descendants in tree form
1125 if proc
.p_childrencnt
> 0:
1126 head_ptr
= proc
.p_children
.lh_first
1128 for p
in IterateListEntry(proc
.p_children
, 'struct proc *', 'p_sibling'):
1129 print prefix
+ "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p
.p_pid
, p
.p_comm
, unsigned(p
))
1130 ShowProcTreeRecurse(p
, prefix
+ "| ")
1132 @lldb_command('showthreadfortid')
1133 def ShowThreadForTid(cmd_args
=None):
1134 """ The thread structure contains a unique thread_id value for each thread.
1135 This command is used to retrieve the address of the thread structure(thread_t)
1136 corresponding to a given thread_id.
1139 print "Please provide thread_t whose tid you'd like to look up"
1140 print ShowThreadForTid
.__doc
__
1142 search_tid
= ArgumentStringToInt(cmd_args
[0])
1143 for taskp
in kern
.tasks
:
1144 for actp
in IterateQueue(taskp
.threads
, 'struct thread *', 'task_threads'):
1145 if search_tid
== int(actp
.thread_id
):
1146 print "Found {0: #019x}".format(actp
)
1147 print GetThreadSummary
.header
1148 print GetThreadSummary(actp
)
1150 print "Not a valid thread_id"
1152 # Macro: showallprocessors
1154 def GetProcessorSummary(processor
):
1155 """ Internal function to print summary of processor
1156 params: processor - value representing struct processor *
1157 return: str - representing the details of given processor
1160 processor_state_str
= "INVALID"
1161 processor_state
= int(processor
.state
)
1163 processor_states
= {
1167 # 3 (formerly INACTIVE)
1173 if processor_state
in processor_states
:
1174 processor_state_str
= "{0: <11s} ".format(processor_states
[processor_state
])
1176 out_str
= "Processor {: <#018x} cpu_id {:>#4x} State {:<s}\n".format(processor
, int(processor
.cpu_id
), processor_state_str
)
1179 def GetGroupSetSummary(runq
, task_map
):
1180 """ Internal function to print summary of group run queue
1181 params: runq - value representing struct run_queue *
1182 return: str - representing the details of given run_queue
1184 out_str
= " runq: count {: <10d} highq: {: <10d} urgency {: <10d}\n".format(runq
.count
, runq
.highq
, runq
.urgency
)
1187 runq_queue_count
= sizeof(runq
.queues
)/sizeof(runq
.queues
[0])
1189 for runq_queue_i
in range(runq_queue_count
) :
1190 runq_queue_head
= addressof(runq
.queues
[runq_queue_i
])
1191 runq_queue_p
= runq_queue_head
.next
1193 if unsigned(runq_queue_p
) != unsigned(runq_queue_head
):
1194 runq_queue_this_count
= 0
1196 for entry
in IterateQueue(runq_queue_head
, "sched_entry_t", "links"):
1197 runq_queue_this_count
+= 1
1199 out_str
+= " Queue [{: <#012x}] Priority {: <3d} count {:d}\n".format(runq_queue_head
, runq_queue_i
, runq_queue_this_count
)
1200 for entry
in IterateQueue(runq_queue_head
, "sched_entry_t", "links"):
1202 task
= task_map
.get(unsigned(group
), "Unknown task!")
1203 out_str
+= "\tEntry [{: <#012x}] Priority {: <3d} Group {: <#012x} Task {: <#012x}\n".format(unsigned(entry
), entry
.sched_pri
, unsigned(entry
.group
), unsigned(task
))
1207 @lldb_command('showrunq')
1208 def ShowRunq(cmd_args
=None):
1209 """ Routine to print information of a runq
1210 Usage: showrunq <runq>
1213 runq
= kern
.GetValueFromAddress(cmd_args
[0], 'struct run_queue *')
1214 out_str
+= GetRunQSummary(runq
)
1217 def GetRunQSummary(runq
):
1218 """ Internal function to print summary of run_queue
1219 params: runq - value representing struct run_queue *
1220 return: str - representing the details of given run_queue
1222 out_str
= " runq: count {: <10d} highq: {: <10d} urgency {: <10d}\n".format(runq
.count
, runq
.highq
, runq
.urgency
)
1225 runq_queue_count
= sizeof(runq
.queues
)/sizeof(runq
.queues
[0])
1227 for runq_queue_i
in range(runq_queue_count
) :
1228 runq_queue_head
= addressof(runq
.queues
[runq_queue_i
])
1229 runq_queue_p
= runq_queue_head
.next
1231 if unsigned(runq_queue_p
) != unsigned(runq_queue_head
):
1232 runq_queue_this_count
= 0
1234 for thread
in IterateQueue(runq_queue_head
, "thread_t", "links"):
1235 runq_queue_this_count
+= 1
1237 out_str
+= " Queue [{: <#012x}] Priority {: <3d} count {:d}\n".format(runq_queue_head
, runq_queue_i
, runq_queue_this_count
)
1238 out_str
+= "\t" + GetThreadSummary
.header
+ "\n"
1239 for thread
in IterateQueue(runq_queue_head
, "thread_t", "links"):
1240 out_str
+= "\t" + GetThreadSummary(thread
) + "\n"
1241 if config
['verbosity'] > vHUMAN
:
1242 out_str
+= "\t" + GetThreadBackTrace(thread
, prefix
="\t\t") + "\n"
1246 def GetGrrrSummary(grrr_runq
):
1247 """ Internal function to print summary of grrr_run_queue
1248 params: grrr_runq - value representing struct grrr_run_queue *
1249 return: str - representing the details of given grrr_run_queue
1251 out_str
= " GRRR Info: Count {: <10d} Weight {: <10d} Current Group {: <#012x}\n".format(grrr_runq
.count
,
1252 grrr_runq
.weight
, grrr_runq
.current_group
)
1254 grrr_group_count
= sizeof(grrr_runq
.groups
)/sizeof(grrr_runq
.groups
[0])
1255 for grrr_group_i
in range(grrr_group_count
) :
1256 grrr_group
= addressof(grrr_runq
.groups
[grrr_group_i
])
1257 if grrr_group
.count
> 0:
1258 out_str
+= " Group {: <3d} [{: <#012x}] ".format(grrr_group
.index
, grrr_group
)
1259 out_str
+= "Count {:d} Weight {:d}\n".format(grrr_group
.count
, grrr_group
.weight
)
1260 grrr_group_client_head
= addressof(grrr_group
.clients
)
1261 out_str
+= GetThreadSummary
.header
1262 for thread
in IterateQueue(grrr_group_client_head
, "thread_t", "links"):
1263 out_str
+= "\t" + GetThreadSummary(thread
) + "\n"
1264 if config
['verbosity'] > vHUMAN
:
1265 out_str
+= "\t" + GetThreadBackTrace(thread
, prefix
="\t\t") + "\n"
1268 @lldb_command('showallprocessors')
1269 def ShowAllProcessors(cmd_args
=None):
1270 """ Routine to print information of all psets and processors
1271 Usage: showallprocessors
1273 pset
= addressof(kern
.globals.pset0
)
1275 show_priority_runq
= 0
1276 show_priority_pset_runq
= 0
1277 show_group_pset_runq
= 0
1278 show_fairshare_grrr
= 0
1279 show_fairshare_list
= 0
1280 sched_enum_val
= kern
.globals._sched
_enum
1282 if sched_enum_val
== 1:
1283 show_priority_runq
= 1
1284 show_fairshare_list
= 1
1285 elif sched_enum_val
== 2:
1286 show_priority_pset_runq
= 1
1287 show_fairshare_list
= 1
1288 elif sched_enum_val
== 4:
1290 show_fairshare_grrr
= 1
1291 elif sched_enum_val
== 5:
1292 show_priority_runq
= 1
1293 show_group_pset_runq
= 1
1294 show_fairshare_list
= 1
1295 elif sched_enum_val
== 6:
1296 show_priority_pset_runq
= 1
1297 show_priority_runq
= 1
1298 show_fairshare_list
= 1
1302 out_str
+= "Scheduler: {:s} ({:s}, {:d})\n".format(kern
.globals.sched_string
,
1303 kern
.Symbolicate(unsigned(kern
.globals.sched_current_dispatch
)),
1306 out_str
+= "Runnable threads: {:d} Timeshare threads: {:d} Background threads {:d}\n".format(
1307 kern
.globals.sched_run_count
, kern
.globals.sched_share_count
, kern
.globals.sched_background_count
)
1309 if show_group_pset_runq
:
1310 # Create a group->task mapping
1312 for task
in kern
.tasks
:
1313 task_map
[unsigned(task
.sched_group
)] = task
1314 for task
in kern
.terminated_tasks
:
1315 task_map
[unsigned(task
.sched_group
)] = task
1317 while unsigned(pset
) != 0:
1318 out_str
+= "Processor Set {: <#012x} Count {:d} (cpu_id {:<#x}-{:<#x})\n".format(pset
,
1319 pset
.cpu_set_count
, pset
.cpu_set_low
, pset
.cpu_set_hi
)
1321 if show_priority_pset_runq
:
1322 runq
= pset
.pset_runq
1323 out_str
+= GetRunQSummary(runq
)
1325 if show_group_pset_runq
:
1326 out_str
+= "Main Runq:\n"
1327 runq
= pset
.pset_runq
1328 out_str
+= GetGroupSetSummary(runq
, task_map
)
1329 out_str
+= "All Groups:\n"
1330 # TODO: Possibly output task header for each group
1331 for group
in IterateQueue(kern
.globals.sched_groups
, "sched_group_t", "sched_groups"):
1332 if (group
.runq
.count
!= 0) :
1333 task
= task_map
.get(unsigned(group
), "Unknown task!")
1334 out_str
+= "Group {: <#012x} Task {: <#012x}\n".format(unsigned(group
), unsigned(task
))
1335 out_str
+= GetRunQSummary(group
.runq
)
1337 out_str
+= " Active Processors:\n"
1338 for processor
in IterateQueue(pset
.active_queue
, "processor_t", "processor_queue"):
1340 out_str
+= GetProcessorSummary(processor
)
1341 if show_priority_runq
:
1342 runq
= processor
.runq
1343 out_str
+= GetRunQSummary(runq
)
1345 grrr_runq
= processor
.grrr_runq
1346 out_str
+= GetGrrrSummary(grrr_runq
)
1348 out_str
+= " Idle Processors:\n"
1349 for processor
in IterateQueue(pset
.idle_queue
, "processor_t", "processor_queue"):
1350 out_str
+= " " + GetProcessorSummary(processor
)
1351 if show_priority_runq
:
1352 out_str
+= GetRunQSummary(processor
.runq
)
1354 out_str
+= " Idle Secondary Processors:\n"
1355 for processor
in IterateQueue(pset
.idle_secondary_queue
, "processor_t", "processor_queue"):
1356 out_str
+= " " + GetProcessorSummary(processor
)
1357 if show_priority_runq
:
1358 out_str
+= GetRunQSummary(processor
.runq
)
1360 pset
= pset
.pset_list
1362 out_str
+= "\nRealtime Queue Count {:d}\n".format(kern
.globals.rt_runq
.count
)
1363 for rt_runq_thread
in IterateQueue(kern
.globals.rt_runq
.queue
, "thread_t", "links"):
1364 out_str
+= ShowTask([unsigned(rt_runq_thread
.task
)])
1365 out_str
+= ShowAct([unsigned(rt_runq_thread
)])
1368 if show_fairshare_list
:
1369 out_str
+= "Fair Share Queue Count {:d}\n".format(kern
.globals.fs_runq
.count
)
1370 for fs_runq_thread
in IterateQueue(kern
.globals.fs_runq
.queue
, "thread_t", "links"):
1371 out_str
+= ShowTask([unsigned(fs_runq_thread
.task
)])
1372 out_str
+= ShowAct([unsigned(rt_runq_thread
)])
1373 if show_fairshare_grrr
:
1374 out_str
+= "Fair Share Queue Count {:d}\n".format(kern
.globals.fs_grrr_runq
.count
)
1375 fs_grrr
= addressof(kern
.globals.fs_grrr_runq
)
1376 out_str
+= GetGrrrSummary(fs_grrr
)
1379 # EndMacro: showallprocessors
1381 def GetLedgerEntrySummary(ledger_template
, ledger
, i
):
1382 """ Internal function to get internals of a ledger entry (*not* a ledger itself)
1383 params: ledger_template - value representing struct ledger_template_t for the task or thread
1384 ledger - value representing struct ledger_entry *
1385 return: str - formatted output information of ledger entries
1387 ledger_limit_infinity
= (uint64_t(0x1).value
<< 63) - 1
1388 lf_refill_scheduled
= 0x0400
1389 lf_tracking_max
= 0x4000
1392 now
= unsigned(kern
.globals.sched_tick
) / 20
1395 out_str
+= "{: >32s} {:<2d}:".format(ledger_template
.lt_entries
[i
].et_key
, i
)
1396 out_str
+= "{: >15d} ".format(unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
))
1397 if (ledger
.le_flags
& lf_tracking_max
):
1398 out_str
+= "{:9d} {:5d} ".format(ledger
._le
.le_peaks
[0].le_max
, now
- unsigned(ledger
._le
.le_peaks
[0].le_time
))
1399 out_str
+= "{:9d} {:4d} ".format(ledger
._le
.le_peaks
[1].le_max
, now
- unsigned(ledger
._le
.le_peaks
[1].le_time
))
1401 out_str
+= " - - - - "
1403 out_str
+= "{:12d} {:12d} ".format(unsigned(ledger
.le_credit
), unsigned(ledger
.le_debit
))
1404 if (unsigned(ledger
.le_limit
) != ledger_limit_infinity
):
1405 out_str
+= "{:12d} ".format(unsigned(ledger
.le_limit
))
1409 if (ledger
.le_flags
& lf_refill_scheduled
):
1410 out_str
+= "{:15d} ".format(ledger
._le
.le_refill
.le_refill_period
)
1414 if (ledger
.le_flags
& lf_refill_scheduled
):
1415 out_str
+= "{:9d} ".format((unsigned(ledger
.le_limit
) * 100) / ledger
._le
.le_refill
.le_refill_period
)
1419 if (unsigned(ledger
.le_warn_level
) != ledger_limit_infinity
):
1420 out_str
+= "{:9d} ".format((unsigned(ledger
.le_warn_level
) * 100) / unsigned(ledger
.le_limit
))
1424 if ((unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
)) > unsigned(ledger
.le_limit
)):
1429 out_str
+= "{:#8x}\n".format(ledger
.le_flags
)
1432 def GetThreadLedgerSummary(thread_val
):
1433 """ Internal function to get a summary of ledger entries for the given thread
1434 params: thread - value representing struct thread *
1435 return: str - formatted output information for ledger entries of the input thread
1437 out_str
= " [{:#08x}]\n".format(thread_val
)
1438 ledgerp
= thread_val
.t_threadledger
1441 while i
!= ledgerp
.l_template
.lt_cnt
:
1442 out_str
+= GetLedgerEntrySummary(kern
.globals.thread_ledger_template
,
1443 ledgerp
.l_entries
[i
], i
)
1447 @header("{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >9s} {5: >6s} {6: >8s} {7: <10s} {8: <9s} \
1448 {9: <12s} {10: <7s} {11: <15s} {12: <8s} {13: <9s} {14: <6s} {15: >6s}".format(
1449 "task [thread]", "entry", "#", "balance", "peakA", "(age)", "peakB", "(age)", "credit",
1450 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags"))
1451 def GetTaskLedgers(task_val
):
1452 """ Internal function to get summary of ledger entries from the task and its threads
1453 params: task_val - value representing struct task *
1454 return: str - formatted output information for ledger entries of the input task
1457 task_ledgerp
= task_val
.ledger
1459 out_str
+= "{: #08x} ".format(task_val
)
1460 pval
= Cast(task_val
.bsd_info
, 'proc *')
1462 out_str
+= "{: <5s}:\n".format(pval
.p_comm
)
1464 out_str
+= "Invalid process:\n"
1465 while i
!= task_ledgerp
.l_template
.lt_cnt
:
1466 out_str
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, task_ledgerp
.l_entries
[i
], i
)
1470 for thval
in IterateQueue(task_val
.threads
, 'thread *', 'task_threads'):
1471 out_str
+= GetThreadLedgerSummary(thval
)
1475 # Macro: showtaskledgers
1477 @lldb_command('showtaskledgers', 'F:')
1478 def ShowTaskLedgers(cmd_args
=None, cmd_options
={}):
1479 """ Routine to print a summary of ledger entries for the task and all of its threads
1480 Usage: showtaskledgers <address of task>
1481 or : showtaskledgers -F <name of task>
1483 if "-F" in cmd_options
:
1484 task_list
= FindTasksByName(cmd_options
["-F"])
1485 for tval
in task_list
:
1486 print GetTaskLedgers
.header
1487 print GetTaskLedgers(tval
)
1491 raise ArgumentError("No arguments passed.")
1492 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1494 raise ArgumentError("unknown arguments: %r" %cmd
_args
)
1495 print GetTaskLedgers
.header
1496 print GetTaskLedgers(tval
)
1498 # EndMacro: showtaskledgers
1500 # Macro: showalltaskledgers
1502 @lldb_command('showalltaskledgers')
1503 def ShowAllTaskLedgers(cmd_args
=None):
1504 """ Routine to print a summary of ledger entries for all tasks and respective threads
1505 Usage: showalltaskledgers
1507 for t
in kern
.tasks
:
1508 task_val
= unsigned(t
)
1509 ShowTaskLedgers([task_val
])
1511 # EndMacro: showalltaskledgers
1513 # Macro: showprocuuidpolicytable
1515 @lldb_type_summary(['proc_uuid_policy_entry'])
1516 @header("{0: <36s} {1: <10s}".format("uuid", "flags"))
1517 def GetProcUUIDPolicyEntrySummary(entry
):
1518 """ Summarizes the important fields in proc_uuid_policy_entry structure.
1519 params: entry: value - value object representing an entry
1520 returns: str - summary of the entry
1524 data
.append(int(entry
.uuid
[i
]))
1525 flags
= unsigned(entry
.flags
)
1526 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
)
1529 @lldb_command('showprocuuidpolicytable')
1530 def ShowProcUUIDPolicyTable(cmd_args
=None):
1531 """ Routine to print the proc UUID policy table
1532 Usage: showprocuuidpolicytable
1534 hashslots
= unsigned(kern
.globals.proc_uuid_policy_hash_mask
)
1535 print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary
.header
1536 for i
in range(0, hashslots
+1):
1537 headp
= addressof(kern
.globals.proc_uuid_policy_hashtbl
[i
])
1539 for entry
in IterateListEntry(headp
, 'struct proc_uuid_policy_entry *', 'entries'):
1540 print "{0: >2d}.{1: <5d} ".format(i
, entrynum
) + GetProcUUIDPolicyEntrySummary(entry
)
1544 # EndMacro: showprocuuidpolicytable
1546 @lldb_command('showalltaskpolicy')
1547 def ShowAllTaskPolicy(cmd_args
=None):
1549 Routine to print a summary listing of all the tasks
1550 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1551 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1552 io_policy -> RAGE - rapid aging of vnodes requested
1553 NORM - normal I/O explicitly requested (this is the default)
1554 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1555 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1558 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1559 for t
in kern
.tasks
:
1560 pval
= Cast(t
.bsd_info
, 'proc *')
1561 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1562 requested_strings
= [
1563 ["int_darwinbg", "DBG-int"],
1564 ["ext_darwinbg", "DBG-ext"],
1565 ["int_iotier", "iotier-int"],
1566 ["ext_iotier", "iotier-ext"],
1567 ["int_iopassive", "passive-int"],
1568 ["ext_iopassive", "passive-ext"],
1569 ["bg_iotier", "bg-iotier"],
1570 ["terminated", "terminated"],
1571 ["th_pidbind_bg", "bg-pidbind"],
1572 ["th_workq_bg", "bg-workq"],
1573 ["t_apptype", "apptype"],
1574 ["t_boosted", "boosted"],
1575 ["t_int_gpu_deny", "gpudeny-int"],
1576 ["t_ext_gpu_deny", "gpudeny-ext"],
1578 ["t_tal_enabled", "tal-enabled"],
1579 ["t_base_latency_qos", "latency-base"],
1580 ["t_over_latency_qos", "latency-override"],
1581 ["t_base_through_qos", "throughput-base"],
1582 ["t_over_through_qos", "throughput-override"]
1586 for value
in requested_strings
:
1587 if t
.requested_policy
.__getattr
__(value
[0]) :
1588 requested
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1592 suppression_strings
= [
1593 ["t_sup_active", "active"],
1594 ["t_sup_lowpri_cpu", "lowpri-cpu"],
1595 ["t_sup_timer", "timer-throttling"],
1596 ["t_sup_disk", "disk-throttling"],
1597 ["t_sup_cpu_limit", "cpu-limits"],
1598 ["t_sup_suspend", "suspend"],
1599 ["t_sup_bg_sockets", "bg-sockets"]
1603 for value
in suppression_strings
:
1604 if t
.requested_policy
.__getattr
__(value
[0]) :
1605 suppression
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1609 effective_strings
= [
1610 ["darwinbg", "background"],
1611 ["lowpri_cpu", "lowpri-cpu"],
1612 ["io_tier", "iotier"],
1613 ["io_passive", "passive"],
1614 ["all_sockets_bg", "bg-allsockets"],
1615 ["new_sockets_bg", "bg-newsockets"],
1616 ["bg_iotier", "bg-iotier"],
1617 ["terminated", "terminated"],
1618 ["t_gpu_deny", "gpu-deny"],
1619 ["t_tal_engaged", "tal-engaged"],
1620 ["t_suspended", "suspended"],
1621 ["t_watchers_bg", "bg-watchers"],
1622 ["t_latency_qos", "latency-qos"],
1623 ["t_through_qos", "throughput-qos"],
1624 ["t_sup_active", "suppression-active"],
1629 for value
in effective_strings
:
1630 if t
.effective_policy
.__getattr
__(value
[0]) :
1631 effective
+=value
[1] + ": " + str(t
.effective_policy
.__getattr
__(value
[0])) + " "
1637 ["t_updating_policy", "updating"],
1638 ["update_sockets", "update_sockets"],
1639 ["t_update_timers", "update_timers"],
1640 ["t_update_watchers", "update_watchers"]
1644 for value
in pended_strings
:
1645 if t
.pended_policy
.__getattr
__(value
[0]) :
1646 pended
+=value
[1] + ": " + str(t
.pended_policy
.__getattr
__(value
[0])) + " "
1650 print "requested: " + requested
1651 print "suppression: " + suppression
1652 print "effective: " + effective
1653 print "pended: " + pended
1656 @lldb_type_summary(['wait_queue', 'wait_queue_t'])
1657 @header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask"))
1658 def GetWaitQSummary(waitq
):
1659 """ Summarizes the important fields in task structure.
1660 params: task: value - value object representing a task in kernel
1661 returns: str - summary of the task
1664 format_string
= '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
1668 if (waitq
.wq_fifo
== 1) :
1673 if (waitq
.wq_prepost
== 1) :
1676 if (waitq
.wq_type
== 0x3) :
1678 elif (waitq
.wq_type
== 0x2) :
1683 out_string
+= format_string
.format(waitq
, unsigned(waitq
.wq_interlock
.lock_data
), policy
, 0, 0, unsigned(waitq
.wq_eventmask
))
1685 out_string
+= "\n" + GetThreadSummary
.header
1687 for thread
in IterateQueue(waitq
.wq_queue
, "thread_t", "links"):
1688 out_string
+= "\n" + GetThreadSummary(thread
)
1693 @lldb_command('showallsuspendedtasks', '')
1694 def ShowSuspendedTasks(cmd_args
=[], options
={}):
1695 """ Show a list of suspended tasks with their process name summary.
1697 print GetTaskSummary
.header
+ ' ' + GetProcSummary
.header
1698 for t
in kern
.tasks
:
1699 if t
.suspend_count
> 0:
1700 print GetTaskSummary(t
) + ' ' + GetProcSummary(Cast(t
.bsd_info
, 'proc *'))