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