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