]> git.saurik.com Git - apple/xnu.git/blame - tools/lldbmacros/process.py
xnu-7195.101.1.tar.gz
[apple/xnu.git] / tools / lldbmacros / process.py
CommitLineData
39236c6e
A
1
2""" Please make sure you read the README file COMPLETELY BEFORE reading anything below.
3e170ce0 3 It is very critical that you read coding guidelines in Section E in README file.
39236c6e
A
4"""
5
6from xnu import *
7import sys, shlex
8from utils import *
9from core.lazytarget import *
3e170ce0 10import time
39236c6e 11import xnudefines
5ba3f43e 12import memory
f427ee49 13import json
c3c9b80d 14from collections import defaultdict
f427ee49
A
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)
39236c6e 28
fe8ab488 29def GetProcNameForTask(task):
c3c9b80d
A
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.
fe8ab488
A
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 """
c3c9b80d
A
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)
f427ee49 47
c3c9b80d 48 return "unknown"
fe8ab488
A
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)
f427ee49 60
fe8ab488
A
61 if task :
62 return unsigned(task.audit_token.val[5])
63
64 return -1
65
39236c6e
A
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 = ""
f427ee49 74 out_string += ("Process {p: <#020x}\n\tname {0: <32s}\n\tpid:{p.p_pid: <6d} " +
39236c6e 75 "task:{p.task: <#020x} p_stat:{p.p_stat: <6d} parent pid: {p.p_ppid: <6d}\n"
f427ee49 76 ).format(GetProcName(proc), p=proc)
39236c6e
A
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):
f427ee49 113 return GetProcName(p)
39236c6e
A
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 """
fe8ab488
A
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
39236c6e
A
170
171@lldb_command('zombstacks')
172def ZombStacks(cmd_args=None):
173 """ Routine to print out all stacks of tasks that are exiting
174 """
fe8ab488 175 header_flag = 0
39236c6e
A
176 for proc in kern.zombprocs:
177 if proc.p_stat != 5:
fe8ab488
A
178 if header_flag == 0:
179 print "\nZombie Stacks:"
180 header_flag = 1
39236c6e
A
181 t = Cast(proc.task, 'task *')
182 ShowTaskStacks(t)
183#End of Zombstacks
184
fe8ab488
A
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
cb323159 198 r - AST_RESET_PCS
c3c9b80d 199 a - AST_ARCADE
fe8ab488
A
200 G - AST_GUARD
201 T - AST_TELEMETRY_USER
202 T - AST_TELEMETRY_KERNEL
203 T - AST_TELEMETRY_WINDOWED
204 S - AST_SFI
5ba3f43e
A
205 D - AST_DTRACE
206 I - AST_TELEMETRY_IO
207 E - AST_KEVENT
d9a64523
A
208 R - AST_REBALANCE
209 N - AST_UNQUIESCE
fe8ab488
A
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',
c3c9b80d 214 0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M', 0x400: 'r', 0x800: 'a',
5ba3f43e 215 0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S',
d9a64523 216 0x20000: 'D', 0x40000: 'I', 0x80000: 'E', 0x100000: 'R', 0x200000: 'N'}
fe8ab488
A
217 state_str = ''
218 mask = 0x1
c3c9b80d 219 while mask <= 0x200000:
fe8ab488
A
220 state_str += thread_state_chars[int(state & mask)]
221 mask = mask << 1
3e170ce0 222
fe8ab488
A
223 return state_str
224
225
3e170ce0
A
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
39236c6e
A
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"))
3e170ce0 239def GetTaskSummary(task, showcorpse=False):
39236c6e
A
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'
5ba3f43e
A
250 if hasattr(task, "effective_policy") and int(task.effective_policy.tep_sup_active) == 1:
251 task_flags += 'N'
39236c6e
A
252 if hasattr(task, "suspend_count") and int(task.suspend_count) > 0:
253 task_flags += 'S'
fe8ab488
A
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'
3e170ce0
A
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
39236c6e 269 out_string += format_string.format(task, task.map, task.itk_space, thread_count, task_flags)
3e170ce0
A
270 if showcorpse is True and unsigned(task.corpse_info) != 0:
271 out_string += " " + GetKCDataSummary(task.corpse_info)
39236c6e
A
272 return out_string
273
813fb2f6
A
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
39236c6e 287@lldb_type_summary(['thread *', 'thread_t'])
3e170ce0 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'))
39236c6e
A
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
fe8ab488
A
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
3e170ce0 302 C - Crashed thread
fe8ab488
A
303
304 policy flags:
305 B - darwinbg
fe8ab488
A
306 T - IO throttle
307 P - IO passive
308 D - Terminated
39236c6e
A
309 """
310 out_string = ""
fe8ab488 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}"
39236c6e
A
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)
39236c6e 316 processor = hex(thread.last_processor)
3e170ce0 317 base_priority = str(int(thread.base_pri))
39236c6e 318 sched_priority = str(int(thread.sched_pri))
fe8ab488
A
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"
39236c6e
A
334
335 io_policy_str = ""
813fb2f6 336 thread_name = GetThreadName(thread)
39236c6e
A
337 if int(thread.uthread) != 0:
338 uthread = Cast(thread.uthread, 'uthread *')
813fb2f6 339
39236c6e
A
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
39037602 348 if int(thread.effective_policy.thep_darwinbg) != 0:
39236c6e 349 io_policy_str += "B"
39037602 350 if int(thread.effective_policy.thep_io_tier) != 0:
39236c6e 351 io_policy_str += "T"
39037602 352 if int(thread.effective_policy.thep_io_passive) != 0:
39236c6e 353 io_policy_str += "P"
39037602 354 if int(thread.effective_policy.thep_terminated) != 0:
39236c6e
A
355 io_policy_str += "D"
356
357 state = int(thread.state)
fe8ab488 358 thread_state_chars = {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
39236c6e 359 state_str = ''
fe8ab488
A
360 mask = 0x1
361 while mask <= 0x80 :
362 state_str += thread_state_chars[int(state & mask)]
363 mask = mask << 1
3e170ce0
A
364
365 if int(thread.inspection):
366 state_str += 'C'
367
fe8ab488
A
368 ast = int(thread.ast) | int(thread.reason)
369 ast_str = GetASTSummary(ast)
39236c6e
A
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
3e170ce0 377 wait_queue_str = str("{0: <#020x}".format(int(hex(thread.waitq), 16)))
39236c6e
A
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
fe8ab488 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)
39236c6e 388 return out_string
39236c6e 389
a1c7dba1 390
3e170ce0
A
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')
fe8ab488 410 if (coal.terminated):
3e170ce0 411 flags.append('terminated')
fe8ab488 412 if (coal.reaped):
3e170ce0
A
413 flags.append('reaped')
414 if (coal.notified):
415 flags.append('notified')
5ba3f43e
A
416 if (coal.efficient):
417 flags.append('efficient')
3e170ce0
A
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')):
39037602 443 task_str = "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task),task,GetProcNameForTask(task),GetTaskRoleString(task.effective_policy.tep_role))
3e170ce0
A
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)
5ba3f43e 479 out_string += "\n\t cpu_ptime {0: <d}".format(coal.r.cpu_ptime)
a39ff7e2
A
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])
3e170ce0
A
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"
5ba3f43e 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))
3e170ce0
A
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)
5ba3f43e 512 out_string += "\n\t Thread Group: {0: <#020x}\n".format(coal.j.thread_group)
3e170ce0
A
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"
a1c7dba1 546
fe8ab488 547 return out_string
39236c6e 548
3e170ce0
A
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:
5ba3f43e 560 raise ArgumentError("No arguments passed")
3e170ce0
A
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
5ba3f43e
A
582# Macro: showallthreadgroups
583
d9a64523 584@lldb_type_summary(['struct thread_group *', 'thread_group *'])
5ba3f43e
A
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'
c3c9b80d 596 out_string += format_string.format(tg, tg.tg_id, tg.tg_name, tg.tg_refcount.ref_count, tg_flags, tg.tg_recommendation)
5ba3f43e
A
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
3e170ce0
A
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
fe8ab488 633@lldb_type_summary(['proc', 'proc *'])
f427ee49 634@header("{0: >6s} {1: <18s} {2: >11s} {3: ^10s} {4: <32s}".format("pid", "process", "io_policy", "wq_state", "command"))
39236c6e
A
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 = ""
f427ee49 643 format_string= "{0: >6d} {1: <#018x} {2: >11s} {3: >2d} {4: >2d} {5: >2d} {6: <32s}"
39236c6e
A
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
39037602 661 if int(task.effective_policy.tep_darwinbg) != 0:
39236c6e 662 io_policy_str += "B"
39037602 663 if int(task.effective_policy.tep_lowpri_cpu) != 0:
39236c6e
A
664 io_policy_str += "L"
665
39037602 666 if int(task.effective_policy.tep_io_tier) != 0:
39236c6e 667 io_policy_str += "T"
39037602 668 if int(task.effective_policy.tep_io_passive) != 0:
39236c6e 669 io_policy_str += "P"
39037602 670 if int(task.effective_policy.tep_terminated) != 0:
39236c6e
A
671 io_policy_str += "D"
672
39037602 673 if int(task.effective_policy.tep_latency_qos) != 0:
39236c6e 674 io_policy_str += "Q"
39037602 675 if int(task.effective_policy.tep_sup_active) != 0:
39236c6e
A
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
f427ee49 693 process_name = GetProcName(proc)
813fb2f6
A
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
39236c6e
A
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
fe8ab488
A
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
39236c6e
A
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:
5ba3f43e 754 raise ArgumentError("No arguments passed")
39236c6e
A
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:
5ba3f43e 773 raise ArgumentError("No arguments passed")
39236c6e
A
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:
5ba3f43e 793 raise ArgumentError("No arguments passed")
39236c6e
A
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
39236c6e
A
823 while count <= proc_lastfile:
824 if unsigned(proc_ofiles[count]) != 0:
825 out_str = ''
f427ee49
A
826 proc_fd_flags = proc_ofiles[count].fp_flags
827 proc_fd_fglob = proc_ofiles[count].fp_glob
39236c6e
A
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)
5ba3f43e
A
832 if proc_fd_ftype in xnudefines.filetype_strings:
833 out_str += "{0: <8s} ".format(xnudefines.filetype_strings[proc_fd_ftype])
39236c6e
A
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
fe8ab488
A
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
3e170ce0
A
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
cb323159 944 for th in IterateMPSCQueue(addressof(kern.globals.thread_terminate_queue.mpd_queue), 'struct thread', 'mpsc_links'):
3e170ce0
A
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
39236c6e
A
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:
3e170ce0
A
976 raise ArgumentError("Invalid arguments")
977
39236c6e
A
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
4bd07ac2
A
990@lldb_command('showalltasklogicalwrites')
991def ShowAllTaskIOStats(cmd_args=None):
992 """ Commad to print I/O stats for all tasks
993 """
f427ee49 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")
4bd07ac2
A
995 for t in kern.tasks:
996 pval = Cast(t.bsd_info, 'proc *')
cb323159
A
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,
f427ee49 1006 GetProcName(pval))
4bd07ac2
A
1007
1008
cb323159
A
1009@lldb_command('showalltasks','C', fancy=True)
1010def ShowAllTasks(cmd_args=None, cmd_options={}, O=None):
39236c6e
A
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)
3e170ce0 1018 Usage: (lldb) showalltasks -C : describe the corpse structure
39236c6e
A
1019 """
1020 global kern
3e170ce0
A
1021 extra_hdr = ''
1022 showcorpse = False
1023 if '-C' in cmd_options:
1024 showcorpse = True
1025 extra_hdr += " " + GetKCDataSummary.header
1026
cb323159
A
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
fe8ab488 1032 ZombTasks()
39236c6e 1033
813fb2f6
A
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:
f427ee49 1046 if kern.GetValueFromAddress(unsigned(t.map.pmap), 'pmap_t') == pmap:
813fb2f6
A
1047 pval = Cast(t.bsd_info, 'proc *')
1048 out_str = GetTaskSummary(t) + " " + GetProcSummary(pval)
1049 print out_str
1050
39236c6e
A
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:
c3c9b80d
A
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.
39236c6e 1069 pval = Cast(t.bsd_info, 'proc *')
c3c9b80d
A
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
39236c6e
A
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 *")
f427ee49 1110 process_name = "{:s}".format(GetProcName(pval))
39236c6e
A
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
d190cdc3
A
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
39236c6e
A
1187@lldb_command('showallthreads')
1188def ShowAllThreads(cmd_args = None):
1189 """ Display info about all threads in the system
1190 """
c3c9b80d
A
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
39236c6e
A
1203 for t in kern.tasks:
1204 ShowTaskThreads([str(int(t))])
c3c9b80d 1205 ShowTaskTerminatedThreads(t)
39236c6e 1206 print " \n"
c3c9b80d 1207
fe8ab488
A
1208 for t in kern.terminated_tasks:
1209 print "Terminated: \n"
1210 ShowTaskThreads([str(int(t))])
c3c9b80d 1211 ShowTaskTerminatedThreads(t)
fe8ab488 1212 print " \n"
c3c9b80d
A
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
39236c6e
A
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 """
5ba3f43e
A
1257 if not cmd_args:
1258 raise ArgumentError("No arguments passed")
39236c6e
A
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 """
5ba3f43e
A
1268 if not cmd_args:
1269 raise ArgumentError("No arguments passed")
39236c6e
A
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 """
5ba3f43e
A
1285 if cmd_args is None or len(cmd_args) < 1:
1286 raise ArgumentError("No arguments passed")
39236c6e
A
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
3e170ce0
A
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)
4bd07ac2 1314 lldbthread = lldb_process.GetThreadByID(int(fake_thread_id))
3e170ce0
A
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
39236c6e
A
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)
fe8ab488
A
1334 print " \n"
1335 ZombStacks()
39236c6e
A
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:
fe8ab488 1348 print "\n" + GetProcessorSummary(current_processor)
39236c6e
A
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:
fe8ab488 1369 print GetProcessorSummary(current_processor)
39236c6e
A
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:
5ba3f43e 1394 if (not kern.arch.startswith('arm') and frame_ptr < mh_execute_addr) or (kern.arch.startswith('arm') and frame_ptr > mh_execute_addr):
39236c6e
A
1395 break
1396 pc_val = kern.GetValueFromAddress(frame_ptr + kern.ptrsize,'uintptr_t *')
c3c9b80d 1397 pc_val = kern.StripKernelPAC(unsigned(dereference(pc_val)))
39236c6e
A
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>
fe8ab488 1412 Example: fullbt `$rbp`
39236c6e
A
1413 """
1414 if len(cmd_args) < 1:
1415 print FullBackTrace.__doc__
1416 return False
1417 print GetFullBackTrace(ArgumentStringToInt(cmd_args[0]), prefix="\t")
1418
fe8ab488
A
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
39236c6e
A
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)
f427ee49
A
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))
39236c6e
A
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'):
f427ee49 1502 print prefix + "|--{0: <6d} {1: <32s} [ {2: #019x} ]\n".format(p.p_pid, GetProcName(p), unsigned(p))
39236c6e
A
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
39236c6e
A
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 """
fe8ab488
A
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
3e170ce0
A
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)
39236c6e
A
1571 return out_str
1572
f427ee49 1573def GetLedgerEntry(ledger_template, ledger, i):
39236c6e
A
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 *
f427ee49 1577 return: entry - entry dictionary
39236c6e
A
1578 """
1579 ledger_limit_infinity = (uint64_t(0x1).value << 63) - 1
1580 lf_refill_scheduled = 0x0400
1581 lf_tracking_max = 0x4000
1582
fe8ab488 1583 now = unsigned(kern.globals.sched_tick) / 20
39236c6e
A
1584 lim_pct = 0
1585
f427ee49
A
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"]
39236c6e 1592 if (ledger.le_flags & lf_tracking_max):
f427ee49
A
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:
d9a64523 1621 out_str += " - "
f427ee49
A
1622
1623 if entry.has_key("lifetime_max"):
1624 out_str += "{:14d} ".format(entry["lifetime_max"])
1625 else:
d9a64523 1626 out_str += " - "
f427ee49
A
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"]))
39236c6e
A
1631 else:
1632 out_str += " - "
1633
f427ee49
A
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"])
39236c6e
A
1637 else:
1638 out_str += " - "
39236c6e
A
1639 out_str += " - "
1640
f427ee49
A
1641 if entry.has_key("warn_percent"):
1642 out_str += "{:9d} ".format(entry["warn_percent"])
39236c6e
A
1643 else:
1644 out_str += " - "
1645
f427ee49
A
1646 if entry.has_key("limit"):
1647 if entry["balance"] > entry["limit"]:
1648 out_str += " X "
1649 else:
1650 out_str += " "
39236c6e
A
1651 else:
1652 out_str += " "
1653
f427ee49 1654 out_str += "{:#8x}\n".format(entry["flags"])
39236c6e
A
1655 return out_str
1656
f427ee49
A
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):
39236c6e 1668 """ Internal function to get a summary of ledger entries for the given thread
f427ee49
A
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.
39236c6e 1672 """
f427ee49
A
1673 thread = {}
1674 thread["address"] = unsigned(thread_val)
39236c6e 1675 ledgerp = thread_val.t_threadledger
f427ee49 1676 thread["entries"] = []
39236c6e
A
1677 if ledgerp:
1678 i = 0
1679 while i != ledgerp.l_template.lt_cnt:
f427ee49
A
1680 thread["entries"].append(GetLedgerEntry(kern.globals.thread_ledger_template,
1681 ledgerp.l_entries[i], i))
39236c6e 1682 i = i + 1
f427ee49
A
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)
39236c6e
A
1694 return out_str
1695
f427ee49 1696def GetTaskLedgers(task_val):
39236c6e
A
1697 """ Internal function to get summary of ledger entries from the task and its threads
1698 params: task_val - value representing struct task *
f427ee49
A
1699 return: task - python dictionary containing tasks's ledger entries. This can
1700 be printed directly with FormatTaskLedgerSummary or outputted as json.
39236c6e 1701 """
39236c6e
A
1702 task_ledgerp = task_val.ledger
1703 i = 0
f427ee49
A
1704 tasks = []
1705 task = {}
1706 task["address"] = unsigned(task_val)
1707
39236c6e
A
1708 pval = Cast(task_val.bsd_info, 'proc *')
1709 if pval:
f427ee49
A
1710 task["name"] = GetProcName(pval)
1711 task["pid"] = int(pval.p_pid)
1712
1713 task["entries"] = []
39236c6e 1714 while i != task_ledgerp.l_template.lt_cnt:
f427ee49 1715 task["entries"].append(GetLedgerEntry(kern.globals.task_ledger_template, task_ledgerp.l_entries[i], i))
39236c6e
A
1716 i = i + 1
1717
1718 # Now walk threads
f427ee49 1719 task["threads"] = []
39236c6e 1720 for thval in IterateQueue(task_val.threads, 'thread *', 'task_threads'):
f427ee49
A
1721 task["threads"].append(GetThreadLedgers(thval))
1722
1723 return task
39236c6e 1724
f427ee49
A
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)
39236c6e
A
1745 return out_str
1746
f427ee49 1747
39236c6e
A
1748# Macro: showtaskledgers
1749
f427ee49 1750@lldb_command('showtaskledgers', 'JF:I')
39236c6e
A
1751def ShowTaskLedgers(cmd_args=None, cmd_options={}):
1752 """ Routine to print a summary of ledger entries for the task and all of its threads
f427ee49 1753 or : showtaskledgers [ -I ] [-J] [ -F ] <task>
d9a64523
A
1754 options:
1755 -I: show footprint interval max (DEV/DEBUG only)
1756 -F: specify task via name instead of address
f427ee49 1757 -J: output json
d9a64523 1758 -
39236c6e 1759 """
f427ee49 1760 print_json = False
39236c6e
A
1761 if "-F" in cmd_options:
1762 task_list = FindTasksByName(cmd_options["-F"])
1763 for tval in task_list:
f427ee49
A
1764 print FormatTaskLedgerSummary.header
1765 ledgers = GetTaskLedgers(tval)
1766 print FormatTaskLedgerSummary(ledgers)
39236c6e 1767 return
f427ee49
A
1768 if "-J" in cmd_options:
1769 print_json = True
39236c6e
A
1770
1771 if not cmd_args:
1772 raise ArgumentError("No arguments passed.")
d9a64523
A
1773 show_footprint_interval_max = False
1774 if "-I" in cmd_options:
1775 show_footprint_interval_max = True
39236c6e
A
1776 tval = kern.GetValueFromAddress(cmd_args[0], 'task *')
1777 if not tval:
1778 raise ArgumentError("unknown arguments: %r" %cmd_args)
f427ee49
A
1779 ledgers = GetTaskLedgers(tval)
1780 if print_json:
1781 print json.dumps(ledgers)
d9a64523 1782 else:
f427ee49
A
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)
39236c6e
A
1790
1791# EndMacro: showtaskledgers
1792
1793# Macro: showalltaskledgers
1794
f427ee49 1795@lldb_command('showalltaskledgers', "J")
d9a64523 1796def ShowAllTaskLedgers(cmd_args=None, cmd_options={}):
39236c6e 1797 """ Routine to print a summary of ledger entries for all tasks and respective threads
f427ee49
A
1798 Usage: showalltaskledgers [-J]
1799 -J : Output json
39236c6e 1800 """
f427ee49
A
1801 print_json = False
1802 if "-J" in cmd_options:
1803 print_json = True
1804 tasks = []
39236c6e
A
1805 for t in kern.tasks:
1806 task_val = unsigned(t)
f427ee49
A
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)
39236c6e
A
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"],
39236c6e
A
1875 ["t_apptype", "apptype"],
1876 ["t_boosted", "boosted"],
39236c6e 1877 ["t_role", "role"],
39236c6e
A
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"],
fe8ab488
A
1898 ["t_sup_suspend", "suspend"],
1899 ["t_sup_bg_sockets", "bg-sockets"]
39236c6e
A
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"],
fe8ab488 1925 ["t_role", "role"]
39236c6e
A
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
39236c6e
A
1935 print "requested: " + requested
1936 print "suppression: " + suppression
1937 print "effective: " + effective
39236c6e
A
1938
1939
fe8ab488
A
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
39236c6e 1986
39037602
A
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:
f427ee49 1998 out_str += "{:s}\n".format(GetProcName(procp))
39037602
A
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
f427ee49 2086 print "{0: <#020x} {1: <32s} {2: >10d}".format(proc, GetProcName(proc), proc_file_count)
39037602
A
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 *')
f427ee49 2246 process_name = "{:s}".format(GetProcName(pval))
39037602
A
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