]> git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/process.py
40f8cfedbd195ab93bce0942825d3740f169d90c
[apple/xnu.git] / tools / lldbmacros / process.py
1
2 """ Please make sure you read the README file COMPLETELY BEFORE reading anything below.
3 It is very critical that you read coding guidelines in Section E in README file.
4 """
5
6 from xnu import *
7 import sys, shlex
8 from utils import *
9 from core.lazytarget import *
10 import xnudefines
11
12 def GetProcNameForTask(task):
13 """ returns a string name of the process. if proc is not valid "unknown" is returned
14 params:
15 task: value object represeting a task in the kernel.
16 returns:
17 str : A string name of the process linked to the task
18 """
19 if not task or not unsigned(task.bsd_info):
20 return "unknown"
21 p = Cast(task.bsd_info, 'proc *')
22 return str(p.p_comm)
23
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.
26 params:
27 task: value object representing a task in the kernel
28 returns:
29 int : pid of the process or -1 if not found
30 """
31 if task and unsigned(task.bsd_info):
32 p = Cast(task.bsd_info, 'proc *')
33 return unsigned(p.p_pid)
34
35 if task :
36 return unsigned(task.audit_token.val[5])
37
38 return -1
39
40 def GetProcInfo(proc):
41 """ returns a string name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields.
42 params:
43 proc : value object representing a proc in the kernel
44 returns:
45 str : A string describing various information for process.
46 """
47 out_string = ""
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"
50 ).format(p=proc)
51 #print the Creds
52 ucred = proc.p_ucred
53 if ucred:
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 )
57 #print the flags
58 flags = int(proc.p_flag)
59 out_string += "Flags: {0: <#020x}\n".format(flags)
60 i = 1
61 num = 1
62 while num <= flags:
63 if flags & num:
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"
67 i += 1
68 num = num << 1
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)"
73 else:
74 out_string += xnudefines.proc_state_strings[int(state_val)]
75
76 return out_string
77
78 def GetProcNameForPid(pid):
79 """ Finds the name of the process corresponding to a given pid
80 params:
81 pid : int, pid you want to find the procname for
82 returns
83 str : Name of the process corresponding to the pid, "Unknown" if not found
84 """
85 for p in kern.procs:
86 if int(p.p_pid) == int(pid):
87 return str(p.p_comm)
88 return "Unknown"
89
90 def GetProcForPid(search_pid):
91 """ Finds the value object representing a proc in the kernel based on its pid
92 params:
93 search_pid : int, pid whose proc structure you want to find
94 returns:
95 value : The value object representing the proc, if a proc corresponding
96 to the given pid is found. Returns None otherwise
97 """
98 if search_pid == 0:
99 return kern.globals.initproc
100 else:
101 headp = kern.globals.allproc
102 for proc in IterateListEntry(headp, 'struct proc *', 'p_list'):
103 if proc.p_pid == search_pid:
104 return proc
105 return None
106
107 @lldb_command('allproc')
108 def AllProc(cmd_args=None):
109 """ Walk through the allproc structure and print procinfo for each process structure.
110 params:
111 cmd_args - [] : array of strings passed from lldb command prompt
112 """
113 for proc in kern.procs :
114 print GetProcInfo(proc)
115
116
117 @lldb_command('zombproc')
118 def ZombProc(cmd_args=None):
119 """ Routine to print out all procs in the zombie list
120 params:
121 cmd_args - [] : array of strings passed from lldb command prompt
122 """
123 if len(kern.zombprocs) != 0:
124 print "\nZombie Processes:"
125 for proc in kern.zombprocs:
126 print GetProcInfo(proc) + "\n\n"
127
128 @lldb_command('zombtasks')
129 def ZombTasks(cmd_args=None):
130 """ Routine to print out all tasks in the zombie list
131 params: None
132 """
133 out_str = ""
134 if len(kern.zombprocs) != 0:
135 header = "\nZombie Tasks:\n"
136 header += GetTaskSummary.header + " " + GetProcSummary.header
137 for proc in kern.zombprocs:
138 if proc.p_stat != 5:
139 t = Cast(proc.task, 'task *')
140 out_str += GetTaskSummary(t) +" "+ GetProcSummary(proc) + "\n"
141 if out_str != "":
142 print header
143 print out_str
144
145 @lldb_command('zombstacks')
146 def ZombStacks(cmd_args=None):
147 """ Routine to print out all stacks of tasks that are exiting
148 """
149 header_flag = 0
150 for proc in kern.zombprocs:
151 if proc.p_stat != 5:
152 if header_flag == 0:
153 print "\nZombie Stacks:"
154 header_flag = 1
155 t = Cast(proc.task, 'task *')
156 ShowTaskStacks(t)
157 #End of Zombstacks
158
159 def GetASTSummary(ast):
160 """ Summarizes an AST field
161 Flags:
162 P - AST_PREEMPT
163 Q - AST_QUANTUM
164 U - AST_URGENT
165 H - AST_HANDOFF
166 Y - AST_YIELD
167 A - AST_APC
168 L - AST_LEDGER
169 B - AST_BSD
170 K - AST_KPERF
171 M - AST_MACF
172 C - AST_CHUD
173 C - AST_CHUD_URGENT
174 G - AST_GUARD
175 T - AST_TELEMETRY_USER
176 T - AST_TELEMETRY_KERNEL
177 T - AST_TELEMETRY_WINDOWED
178 S - AST_SFI
179 """
180 out_string = ""
181 state = int(ast)
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'}
185 state_str = ''
186 mask = 0x1
187 while mask <= 0x10000 :
188 state_str += thread_state_chars[int(state & mask)]
189 mask = mask << 1
190
191 return state_str
192
193
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
200 """
201 out_string = ""
202 format_string = '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}'
203 thread_count = int(task.thread_count)
204 task_flags = ''
205 if hasattr(task, "suppression_generation") and (int(task.suppression_generation) & 0x1) == 0x1:
206 task_flags += 'P'
207 if hasattr(task, "suspend_count") and int(task.suspend_count) > 0:
208 task_flags += 'S'
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:
212 task_flags += 'R'
213 if int(tib.iit_donor) == 1:
214 task_flags += 'D'
215 if int(tib.iit_assertcnt) > 0:
216 task_flags += 'B'
217 out_string += format_string.format(task, task.map, task.itk_space, thread_count, task_flags)
218 return out_string
219
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
226
227 State flags:
228 W - WAIT
229 S - SUSP
230 R - RUN
231 U - Uninterruptible
232 H - Terminated
233 A - Terminated and on termination queue
234 I - Idle thread
235
236 policy flags:
237 B - darwinbg
238 L - lowpri cpu
239 T - IO throttle
240 P - IO passive
241 D - Terminated
242 """
243 out_string = ""
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)
249 thread_name = ''
250 processor = hex(thread.last_processor)
251 base_priority = str(int(thread.priority))
252 sched_priority = str(int(thread.sched_pri))
253 sched_mode = ''
254 mode = str(thread.sched_mode)
255 if "TIMESHARE" in mode:
256 sched_mode+="timeshare"
257 elif "FIXED" in mode:
258 sched_mode+="fixed"
259 elif "REALTIME" in mode:
260 sched_mode+="realtime"
261
262 if (unsigned(thread.bound_processor) != 0):
263 sched_mode+=" bound"
264
265 # TH_SFLAG_THROTTLED
266 if (unsigned(thread.sched_flags) & 0x0004):
267 sched_mode+=" BG"
268
269 io_policy_str = ""
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)
277
278 #check for io_policy flags
279 if int(uthread.uu_flag) & 0x400:
280 io_policy_str+='RAGE '
281
282 #now flags for task_policy
283
284 io_policy_str = ""
285
286 if int(thread.effective_policy.darwinbg) != 0:
287 io_policy_str += "B"
288 if int(thread.effective_policy.lowpri_cpu) != 0:
289 io_policy_str += "L"
290
291 if int(thread.effective_policy.io_tier) != 0:
292 io_policy_str += "T"
293 if int(thread.effective_policy.io_passive) != 0:
294 io_policy_str += "P"
295 if int(thread.effective_policy.terminated) != 0:
296 io_policy_str += "D"
297
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'}
300 state_str = ''
301 mask = 0x1
302 while mask <= 0x80 :
303 state_str += thread_state_chars[int(state & mask)]
304 mask = mask << 1
305
306 ast = int(thread.ast) | int(thread.reason)
307 ast_str = GetASTSummary(ast)
308
309 #wait queue information
310 wait_queue_str = ''
311 wait_event_str = ''
312 wait_message = ''
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 *'))
324
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)
326 return out_string
327
328
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):
332 out_string = ""
333 format_string = '{:>#018x} {:>10d} {:>8d} {:>8d} {:>8d} {:>8d}'
334
335 flags_string = ''
336 if (coal.terminated):
337 flags_string += ' terminated'
338 if (coal.reaped):
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)
341
342 return out_string
343
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.
348 params:
349 proc : value - value representaitng a proc * in kernel
350 returns:
351 str - string summary of the process.
352 """
353 out_string = ""
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))
359 if not proc:
360 out_string += "Process " + hex(proc) + " is not valid."
361 return out_string
362 pid = int(proc.p_pid)
363 proc_addr = int(hex(proc), 16)
364 proc_rage_str = ""
365 if int(proc.p_lflag) & 0x400000 :
366 proc_rage_str = "RAGE"
367
368 task = Cast(proc.task, 'task *')
369
370 io_policy_str = ""
371
372 if int(task.effective_policy.darwinbg) != 0:
373 io_policy_str += "B"
374 if int(task.effective_policy.lowpri_cpu) != 0:
375 io_policy_str += "L"
376
377 if int(task.effective_policy.io_tier) != 0:
378 io_policy_str += "T"
379 if int(task.effective_policy.io_passive) != 0:
380 io_policy_str += "P"
381 if int(task.effective_policy.terminated) != 0:
382 io_policy_str += "D"
383
384 if int(task.effective_policy.t_suspended) != 0:
385 io_policy_str += "S"
386 if int(task.effective_policy.t_latency_qos) != 0:
387 io_policy_str += "Q"
388 if int(task.effective_policy.t_sup_active) != 0:
389 io_policy_str += "A"
390
391
392 try:
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)
398 else:
399 wq_num_threads = 0
400 wq_idle_threads = 0
401 wq_req_threads = 0
402 except:
403 wq_num_threads = -1
404 wq_idle_threads = -1
405 wq_req_threads = -1
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)
408 return out_string
409
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
416 """
417 out_string = ""
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)
424 return out_string
425
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
431 """
432 out_string = ""
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)
435 state_str = ''
436 mask = 0x1
437 while mask <= 0x80 :
438 if int(state & mask):
439 state_str += ' ' + xnudefines.kq_state_strings[int(state & mask)]
440 mask = mask << 1
441 out_string += format_string.format(o=kq, st_str=state_str)
442 return out_string
443
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
449 """
450 out_string = ""
451 format_string = "{o: <#020x}"
452 out_string += format_string.format(o=kn)
453 return out_string
454
455 # Macro: showtask
456
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>
462 """
463 task_list = []
464 if "-F" in cmd_options:
465 task_list = FindTasksByName(cmd_options['-F'])
466 else:
467 if not cmd_args:
468 raise ArgumentError("Invalid arguments passed.")
469
470 tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
471 if not tval:
472 raise ("Unknown arguments: %r" % cmd_args)
473 task_list.append(tval)
474
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)
479
480 # EndMacro: showtask
481
482 # Macro: showpid
483
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>
488 """
489 if not cmd_args:
490 print "No arguments passed"
491 print ShowPid.__doc__
492 return False
493 pidval = ArgumentStringToInt(cmd_args[0])
494 for t in kern.tasks:
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)
499 break
500
501 # EndMacro: showpid
502
503 # Macro: showproc
504
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>
509 """
510 if not cmd_args:
511 print "No arguments passed"
512 print ShowProc.__doc__
513 return False
514 pval = kern.GetValueFromAddress(cmd_args[0], 'proc *')
515 if not pval:
516 print "unknown arguments:", str(cmd_args)
517 return False
518 print GetTaskSummary.header + " " + GetProcSummary.header
519 tval = Cast(pval.task, 'task *')
520 print GetTaskSummary(tval) +" "+ GetProcSummary(pval)
521
522 # EndMacro: showproc
523
524 # Macro: showprocinfo
525
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>
531 """
532 if not cmd_args:
533 print "No arguments passed"
534 print ShowProcInfo.__doc__
535 return False
536 pval = kern.GetValueFromAddress(cmd_args[0], 'proc *')
537 if not pval:
538 print "unknown arguments:", str(cmd_args)
539 return False
540 print GetProcInfo(pval)
541
542 # EndMacro: showprocinfo
543
544 #Macro: showprocfiles
545
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>
550 """
551 if not cmd_args:
552 print ShowProcFiles.__doc__
553 return
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])
560 return
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("")
563 count = 0
564
565 # Filetype map
566 filetype_dict = {
567 1: 'VNODE',
568 2: 'SOCKET',
569 3: 'PSXSHM',
570 4: 'PSXSEM',
571 5: 'KQUEUE',
572 6: 'PIPE',
573 7: 'FSEVENTS'
574 }
575
576 while count <= proc_lastfile:
577 if unsigned(proc_ofiles[count]) != 0:
578 out_str = ''
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])
587 else:
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)
593 out_str += "\n"
594 print out_str
595 count += 1
596
597 #EndMacro: showprocfiles
598
599 #Macro: showkqueue
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 *>
604 """
605 if not cmd_args:
606 raise ArgumentError('Invalid arguments')
607
608 kq = kern.GetValueFromAddress(cmd_args[0], 'struct kqueue *')
609 print GetKQueueSummary.header
610 print GetKQueueSummary(kq)
611
612 #EndMacro: showkqueue
613
614 #Macro: showtty
615
616 @lldb_command('showtty')
617 def ShowTTY(cmd_args=None):
618 """ Display information about a struct tty
619 Usage: showtty <tty struct>
620 """
621 if not cmd_args:
622 print ShowTTY.__doc__
623 return
624
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)
630 tty_state_info = [
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)']
655 ]
656 index = 0
657 mask = 0x1
658 tty_state = unsigned(tty.t_state)
659 print "State:"
660 while index < 24:
661 if tty_state & mask != 0:
662 if len(tty_state_info[index][1]) > 0:
663 print '\t' + tty_state_info[index][1]
664 else:
665 if len(tty_state_info[index][0]) > 0:
666 print '\t' + tty_state_info[index][0]
667 index += 1
668 mask = mask << 1
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))
672 print "Termios:"
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)
681
682 #EndMacro: showtty
683
684 #Macro showallttydevs
685
686 @lldb_command('showallttydevs')
687 def ShowAllTTYDevs(cmd_args=[], cmd_options={}):
688 """ Show a list of ttydevs registered in the system.
689 Usage:
690 (lldb)showallttydevs
691 """
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
698 return ""
699
700 #EndMacro: showallttydevs
701
702 #Macro: dumpcallqueue
703
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 *>
708 """
709 if not cmd_args:
710 print DumpCallQueue.__doc__
711 return
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 *')
714 count = 0
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))
719 count += 1
720 print "{0: <d} entries!".format(count)
721
722 #EndMacro: dumpcallqueue
723
724 @lldb_command('showallcoalitions')
725 def ShowAllCoalitions(cmd_args=None):
726 """ Routine to print a summary listing of all the coalitions
727 """
728 global kern
729
730 role_strs = {
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",
739 }
740
741 sfi_strs = {
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",
759 }
760
761
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)]
769
770
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)
780 """
781 global kern
782 print GetTaskSummary.header + " " + GetProcSummary.header
783 for t in kern.tasks:
784 pval = Cast(t.bsd_info, 'proc *')
785 print GetTaskSummary(t) +" "+ GetProcSummary(pval)
786 ZombTasks()
787
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
798 """
799 global kern
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)
804 return True
805
806 # Macro: showtaskstacks
807
808 def ShowTaskStacks(task):
809 """ Print a task with summary and stack information for each of its threads
810 """
811 global kern
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"
819
820 def FindTasksByName(searchstr, ignore_case=True):
821 """ Search the list of tasks by name.
822 params:
823 searchstr: str - a regex like string to search for task
824 ignore_case: bool - If False then exact matching will be enforced
825 returns:
826 [] - array of task object. Empty if not found any
827 """
828 re_options = 0
829 if ignore_case:
830 re_options = re.IGNORECASE
831 search_regex = re.compile(searchstr, re_options)
832 retval = []
833 for t in kern.tasks:
834 pval = Cast(t.bsd_info, "proc *")
835 process_name = "{:s}".format(pval.p_comm)
836 if search_regex.search(process_name):
837 retval.append(t)
838 return retval
839
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
845 """
846
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:
851 ShowTaskStacks(tval)
852 return
853
854 if not cmd_args:
855 raise ArgumentError("No arguments passed")
856
857 tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
858 if not tval:
859 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args)))
860 else:
861 ShowTaskStacks(tval)
862 return
863
864 # EndMacro: showtaskstacks
865
866 @lldb_command('showallthreads')
867 def ShowAllThreads(cmd_args = None):
868 """ Display info about all threads in the system
869 """
870 for t in kern.tasks:
871 ShowTaskThreads([str(int(t))])
872 print " \n"
873
874 for t in kern.terminated_tasks:
875 print "Terminated: \n"
876 ShowTaskThreads([str(int(t))])
877 print " \n"
878
879 return
880
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>
886 """
887 task_list = []
888 if "-F" in cmd_options:
889 task_list = FindTasksByName(cmd_options["-F"])
890 elif cmd_args:
891 t = kern.GetValueFromAddress(cmd_args[0], 'task *')
892 task_list.append(t)
893 else:
894 raise ArgumentError("No arguments passed")
895
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)
903 return
904
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>
909 """
910 if cmd_args == None or len(cmd_args) < 1:
911 print "No arguments passed"
912 print ShowAct.__doc__
913 return False
914 threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *')
915 print GetThreadSummary.header
916 print GetThreadSummary(threadval)
917
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>
922 """
923 if cmd_args == None or len(cmd_args) < 1:
924 print "No arguments passed"
925 print ShowAct.__doc__.strip()
926 return False
927 threadval = kern.GetValueFromAddress(cmd_args[0], 'thread *')
928 print GetThreadSummary.header
929 print GetThreadSummary(threadval)
930 print GetThreadBackTrace(threadval, prefix="\t")
931 return
932
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.
941 """
942 if cmd_args == None or len(cmd_args) < 1:
943 print "No arguments passed"
944 print SwitchToAct.__doc__.strip()
945 return False
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."
953 return
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.
958 """
959 for t in kern.tasks:
960 ShowTaskStacks(t)
961 print " \n"
962 ZombStacks()
963 return
964
965 # EndMacro: showallstacks
966
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)
971 """
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)
984 print "\tBacktrace:"
985 print GetThreadBackTrace(active_thread, prefix="\t")
986 current_processor = current_processor.processor_list
987 return
988 # EndMacro: showcurrentstacks
989
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
1006 return
1007
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.
1012
1013 """
1014 out_string = ""
1015 bt_count = 0
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):
1022 break
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"
1026 bt_count +=1
1027 previous_frame_ptr = frame_ptr
1028 frame_val = kern.GetValueFromAddress((frame_ptr), 'uintptr_t *')
1029 if unsigned(frame_val) == 0:
1030 break
1031 frame_ptr = unsigned(dereference(frame_val))
1032
1033 return out_string
1034
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`
1040 """
1041 if len(cmd_args) < 1:
1042 print FullBackTrace.__doc__
1043 return False
1044 print GetFullBackTrace(ArgumentStringToInt(cmd_args[0]), prefix="\t")
1045
1046 @lldb_command('fullbtall')
1047 def FullBackTraceAll(cmd_args=[]):
1048 """ Show full backtrace across the interrupt boundary for threads running on all processors.
1049 Syntax: fullbtall
1050 Example: fullbtall
1051 """
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:"
1063
1064 ThreadVal = GetLLDBThreadForKernelThread(active_thread)
1065
1066 FramePtr = ThreadVal.frames[0].GetFP()
1067
1068 print GetFullBackTrace(unsigned(FramePtr), prefix="\t")
1069
1070
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"
1075 """
1076 if len(cmd_args) < 1:
1077 print "Invalid address.\nSyntax: symbolicate <address>"
1078 return False
1079 print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args[0]))
1080 return True
1081
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
1086 """
1087 headp = kern.globals.initproc.p_children
1088 for pp in IterateListEntry(headp, 'struct proc *', 'p_sibling'):
1089 print GetProcInfo(pp)
1090 return
1091
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
1097 """
1098 search_pid = 0
1099 if cmd_args:
1100 search_pid = ArgumentStringToInt(cmd_args[0])
1101
1102 if search_pid < 0:
1103 print "pid specified must be a positive number"
1104 print ShowProcTree.__doc__
1105 return
1106
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))
1113 print out_string
1114 ShowProcTreeRecurse(proc, "| ")
1115
1116 return
1117
1118 def ShowProcTreeRecurse(proc, prefix=""):
1119 """ Prints descendants of a given proc in hierarchial tree form
1120 params:
1121 proc : core.value representing a struct proc * in the kernel
1122 returns:
1123 str : String containing info about a given proc and its descendants in tree form
1124 """
1125 if proc.p_childrencnt > 0:
1126 head_ptr = proc.p_children.lh_first
1127
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 + "| ")
1131
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.
1137 """
1138 if not cmd_args:
1139 print "Please provide thread_t whose tid you'd like to look up"
1140 print ShowThreadForTid.__doc__
1141 return
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)
1149 return
1150 print "Not a valid thread_id"
1151
1152 # Macro: showallprocessors
1153
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
1158 """
1159
1160 processor_state_str = "INVALID"
1161 processor_state = int(processor.state)
1162
1163 processor_states = {
1164 0: 'OFF_LINE',
1165 1: 'SHUTDOWN',
1166 2: 'START',
1167 # 3 (formerly INACTIVE)
1168 4: 'IDLE',
1169 5: 'DISPATCHING',
1170 6: 'RUNNING'
1171 }
1172
1173 if processor_state in processor_states:
1174 processor_state_str = "{0: <11s} ".format(processor_states[processor_state])
1175
1176 out_str = "Processor {: <#018x} cpu_id {:>#4x} State {:<s}\n".format(processor, int(processor.cpu_id), processor_state_str)
1177 return out_str
1178
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
1183 """
1184 out_str = " runq: count {: <10d} highq: {: <10d} urgency {: <10d}\n".format(runq.count, runq.highq, runq.urgency)
1185
1186 runq_queue_i = 0
1187 runq_queue_count = sizeof(runq.queues)/sizeof(runq.queues[0])
1188
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
1192
1193 if unsigned(runq_queue_p) != unsigned(runq_queue_head):
1194 runq_queue_this_count = 0
1195
1196 for entry in IterateQueue(runq_queue_head, "sched_entry_t", "links"):
1197 runq_queue_this_count += 1
1198
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"):
1201 group = entry.group
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))
1204
1205 return out_str
1206
1207 @lldb_command('showrunq')
1208 def ShowRunq(cmd_args=None):
1209 """ Routine to print information of a runq
1210 Usage: showrunq <runq>
1211 """
1212 out_str = ''
1213 runq = kern.GetValueFromAddress(cmd_args[0], 'struct run_queue *')
1214 out_str += GetRunQSummary(runq)
1215 print out_str
1216
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
1221 """
1222 out_str = " runq: count {: <10d} highq: {: <10d} urgency {: <10d}\n".format(runq.count, runq.highq, runq.urgency)
1223
1224 runq_queue_i = 0
1225 runq_queue_count = sizeof(runq.queues)/sizeof(runq.queues[0])
1226
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
1230
1231 if unsigned(runq_queue_p) != unsigned(runq_queue_head):
1232 runq_queue_this_count = 0
1233
1234 for thread in IterateQueue(runq_queue_head, "thread_t", "links"):
1235 runq_queue_this_count += 1
1236
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"
1243 return out_str
1244
1245
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
1250 """
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)
1253 grrr_group_i = 0
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"
1266 return out_str
1267
1268 @lldb_command('showallprocessors')
1269 def ShowAllProcessors(cmd_args=None):
1270 """ Routine to print information of all psets and processors
1271 Usage: showallprocessors
1272 """
1273 pset = addressof(kern.globals.pset0)
1274 show_grrr = 0
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
1281
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:
1289 show_grrr = 1
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
1299
1300 out_str = ''
1301
1302 out_str += "Scheduler: {:s} ({:s}, {:d})\n".format(kern.globals.sched_string,
1303 kern.Symbolicate(unsigned(kern.globals.sched_current_dispatch)),
1304 sched_enum_val)
1305
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)
1308
1309 if show_group_pset_runq:
1310 # Create a group->task mapping
1311 task_map = {}
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
1316
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)
1320
1321 if show_priority_pset_runq:
1322 runq = pset.pset_runq
1323 out_str += GetRunQSummary(runq)
1324
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)
1336
1337 out_str += " Active Processors:\n"
1338 for processor in IterateQueue(pset.active_queue, "processor_t", "processor_queue"):
1339 out_str += " "
1340 out_str += GetProcessorSummary(processor)
1341 if show_priority_runq:
1342 runq = processor.runq
1343 out_str += GetRunQSummary(runq)
1344 if show_grrr:
1345 grrr_runq = processor.grrr_runq
1346 out_str += GetGrrrSummary(grrr_runq)
1347
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)
1353
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)
1359
1360 pset = pset.pset_list
1361
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)])
1366
1367 out_str += "\n"
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)
1377
1378 print out_str
1379 # EndMacro: showallprocessors
1380
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
1386 """
1387 ledger_limit_infinity = (uint64_t(0x1).value << 63) - 1
1388 lf_refill_scheduled = 0x0400
1389 lf_tracking_max = 0x4000
1390
1391 out_str = ''
1392 now = unsigned(kern.globals.sched_tick) / 20
1393 lim_pct = 0
1394
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))
1400 else:
1401 out_str += " - - - - "
1402
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))
1406 else:
1407 out_str += " - "
1408
1409 if (ledger.le_flags & lf_refill_scheduled):
1410 out_str += "{:15d} ".format(ledger._le.le_refill.le_refill_period)
1411 else:
1412 out_str += " - "
1413
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)
1416 else:
1417 out_str += " - "
1418
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))
1421 else:
1422 out_str += " - "
1423
1424 if ((unsigned(ledger.le_credit) - unsigned(ledger.le_debit)) > unsigned(ledger.le_limit)):
1425 out_str += " X "
1426 else:
1427 out_str += " "
1428
1429 out_str += "{:#8x}\n".format(ledger.le_flags)
1430 return out_str
1431
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
1436 """
1437 out_str = " [{:#08x}]\n".format(thread_val)
1438 ledgerp = thread_val.t_threadledger
1439 if ledgerp:
1440 i = 0
1441 while i != ledgerp.l_template.lt_cnt:
1442 out_str += GetLedgerEntrySummary(kern.globals.thread_ledger_template,
1443 ledgerp.l_entries[i], i)
1444 i = i + 1
1445 return out_str
1446
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
1455 """
1456 out_str = ''
1457 task_ledgerp = task_val.ledger
1458 i = 0
1459 out_str += "{: #08x} ".format(task_val)
1460 pval = Cast(task_val.bsd_info, 'proc *')
1461 if pval:
1462 out_str += "{: <5s}:\n".format(pval.p_comm)
1463 else:
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)
1467 i = i + 1
1468
1469 # Now walk threads
1470 for thval in IterateQueue(task_val.threads, 'thread *', 'task_threads'):
1471 out_str += GetThreadLedgerSummary(thval)
1472
1473 return out_str
1474
1475 # Macro: showtaskledgers
1476
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>
1482 """
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)
1488 return
1489
1490 if not cmd_args:
1491 raise ArgumentError("No arguments passed.")
1492 tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
1493 if not tval:
1494 raise ArgumentError("unknown arguments: %r" %cmd_args)
1495 print GetTaskLedgers.header
1496 print GetTaskLedgers(tval)
1497
1498 # EndMacro: showtaskledgers
1499
1500 # Macro: showalltaskledgers
1501
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
1506 """
1507 for t in kern.tasks:
1508 task_val = unsigned(t)
1509 ShowTaskLedgers([task_val])
1510
1511 # EndMacro: showalltaskledgers
1512
1513 # Macro: showprocuuidpolicytable
1514
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
1521 """
1522 data = []
1523 for i in range(16):
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)
1527 return out_string
1528
1529 @lldb_command('showprocuuidpolicytable')
1530 def ShowProcUUIDPolicyTable(cmd_args=None):
1531 """ Routine to print the proc UUID policy table
1532 Usage: showprocuuidpolicytable
1533 """
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])
1538 entrynum = 0
1539 for entry in IterateListEntry(headp, 'struct proc_uuid_policy_entry *', 'entries'):
1540 print "{0: >2d}.{1: <5d} ".format(i, entrynum) + GetProcUUIDPolicyEntrySummary(entry)
1541 entrynum += 1
1542
1543
1544 # EndMacro: showprocuuidpolicytable
1545
1546 @lldb_command('showalltaskpolicy')
1547 def ShowAllTaskPolicy(cmd_args=None):
1548 """
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)
1556 """
1557 global kern
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"],
1577 ["t_role", "role"],
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"]
1583 ]
1584
1585 requested=""
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])) + " "
1589 else:
1590 requested+=""
1591
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"]
1600 ]
1601
1602 suppression=""
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])) + " "
1606 else:
1607 suppression+=""
1608
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"],
1625 ["t_role", "role"]
1626 ]
1627
1628 effective=""
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])) + " "
1632 else:
1633 effective+=""
1634
1635
1636 pended_strings = [
1637 ["t_updating_policy", "updating"],
1638 ["update_sockets", "update_sockets"],
1639 ["t_update_timers", "update_timers"],
1640 ["t_update_watchers", "update_watchers"]
1641 ]
1642
1643 pended=""
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])) + " "
1647 else:
1648 pended+=""
1649
1650 print "requested: " + requested
1651 print "suppression: " + suppression
1652 print "effective: " + effective
1653 print "pended: " + pended
1654
1655
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
1662 """
1663 out_string = ""
1664 format_string = '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
1665
1666 wqtype = ""
1667
1668 if (waitq.wq_fifo == 1) :
1669 wqtype += "FIFO"
1670 else :
1671 wqtype += "PRIO"
1672
1673 if (waitq.wq_prepost == 1) :
1674 wqtype += "Prepost"
1675
1676 if (waitq.wq_type == 0x3) :
1677 wqtype += "Set"
1678 elif (waitq.wq_type == 0x2) :
1679 wqtype += "Queue"
1680 else :
1681 wqtype += "INVALID"
1682
1683 out_string += format_string.format(waitq, unsigned(waitq.wq_interlock.lock_data), policy, 0, 0, unsigned(waitq.wq_eventmask))
1684
1685 out_string += "\n" + GetThreadSummary.header
1686
1687 for thread in IterateQueue(waitq.wq_queue, "thread_t", "links"):
1688 out_string += "\n" + GetThreadSummary(thread)
1689
1690 return out_string
1691
1692
1693 @lldb_command('showallsuspendedtasks', '')
1694 def ShowSuspendedTasks(cmd_args=[], options={}):
1695 """ Show a list of suspended tasks with their process name summary.
1696 """
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 *'))
1701 return True
1702
1703