2 """ Please make sure you read the README file COMPLETELY BEFORE reading anything below.
3 It is very critical that you read coding guidelines in Section E in README file.
9 from core
.lazytarget
import *
14 def GetProcNameForTask(task
):
15 """ returns a string name of the process. if proc is not valid "unknown" is returned
17 task: value object represeting a task in the kernel.
19 str : A string name of the process linked to the task
21 if not task
or not unsigned(task
.bsd_info
):
23 p
= Cast(task
.bsd_info
, 'proc *')
26 def GetProcPIDForTask(task
):
27 """ returns a int pid of the process. if the proc is not valid, val[5] from audit_token is returned.
29 task: value object representing a task in the kernel
31 int : pid of the process or -1 if not found
33 if task
and unsigned(task
.bsd_info
):
34 p
= Cast(task
.bsd_info
, 'proc *')
35 return unsigned(p
.p_pid
)
38 return unsigned(task
.audit_token
.val
[5])
42 def GetProcInfo(proc
):
43 """ returns a string name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields.
45 proc : value object representing a proc in the kernel
47 str : A string describing various information for process.
50 out_string
+= ("Process {p: <#020x}\n\tname {p.p_comm: <20s}\n\tpid:{p.p_pid: <6d} " +
51 "task:{p.task: <#020x} p_stat:{p.p_stat: <6d} parent pid: {p.p_ppid: <6d}\n"
56 out_string
+= "Cred: euid {:d} ruid {:d} svuid {:d}\n".format(ucred
.cr_posix
.cr_uid
,
57 ucred
.cr_posix
.cr_ruid
,
58 ucred
.cr_posix
.cr_svuid
)
60 flags
= int(proc
.p_flag
)
61 out_string
+= "Flags: {0: <#020x}\n".format(flags
)
66 out_string
+= "\t" + xnudefines
.proc_flag_explain_strings
[i
] + "\n"
67 elif num
== 0x4: #special case for 32bit flag
68 out_string
+= "\t" + xnudefines
.proc_flag_explain_strings
[0] + "\n"
71 out_string
+= "State: "
72 state_val
= proc
.p_stat
73 if state_val
< 1 or state_val
> len(xnudefines
.proc_state_strings
) :
74 out_string
+= "(Unknown)"
76 out_string
+= xnudefines
.proc_state_strings
[int(state_val
)]
80 def GetProcNameForPid(pid
):
81 """ Finds the name of the process corresponding to a given pid
83 pid : int, pid you want to find the procname for
85 str : Name of the process corresponding to the pid, "Unknown" if not found
88 if int(p
.p_pid
) == int(pid
):
92 def GetProcForPid(search_pid
):
93 """ Finds the value object representing a proc in the kernel based on its pid
95 search_pid : int, pid whose proc structure you want to find
97 value : The value object representing the proc, if a proc corresponding
98 to the given pid is found. Returns None otherwise
101 return kern
.globals.initproc
103 headp
= kern
.globals.allproc
104 for proc
in IterateListEntry(headp
, 'struct proc *', 'p_list'):
105 if proc
.p_pid
== search_pid
:
109 @lldb_command('allproc')
110 def AllProc(cmd_args
=None):
111 """ Walk through the allproc structure and print procinfo for each process structure.
113 cmd_args - [] : array of strings passed from lldb command prompt
115 for proc
in kern
.procs
:
116 print GetProcInfo(proc
)
119 @lldb_command('zombproc')
120 def ZombProc(cmd_args
=None):
121 """ Routine to print out all procs in the zombie list
123 cmd_args - [] : array of strings passed from lldb command prompt
125 if len(kern
.zombprocs
) != 0:
126 print "\nZombie Processes:"
127 for proc
in kern
.zombprocs
:
128 print GetProcInfo(proc
) + "\n\n"
130 @lldb_command('zombtasks')
131 def ZombTasks(cmd_args
=None):
132 """ Routine to print out all tasks in the zombie list
136 if len(kern
.zombprocs
) != 0:
137 header
= "\nZombie Tasks:\n"
138 header
+= GetTaskSummary
.header
+ " " + GetProcSummary
.header
139 for proc
in kern
.zombprocs
:
141 t
= Cast(proc
.task
, 'task *')
142 out_str
+= GetTaskSummary(t
) +" "+ GetProcSummary(proc
) + "\n"
147 @lldb_command('zombstacks')
148 def ZombStacks(cmd_args
=None):
149 """ Routine to print out all stacks of tasks that are exiting
152 for proc
in kern
.zombprocs
:
155 print "\nZombie Stacks:"
157 t
= Cast(proc
.task
, 'task *')
161 def GetASTSummary(ast
):
162 """ Summarizes an AST field
175 T - AST_TELEMETRY_USER
176 T - AST_TELEMETRY_KERNEL
177 T - AST_TELEMETRY_WINDOWED
185 thread_state_chars
= {0x0:'', 0x1:'P', 0x2:'Q', 0x4:'U', 0x8:'H', 0x10:'Y', 0x20:'A',
186 0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M',
187 0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S',
188 0x20000: 'D', 0x40000: 'I', 0x80000: 'E'}
191 while mask
<= 0x80000:
192 state_str
+= thread_state_chars
[int(state
& mask
)]
198 @lldb_type_summary(['kcdata_descriptor *', 'kcdata_descriptor_t'])
199 @header("{0: <20s} {1: <20s} {2: <20s} {3: <10s} {4: <5s}".format("kcdata_descriptor", "begin_addr", "cur_pos", "size", "flags"))
200 def GetKCDataSummary(kcdata
):
201 """ Summarizes kcdata_descriptor structure
202 params: kcdata: value - value object representing kcdata_descriptor
203 returns: str - summary of the kcdata object
205 format_string
= "{0: <#020x} {1: <#020x} {2: <#020x} {3: <10d} {4: <#05x}"
206 return format_string
.format(kcdata
, kcdata
.kcd_addr_begin
, kcdata
.kcd_addr_end
, kcdata
.kcd_length
, kcdata
.kcd_flags
)
209 @lldb_type_summary(['task', 'task_t'])
210 @header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags"))
211 def GetTaskSummary(task
, showcorpse
=False):
212 """ Summarizes the important fields in task structure.
213 params: task: value - value object representing a task in kernel
214 returns: str - summary of the task
217 format_string
= '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}'
218 thread_count
= int(task
.thread_count
)
220 if hasattr(task
, "suppression_generation") and (int(task
.suppression_generation
) & 0x1) == 0x1:
222 if hasattr(task
, "effective_policy") and int(task
.effective_policy
.tep_sup_active
) == 1:
224 if hasattr(task
, "suspend_count") and int(task
.suspend_count
) > 0:
226 if hasattr(task
, 'task_imp_base') and unsigned(task
.task_imp_base
):
227 tib
= task
.task_imp_base
228 if int(tib
.iit_receiver
) == 1:
230 if int(tib
.iit_donor
) == 1:
232 if int(tib
.iit_assertcnt
) > 0:
235 # check if corpse flag is set
236 if unsigned(task
.t_flags
) & 0x20:
238 if unsigned(task
.t_flags
) & 0x40:
241 out_string
+= format_string
.format(task
, task
.map, task
.itk_space
, thread_count
, task_flags
)
242 if showcorpse
is True and unsigned(task
.corpse_info
) != 0:
243 out_string
+= " " + GetKCDataSummary(task
.corpse_info
)
246 def GetThreadName(thread
):
247 """ Get the name of a thread, if possible. Returns the empty string
250 if int(thread
.uthread
) != 0:
251 uthread
= Cast(thread
.uthread
, 'uthread *')
252 if int(uthread
.pth_name
) != 0 :
253 th_name_strval
= Cast(uthread
.pth_name
, 'char *')
254 if len(str(th_name_strval
)) > 0 :
255 return str(th_name_strval
)
259 @lldb_type_summary(['thread *', 'thread_t'])
260 @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'))
261 def GetThreadSummary(thread
):
262 """ Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct.
263 params: thread: value - value objecte representing a thread in kernel
264 returns: str - summary of a thread
272 A - Terminated and on termination queue
283 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}"
284 thread_ptr_str
= str("{0: <#020x}".format(thread
))
285 if int(thread
.static_param
) :
286 thread_ptr_str
+="[WQ]"
287 thread_id
= hex(thread
.thread_id
)
288 processor
= hex(thread
.last_processor
)
289 base_priority
= str(int(thread
.base_pri
))
290 sched_priority
= str(int(thread
.sched_pri
))
292 mode
= str(thread
.sched_mode
)
293 if "TIMESHARE" in mode
:
294 sched_mode
+="timeshare"
295 elif "FIXED" in mode
:
297 elif "REALTIME" in mode
:
298 sched_mode
+="realtime"
300 if (unsigned(thread
.bound_processor
) != 0):
304 if (unsigned(thread
.sched_flags
) & 0x0004):
308 thread_name
= GetThreadName(thread
)
309 if int(thread
.uthread
) != 0:
310 uthread
= Cast(thread
.uthread
, 'uthread *')
312 #check for io_policy flags
313 if int(uthread
.uu_flag
) & 0x400:
314 io_policy_str
+='RAGE '
316 #now flags for task_policy
320 if int(thread
.effective_policy
.thep_darwinbg
) != 0:
322 if int(thread
.effective_policy
.thep_io_tier
) != 0:
324 if int(thread
.effective_policy
.thep_io_passive
) != 0:
326 if int(thread
.effective_policy
.thep_terminated
) != 0:
329 state
= int(thread
.state
)
330 thread_state_chars
= {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
334 state_str
+= thread_state_chars
[int(state
& mask
)]
337 if int(thread
.inspection
):
340 ast
= int(thread
.ast
) |
int(thread
.reason
)
341 ast_str
= GetASTSummary(ast
)
343 #wait queue information
347 if ( state
& 0x1 ) != 0:
348 #we need to look at the waitqueue as well
349 wait_queue_str
= str("{0: <#020x}".format(int(hex(thread
.waitq
), 16)))
350 wait_event_str
= str("{0: <#020x}".format(int(hex(thread
.wait_event
), 16)))
351 wait_event_str_sym
= kern
.Symbolicate(int(hex(thread
.wait_event
), 16))
352 if len(wait_event_str_sym
) > 0:
353 wait_event_str
= wait_event_str
.strip() + " <" + wait_event_str_sym
+ ">"
354 if int(thread
.uthread
) != 0 :
355 uthread
= Cast(thread
.uthread
, 'uthread *')
356 if int(uthread
.uu_wmesg
) != 0:
357 wait_message
= str(Cast(uthread
.uu_wmesg
, 'char *'))
359 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
)
363 def GetTaskRoleString(role
):
365 0 : "TASK_UNSPECIFIED",
366 1 : "TASK_FOREGROUND_APPLICATION",
367 2 : "TASK_BACKGROUND_APPLICATION",
368 3 : "TASK_CONTROL_APPLICATION",
369 4 : "TASK_GRAPHICS_SERVER",
370 5 : "TASK_THROTTLE_APPLICATION",
371 6 : "TASK_NONUI_APPLICATION",
372 7 : "TASK_DEFAULT_APPLICATION",
374 return role_strs
[int(role
)]
376 def GetCoalitionFlagString(coal
):
378 if (coal
.privileged
):
379 flags
.append('privileged')
380 if (coal
.termrequested
):
381 flags
.append('termrequested')
382 if (coal
.terminated
):
383 flags
.append('terminated')
385 flags
.append('reaped')
387 flags
.append('notified')
389 flags
.append('efficient')
390 return "|".join(flags
)
392 def GetCoalitionTasks(queue
, coal_type
, thread_details
=False):
394 0x0 : "SFI_CLASS_UNSPECIFIED",
395 0x1 : "SFI_CLASS_DARWIN_BG",
396 0x2 : "SFI_CLASS_APP_NAP",
397 0x3 : "SFI_CLASS_MANAGED_FOCAL",
398 0x4 : "SFI_CLASS_MANAGED_NONFOCAL",
399 0x5 : "SFI_CLASS_DEFAULT_FOCAL",
400 0x6 : "SFI_CLASS_DEFAULT_NONFOCAL",
401 0x7 : "SFI_CLASS_KERNEL",
402 0x8 : "SFI_CLASS_OPTED_OUT",
403 0x9 : "SFI_CLASS_UTILITY",
404 0xA : "SFI_CLASS_LEGACY_FOCAL",
405 0xB : "SFI_CLASS_LEGACY_NONFOCAL",
406 0xC : "SFI_CLASS_USER_INITIATED_FOCAL",
407 0xD : "SFI_CLASS_USER_INITIATED_NONFOCAL",
408 0xE : "SFI_CLASS_USER_INTERACTIVE_FOCAL",
409 0xF : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL",
410 0x10 : "SFI_CLASS_MAINTENANCE",
413 field_name
= 'task_coalition'
414 for task
in IterateLinkageChain(queue
, 'task *', field_name
, coal_type
* sizeof('queue_chain_t')):
415 task_str
= "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task
),task
,GetProcNameForTask(task
),GetTaskRoleString(task
.effective_policy
.tep_role
))
417 for thread
in IterateQueue(task
.threads
, "thread_t", "task_threads"):
418 task_str
+= "\n\t\t\t|-> thread:" + hex(thread
) + ", " + sfi_strs
[int(thread
.sfi_class
)]
419 tasks
.append(task_str
)
422 def GetCoalitionTypeString(type):
423 """ Convert a coalition type field into a string
424 Currently supported types (from <mach/coalition.h>):
425 COALITION_TYPE_RESOURCE
426 COALITION_TYPE_JETSAM
428 if type == 0: # COALITION_TYPE_RESOURCE
434 def GetResourceCoalitionSummary(coal
, verbose
=False):
435 """ Summarize a resource coalition
437 out_string
= "Resource Coalition:\n\t Ledger:\n"
438 thread_details
= False
439 if config
['verbosity'] > vSCRIPT
:
440 thread_details
= True
441 ledgerp
= coal
.r
.ledger
442 if verbose
and unsigned(ledgerp
) != 0:
444 while i
!= ledgerp
.l_template
.lt_cnt
:
446 out_string
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, ledgerp
.l_entries
[i
], i
)
448 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
)
449 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
)
450 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
)
451 out_string
+= "\n\t cpu_ptime {0: <d}".format(coal
.r
.cpu_ptime
)
453 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_DEFAULT] {0: <d}".format(coal
.r
.cpu_time_eqos
[0])
454 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_MAINTENANCE] {0: <d}".format(coal
.r
.cpu_time_eqos
[1])
455 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_BACKGROUND] {0: <d}".format(coal
.r
.cpu_time_eqos
[2])
456 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_UTILITY] {0: <d}".format(coal
.r
.cpu_time_eqos
[3])
457 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_LEGACY] {0: <d}".format(coal
.r
.cpu_time_eqos
[4])
458 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_USER_INITIATED] {0: <d}".format(coal
.r
.cpu_time_eqos
[5])
459 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_USER_INTERACTIVE] {0: <d}".format(coal
.r
.cpu_time_eqos
[6])
460 out_string
+= "\n\t Tasks:\n\t\t"
461 tasks
= GetCoalitionTasks(addressof(coal
.r
.tasks
), 0, thread_details
)
462 out_string
+= "\n\t\t".join(tasks
)
465 def GetJetsamCoalitionSummary(coal
, verbose
=False):
466 out_string
= "Jetsam Coalition:"
467 thread_details
= False
468 if config
['verbosity'] > vSCRIPT
:
469 thread_details
= True
470 if unsigned(coal
.j
.leader
) == 0:
471 out_string
+= "\n\t NO Leader!"
473 out_string
+= "\n\t Leader:\n\t\t"
474 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
))
475 out_string
+= "\n\t Extensions:\n\t\t"
476 tasks
= GetCoalitionTasks(addressof(coal
.j
.extensions
), 1, thread_details
)
477 out_string
+= "\n\t\t".join(tasks
)
478 out_string
+= "\n\t XPC Services:\n\t\t"
479 tasks
= GetCoalitionTasks(addressof(coal
.j
.services
), 1, thread_details
)
480 out_string
+= "\n\t\t".join(tasks
)
481 out_string
+= "\n\t Other Tasks:\n\t\t"
482 tasks
= GetCoalitionTasks(addressof(coal
.j
.other
), 1, thread_details
)
483 out_string
+= "\n\t\t".join(tasks
)
484 out_string
+= "\n\t Thread Group: {0: <#020x}\n".format(coal
.j
.thread_group
)
487 @lldb_type_summary(['coalition_t', 'coalition *'])
488 @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"))
489 def GetCoalitionSummary(coal
):
490 if unsigned(coal
) == 0:
491 return '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'.format(0, "", -1, -1, -1, -1, -1, "")
493 format_string
= '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'
494 type_string
= GetCoalitionTypeString(coal
.type)
495 flag_string
= GetCoalitionFlagString(coal
)
496 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
)
499 def GetCoalitionInfo(coal
, verbose
=False):
500 """ returns a string describing a coalition, including details about the particular coalition type.
502 coal : value object representing a coalition in the kernel
504 str : A string describing the coalition.
506 if unsigned(coal
) == 0:
507 return "<null coalition>"
508 typestr
= GetCoalitionTypeString(coal
.type)
509 flagstr
= GetCoalitionFlagString(coal
)
511 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
)
512 if coal
.type == 0: # COALITION_TYPE_RESOURCE
513 out_string
+= GetResourceCoalitionSummary(coal
, verbose
)
514 elif coal
.type == 1: # COALITION_TYPE_JETSAM
515 out_string
+= GetJetsamCoalitionSummary(coal
, verbose
)
517 out_string
+= "Unknown Type"
521 # Macro: showcoalitioninfo
523 @lldb_command('showcoalitioninfo')
524 def ShowCoalitionInfo(cmd_args
=None, cmd_options
={}):
525 """ Display more detailed information about a coalition
526 Usage: showcoalitioninfo <address of coalition>
529 if config
['verbosity'] > vHUMAN
:
532 raise ArgumentError("No arguments passed")
533 coal
= kern
.GetValueFromAddress(cmd_args
[0], 'coalition *')
535 print "unknown arguments:", str(cmd_args
)
537 print GetCoalitionInfo(coal
, verbose
)
539 # EndMacro: showcoalitioninfo
541 # Macro: showallcoalitions
543 @lldb_command('showallcoalitions')
544 def ShowAllCoalitions(cmd_args
=None):
545 """ Print a summary listing of all the coalitions
548 print GetCoalitionSummary
.header
549 for c
in kern
.coalitions
:
550 print GetCoalitionSummary(c
)
552 # EndMacro: showallcoalitions
554 # Macro: showallthreadgroups
556 @lldb_type_summary(['thread_group_t', 'thread_group *'])
557 @header("{0: <20s} {1: <5s} {2: <16s} {3: <5s} {4: <8s} {5: <20s}".format("thread_group", "id", "name", "refc", "flags", "recommendation"))
558 def GetThreadGroupSummary(tg
):
559 if unsigned(tg
) == 0:
560 return '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'.format(0, -1, "", -1, "", -1)
562 format_string
= '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'
564 if (tg
.tg_flags
& 0x1):
566 if (tg
.tg_flags
& 0x2):
568 out_string
+= format_string
.format(tg
, tg
.tg_id
, tg
.tg_name
, tg
.tg_refcount
, tg_flags
, tg
.tg_recommendation
)
571 @lldb_command('showallthreadgroups')
572 def ShowAllThreadGroups(cmd_args
=None):
573 """ Print a summary listing of all thread groups
576 print GetThreadGroupSummary
.header
577 for tg
in kern
.thread_groups
:
578 print GetThreadGroupSummary(tg
)
580 # EndMacro: showallthreadgroups
582 # Macro: showtaskcoalitions
584 @lldb_command('showtaskcoalitions', 'F:')
585 def ShowTaskCoalitions(cmd_args
=None, cmd_options
={}):
589 if "-F" in cmd_options
:
590 task_list
= FindTasksByName(cmd_options
["-F"])
592 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
595 raise ArgumentError("No arguments passed")
597 if len(task_list
) > 0:
598 print GetCoalitionSummary
.header
599 for task
in task_list
:
600 print GetCoalitionSummary(task
.coalition
[0])
601 print GetCoalitionSummary(task
.coalition
[1])
603 # EndMacro: showtaskcoalitions
605 @lldb_type_summary(['proc', 'proc *'])
606 @header("{0: >6s} {1: ^20s} {2: >14s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command"))
607 def GetProcSummary(proc
):
608 """ Summarize the process data.
610 proc : value - value representaitng a proc * in kernel
612 str - string summary of the process.
615 format_string
= "{0: >6d} {1: >#020x} {2: >14s} {3: >2d} {4: >2d} {5: >2d} {6: <20s}"
616 pval
= proc
.GetSBValue()
617 #code.interact(local=locals())
618 if str(pval
.GetType()) != str(gettype('proc *')) :
619 return "Unknown type " + str(pval
.GetType()) + " " + str(hex(proc
))
621 out_string
+= "Process " + hex(proc
) + " is not valid."
623 pid
= int(proc
.p_pid
)
624 proc_addr
= int(hex(proc
), 16)
626 if int(proc
.p_lflag
) & 0x400000 :
627 proc_rage_str
= "RAGE"
629 task
= Cast(proc
.task
, 'task *')
633 if int(task
.effective_policy
.tep_darwinbg
) != 0:
635 if int(task
.effective_policy
.tep_lowpri_cpu
) != 0:
638 if int(task
.effective_policy
.tep_io_tier
) != 0:
640 if int(task
.effective_policy
.tep_io_passive
) != 0:
642 if int(task
.effective_policy
.tep_terminated
) != 0:
645 if int(task
.effective_policy
.tep_latency_qos
) != 0:
647 if int(task
.effective_policy
.tep_sup_active
) != 0:
652 work_queue
= Cast(proc
.p_wqptr
, 'workqueue *')
653 if proc
.p_wqptr
!= 0 :
654 wq_num_threads
= int(work_queue
.wq_nthreads
)
655 wq_idle_threads
= int(work_queue
.wq_thidlecount
)
656 wq_req_threads
= int(work_queue
.wq_reqcount
)
665 process_name
= str(proc
.p_comm
)
666 if process_name
== 'xpcproxy':
667 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
668 thread_name
= GetThreadName(thread
)
670 process_name
+= ' (' + thread_name
+ ')'
672 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
)
675 @lldb_type_summary(['tty_dev_t', 'tty_dev_t *'])
676 @header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","master", "slave", "open", "free", "name", "revoke"))
677 def GetTTYDevSummary(tty_dev
):
678 """ Summarizes the important fields in tty_dev_t structure.
679 params: tty_dev: value - value object representing a tty_dev_t in kernel
680 returns: str - summary of the tty_dev
683 format_string
= "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"
684 open_fn
= kern
.Symbolicate(int(hex(tty_dev
.open), 16))
685 free_fn
= kern
.Symbolicate(int(hex(tty_dev
.free
), 16))
686 name_fn
= kern
.Symbolicate(int(hex(tty_dev
.name
), 16))
687 revoke_fn
= kern
.Symbolicate(int(hex(tty_dev
.revoke
), 16))
688 out_string
+= format_string
.format(tty_dev
, tty_dev
.master
, tty_dev
.slave
, open_fn
, free_fn
, name_fn
, revoke_fn
)
693 @lldb_command('showtask', 'F:')
694 def ShowTask(cmd_args
=None, cmd_options
={}):
695 """ Routine to print a summary listing of given task
696 Usage: showtask <address of task>
697 or : showtask -F <name of task>
700 if "-F" in cmd_options
:
701 task_list
= FindTasksByName(cmd_options
['-F'])
704 raise ArgumentError("Invalid arguments passed.")
706 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
708 raise ("Unknown arguments: %r" % cmd_args
)
709 task_list
.append(tval
)
711 for tval
in task_list
:
712 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
713 pval
= Cast(tval
.bsd_info
, 'proc *')
714 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
720 @lldb_command('showpid')
721 def ShowPid(cmd_args
=None):
722 """ Routine to print a summary listing of task corresponding to given pid
723 Usage: showpid <pid value>
726 raise ArgumentError("No arguments passed")
727 pidval
= ArgumentStringToInt(cmd_args
[0])
729 pval
= Cast(t
.bsd_info
, 'proc *')
730 if pval
and pval
.p_pid
== pidval
:
731 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
732 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
739 @lldb_command('showproc')
740 def ShowProc(cmd_args
=None):
741 """ Routine to print a summary listing of task corresponding to given proc
742 Usage: showproc <address of proc>
745 raise ArgumentError("No arguments passed")
746 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
748 print "unknown arguments:", str(cmd_args
)
750 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
751 tval
= Cast(pval
.task
, 'task *')
752 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
756 # Macro: showprocinfo
758 @lldb_command('showprocinfo')
759 def ShowProcInfo(cmd_args
=None):
760 """ Routine to display name, pid, parent & task for the given proc address
761 It also shows the Cred, Flags and state of the process
762 Usage: showprocinfo <address of proc>
765 raise ArgumentError("No arguments passed")
766 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
768 print "unknown arguments:", str(cmd_args
)
770 print GetProcInfo(pval
)
772 # EndMacro: showprocinfo
774 #Macro: showprocfiles
776 @lldb_command('showprocfiles')
777 def ShowProcFiles(cmd_args
=None):
778 """ Given a proc_t pointer, display the list of open file descriptors for the referenced process.
779 Usage: showprocfiles <proc_t>
782 print ShowProcFiles
.__doc
__
784 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t')
785 proc_filedesc
= proc
.p_fd
786 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
787 proc_ofiles
= proc_filedesc
.fd_ofiles
788 if unsigned(proc_ofiles
) == 0:
789 print 'No open files for proc {0: <s}'.format(cmd_args
[0])
791 print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')
792 print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")
795 while count
<= proc_lastfile
:
796 if unsigned(proc_ofiles
[count
]) != 0:
798 proc_fd_flags
= proc_ofiles
[count
].f_flags
799 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
800 out_str
+= "{0: <5d} ".format(count
)
801 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
))
802 out_str
+= "0x{0:0>8x} ".format(unsigned(proc_fd_flags
))
803 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
804 if proc_fd_ftype
in xnudefines
.filetype_strings
:
805 out_str
+= "{0: <8s} ".format(xnudefines
.filetype_strings
[proc_fd_ftype
])
807 out_str
+= "?: {0: <5d} ".format(proc_fd_ftype
)
808 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
.fg_data
))
809 if proc_fd_ftype
== 1:
810 fd_name
= Cast(proc_fd_fglob
.fg_data
, 'struct vnode *').v_name
811 out_str
+= "{0: <64s}".format(fd_name
)
816 #EndMacro: showprocfiles
820 @lldb_command('showtty')
821 def ShowTTY(cmd_args
=None):
822 """ Display information about a struct tty
823 Usage: showtty <tty struct>
826 print ShowTTY
.__doc
__
829 tty
= kern
.GetValueFromAddress(cmd_args
[0], 'struct tty *')
830 print "TTY structure at: {0: <s}".format(cmd_args
[0])
831 print "Last input to raw queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_rawq
.c_cs
), tty
.t_rawq
.c_cs
)
832 print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_canq
.c_cs
), tty
.t_canq
.c_cs
)
833 print "Last output data: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_outq
.c_cs
), tty
.t_outq
.c_cs
)
835 ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'],
836 ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'],
837 ['', 'TS_BUSY (Draining output)'],
838 ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'],
839 ['', 'TS_FLUSH (Outq has been flushed during DMA)'],
840 ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'],
841 ['', 'TS_TBLOCK (Further input blocked)'],
842 ['', 'TS_TIMEOUT (Wait for output char processing)'],
843 ['', 'TS_TTSTOP (Output paused)'],
844 ['', 'TS_WOPEN (Open in progress)'],
845 ['', 'TS_XCLUDE (Tty requires exclusivity)'],
846 ['', 'TS_BKSL (State for lowercase \\ work)'],
847 ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'],
848 ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'],
849 ['', 'TS_LNCH (Next character is literal)'],
850 ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'],
851 ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'],
852 ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'],
853 ['', 'TS_SNOOP (Device is being snooped on)'],
854 ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'],
855 ['', 'TS_ZOMBIE (Connection lost)'],
856 ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'],
857 ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'],
858 ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)']
862 tty_state
= unsigned(tty
.t_state
)
865 if tty_state
& mask
!= 0:
866 if len(tty_state_info
[index
][1]) > 0:
867 print '\t' + tty_state_info
[index
][1]
869 if len(tty_state_info
[index
][0]) > 0:
870 print '\t' + tty_state_info
[index
][0]
873 print "Flags: 0x{0:0>8x}".format(unsigned(tty
.t_flags
))
874 print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty
.t_pgrp
))
875 print "Enclosing session: 0x{0:0>16x}".format(unsigned(tty
.t_session
))
877 print "\tInput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_iflag
))
878 print "\tOutput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_oflag
))
879 print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_cflag
))
880 print "\tLocal Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_lflag
))
881 print "\tInput Speed: {0: <8d}".format(tty
.t_termios
.c_ispeed
)
882 print "\tOutput Speed: {0: <8d}".format(tty
.t_termios
.c_ospeed
)
883 print "High Watermark: {0: <d} bytes".format(tty
.t_hiwat
)
884 print "Low Watermark : {0: <d} bytes".format(tty
.t_lowat
)
888 #Macro showallttydevs
890 @lldb_command('showallttydevs')
891 def ShowAllTTYDevs(cmd_args
=[], cmd_options
={}):
892 """ Show a list of ttydevs registered in the system.
896 tty_dev_head
= kern
.globals.tty_dev_head
897 tty_dev
= tty_dev_head
898 print GetTTYDevSummary
.header
899 while unsigned(tty_dev
) != 0:
900 print GetTTYDevSummary(tty_dev
)
901 tty_dev
= tty_dev
.next
904 #EndMacro: showallttydevs
906 #Macro: dumpthread_terminate_queue
908 @lldb_command('dumpthread_terminate_queue')
909 def DumpThreadTerminateQueue(cmd_args
=None):
910 """ Displays the contents of the specified call_entry queue.
911 Usage: dumpthread_terminate_queue
915 print GetThreadSummary
.header
916 for th
in IterateQueue(addressof(kern
.globals.thread_terminate_queue
), 'struct thread *', 'q_link'):
917 print GetThreadSummary(th
)
919 print "{0: <d} entries!".format(count
)
921 #EndMacro: dumpthread_terminate_queue
923 #Macro: dumpcrashed_thread_queue
925 @lldb_command('dumpcrashed_thread_queue')
926 def DumpCrashedThreadsQueue(cmd_args
=None):
927 """ Displays the contents of the specified call_entry queue.
928 Usage: dumpcrashed_thread_queue
932 print GetThreadSummary
.header
933 for th
in IterateQueue(addressof(kern
.globals.crashed_threads_queue
), 'struct thread *', 'q_link'):
934 print GetThreadSummary(th
)
936 print "{0: <d} entries!".format(count
)
938 #EndMacro: dumpcrashed_thread_queue
940 #Macro: dumpcallqueue
942 @lldb_command('dumpcallqueue')
943 def DumpCallQueue(cmd_args
=None):
944 """ Displays the contents of the specified call_entry queue.
945 Usage: dumpcallqueue <queue_head_t *>
948 raise ArgumentError("Invalid arguments")
950 print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
951 callhead
= kern
.GetValueFromAddress(cmd_args
[0], 'queue_head_t *')
953 for callentry
in IterateQueue(callhead
, 'struct call_entry *', 'q_link'):
954 print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format(
955 unsigned(callentry
), unsigned(callentry
.param0
), unsigned(callentry
.param1
),
956 unsigned(callentry
.deadline
), unsigned(callentry
.func
))
958 print "{0: <d} entries!".format(count
)
960 #EndMacro: dumpcallqueue
962 @lldb_command('showalltasklogicalwrites')
963 def ShowAllTaskIOStats(cmd_args
=None):
964 """ Commad to print I/O stats for all tasks
966 print "{0: <20s} {1: <20s} {2: <20s} {3: <20s} {4: <20s} {5: <20s}".format("task", "Immediate Writes", "Deferred Writes", "Invalidated Writes", "Metadata Writes", "name")
968 pval
= Cast(t
.bsd_info
, 'proc *')
969 print "{0: <#18x} {1: >20d} {2: >20d} {3: >20d} {4: >20d} {5: <20s}".format(t
,
970 t
.task_immediate_writes
,
971 t
.task_deferred_writes
,
972 t
.task_invalidated_writes
,
973 t
.task_metadata_writes
,
977 @lldb_command('showalltasks','C')
978 def ShowAllTasks(cmd_args
=None, cmd_options
={}):
979 """ Routine to print a summary listing of all the tasks
980 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
981 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
982 io_policy -> RAGE - rapid aging of vnodes requested
983 NORM - normal I/O explicitly requested (this is the default)
984 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
985 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
986 Usage: (lldb) showalltasks -C : describe the corpse structure
991 if '-C' in cmd_options
:
993 extra_hdr
+= " " + GetKCDataSummary
.header
995 print GetTaskSummary
.header
+ extra_hdr
+ " " + GetProcSummary
.header
997 pval
= Cast(t
.bsd_info
, 'proc *')
998 out_str
= GetTaskSummary(t
, showcorpse
) + " " + GetProcSummary(pval
)
1002 @lldb_command('taskforpmap')
1003 def TaskForPmap(cmd_args
=None):
1004 """ Find the task whose pmap corresponds to <pmap>.
1005 Syntax: (lldb) taskforpmap <pmap>
1006 Multiple -v's can be specified for increased verbosity
1008 if cmd_args
== None or len(cmd_args
) < 1:
1009 raise ArgumentError("Too few arguments to taskforpmap.")
1010 pmap
= kern
.GetValueFromAddress(cmd_args
[0], 'pmap_t')
1011 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1012 for tasklist
in [kern
.tasks
, kern
.terminated_tasks
]:
1014 if t
.map.pmap
== pmap
:
1015 pval
= Cast(t
.bsd_info
, 'proc *')
1016 out_str
= GetTaskSummary(t
) + " " + GetProcSummary(pval
)
1019 @lldb_command('showterminatedtasks')
1020 def ShowTerminatedTasks(cmd_args
=None):
1021 """ Routine to print a summary listing of all the terminated tasks
1022 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1023 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1024 io_policy -> RAGE - rapid aging of vnodes requested
1025 NORM - normal I/O explicitly requested (this is the default)
1026 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1027 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1028 syntax: (lldb)showallterminatedtasks
1031 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1032 for t
in kern
.terminated_tasks
:
1033 pval
= Cast(t
.bsd_info
, 'proc *')
1034 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1037 # Macro: showtaskstacks
1039 def ShowTaskStacks(task
):
1040 """ Print a task with summary and stack information for each of its threads
1043 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1044 pval
= Cast(task
.bsd_info
, 'proc *')
1045 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1046 for th
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1047 print " " + GetThreadSummary
.header
1048 print " " + GetThreadSummary(th
)
1049 print GetThreadBackTrace(th
, prefix
=" ") + "\n"
1051 def FindTasksByName(searchstr
, ignore_case
=True):
1052 """ Search the list of tasks by name.
1054 searchstr: str - a regex like string to search for task
1055 ignore_case: bool - If False then exact matching will be enforced
1057 [] - array of task object. Empty if not found any
1061 re_options
= re
.IGNORECASE
1062 search_regex
= re
.compile(searchstr
, re_options
)
1064 for t
in kern
.tasks
:
1065 pval
= Cast(t
.bsd_info
, "proc *")
1066 process_name
= "{:s}".format(pval
.p_comm
)
1067 if search_regex
.search(process_name
):
1071 @lldb_command('showtaskstacks', 'F:')
1072 def ShowTaskStacksCmdHelper(cmd_args
=None, cmd_options
={}):
1073 """ Routine to print out the stack for each thread in a task
1074 Usage: showtaskstacks <0xaddress of task>
1075 or: showtaskstacks -F launchd
1078 if "-F" in cmd_options
:
1079 find_task_str
= cmd_options
["-F"]
1080 task_list
= FindTasksByName(find_task_str
)
1081 for tval
in task_list
:
1082 ShowTaskStacks(tval
)
1086 raise ArgumentError("No arguments passed")
1088 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1090 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
1092 ShowTaskStacks(tval
)
1095 # EndMacro: showtaskstacks
1097 def CheckTaskProcRefs(task
, proc
):
1098 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1099 if int(thread
.uthread
) == 0:
1101 uthread
= Cast(thread
.uthread
, 'uthread *')
1102 refcount
= int(uthread
.uu_proc_refcount
)
1103 uu_ref_index
= int(uthread
.uu_pindex
)
1106 for ref
in range(0, uu_ref_index
):
1107 if unsigned(uthread
.uu_proc_ps
[ref
]) == unsigned(proc
):
1108 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1109 pval
= Cast(task
.bsd_info
, 'proc *')
1110 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1111 print "\t" + GetThreadSummary
.header
1112 print "\t" + GetThreadSummary(thread
) + "\n"
1114 for frame
in range (0, 10):
1115 trace_addr
= unsigned(uthread
.uu_proc_pcs
[ref
][frame
])
1116 symbol_arr
= kern
.SymbolicateFromAddress(unsigned(trace_addr
))
1118 symbol_str
= str(symbol_arr
[0].addr
)
1121 print '{0: <#x} {1: <s}'.format(trace_addr
, symbol_str
)
1124 @lldb_command('showprocrefs')
1125 def ShowProcRefs(cmd_args
= None):
1126 """ Display information on threads/BTs that could be holding a reference on the specified proc
1127 NOTE: We can't say affirmatively if any of these references are still held since
1128 there's no way to pair references with drop-refs in the current infrastructure.
1129 Usage: showprocrefs <proc>
1131 if cmd_args
== None or len(cmd_args
) < 1:
1132 raise ArgumentError("No arguments passed")
1134 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
1136 for t
in kern
.tasks
:
1137 CheckTaskProcRefs(t
, proc
)
1138 for t
in kern
.terminated_tasks
:
1139 CheckTaskProcRefs(t
, proc
)
1143 @lldb_command('showallthreads')
1144 def ShowAllThreads(cmd_args
= None):
1145 """ Display info about all threads in the system
1147 for t
in kern
.tasks
:
1148 ShowTaskThreads([str(int(t
))])
1151 for t
in kern
.terminated_tasks
:
1152 print "Terminated: \n"
1153 ShowTaskThreads([str(int(t
))])
1158 @lldb_command('showtaskthreads', "F:")
1159 def ShowTaskThreads(cmd_args
= None, cmd_options
={}):
1160 """ Display thread information for a given task
1161 Usage: showtaskthreads <0xaddress of task>
1162 or: showtaskthreads -F <name>
1165 if "-F" in cmd_options
:
1166 task_list
= FindTasksByName(cmd_options
["-F"])
1168 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1171 raise ArgumentError("No arguments passed")
1173 for task
in task_list
:
1174 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1175 pval
= Cast(task
.bsd_info
, 'proc *')
1176 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1177 print "\t" + GetThreadSummary
.header
1178 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1179 print "\t" + GetThreadSummary(thval
)
1182 @lldb_command('showact')
1183 def ShowAct(cmd_args
=None):
1184 """ Routine to print out the state of a specific thread.
1185 usage: showact <activation>
1188 raise ArgumentError("No arguments passed")
1189 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1190 print GetThreadSummary
.header
1191 print GetThreadSummary(threadval
)
1193 @lldb_command('showactstack')
1194 def ShowActStack(cmd_args
=None):
1195 """ Routine to print out the stack of a specific thread.
1196 usage: showactstack <activation>
1199 raise ArgumentError("No arguments passed")
1200 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1201 print GetThreadSummary
.header
1202 print GetThreadSummary(threadval
)
1203 print GetThreadBackTrace(threadval
, prefix
="\t")
1206 @lldb_command('switchtoact')
1207 def SwitchToAct(cmd_args
=None):
1208 """ Switch to different context specified by activation
1209 This command allows gdb to examine the execution context and call
1210 stack for the specified activation. For example, to view the backtrace
1211 for an activation issue "switchtoact <address>", followed by "bt".
1212 Before resuming execution, issue a "resetctx" command, to
1213 return to the original execution context.
1215 if cmd_args
is None or len(cmd_args
) < 1:
1216 raise ArgumentError("No arguments passed")
1217 thval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1218 lldbthread
= GetLLDBThreadForKernelThread(thval
)
1219 print GetThreadSummary
.header
1220 print GetThreadSummary(thval
)
1221 LazyTarget
.GetProcess().selected_thread
= lldbthread
1222 if not LazyTarget
.GetProcess().SetSelectedThread(lldbthread
):
1223 print "Failed to switch thread."
1226 @lldb_command('switchtoregs')
1227 def SwitchToRegs(cmd_args
=None):
1228 """ Routine to switch to a register state.
1229 Usage: (lldb) switchtoregs <struct arm_saved_state[64] *>
1230 This command creates a fake thread in lldb with the saved register state.
1231 Note: This command ONLY works for ARM based kernel setup.
1234 if cmd_args
== None or len(cmd_args
) < 1:
1235 raise ArgumentError("No arguments passed")
1237 lldb_process
= LazyTarget
.GetProcess()
1239 saved_state
= ArgumentStringToInt(cmd_args
[0])
1240 # any change to this logic requires change in operating_system.py as well
1241 fake_thread_id
= 0xdead0000 |
(saved_state
& ~
0xffff0000)
1242 fake_thread_id
= fake_thread_id
& 0xdeadffff
1243 lldb_process
.CreateOSPluginThread(0xdeadbeef, saved_state
)
1244 lldbthread
= lldb_process
.GetThreadByID(int(fake_thread_id
))
1246 if not lldbthread
.IsValid():
1247 print "Failed to create thread"
1250 lldb_process
.selected_thread
= lldbthread
1251 if not lldb_process
.SetSelectedThread(lldbthread
):
1252 print "Failed to switch thread"
1253 print "Switched to Fake thread created from register state at 0x%x" % saved_state
1257 # Macro: showallstacks
1258 @lldb_command('showallstacks')
1259 def ShowAllStacks(cmd_args
=None):
1260 """Routine to print out the stack for each thread in the system.
1262 for t
in kern
.tasks
:
1268 # EndMacro: showallstacks
1270 # Macro: showcurrentstacks
1271 @lldb_command('showcurrentstacks')
1272 def ShowCurrentStacks(cmd_args
=None):
1273 """ Routine to print out the thread running on each cpu (incl. its stack)
1275 processor_list
= kern
.GetGlobalVariable('processor_list')
1276 current_processor
= processor_list
1277 while unsigned(current_processor
) > 0:
1278 print "\n" + GetProcessorSummary(current_processor
)
1279 active_thread
= current_processor
.active_thread
1280 if unsigned(active_thread
) != 0 :
1281 task_val
= active_thread
.task
1282 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1283 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1284 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1285 print "\t" + GetThreadSummary
.header
1286 print "\t" + GetThreadSummary(active_thread
)
1287 print "\tBacktrace:"
1288 print GetThreadBackTrace(active_thread
, prefix
="\t")
1289 current_processor
= current_processor
.processor_list
1291 # EndMacro: showcurrentstacks
1293 @lldb_command('showcurrentthreads')
1294 def ShowCurrentThreads(cmd_args
=None):
1295 """ Display info about threads running on each cpu """
1296 processor_list
= kern
.GetGlobalVariable('processor_list')
1297 current_processor
= processor_list
1298 while unsigned(current_processor
) > 0:
1299 print GetProcessorSummary(current_processor
)
1300 active_thread
= current_processor
.active_thread
1301 if unsigned(active_thread
) != 0 :
1302 task_val
= active_thread
.task
1303 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1304 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1305 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1306 print "\t" + GetThreadSummary
.header
1307 print "\t" + GetThreadSummary(active_thread
)
1308 current_processor
= current_processor
.processor_list
1311 def GetFullBackTrace(frame_addr
, verbosity
= vHUMAN
, prefix
= ""):
1312 """ Get backtrace across interrupt context.
1313 params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7)
1314 prefix - str - prefix for each line of output.
1319 frame_ptr
= frame_addr
1320 previous_frame_ptr
= 0
1321 # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
1322 mh_execute_addr
= int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
1323 while frame_ptr
and frame_ptr
!= previous_frame_ptr
and bt_count
< 128:
1324 if (not kern
.arch
.startswith('arm') and frame_ptr
< mh_execute_addr
) or (kern
.arch
.startswith('arm') and frame_ptr
> mh_execute_addr
):
1326 pc_val
= kern
.GetValueFromAddress(frame_ptr
+ kern
.ptrsize
,'uintptr_t *')
1327 pc_val
= unsigned(dereference(pc_val
))
1328 out_string
+= prefix
+ GetSourceInformationForAddress(pc_val
) + "\n"
1330 previous_frame_ptr
= frame_ptr
1331 frame_val
= kern
.GetValueFromAddress((frame_ptr
), 'uintptr_t *')
1332 if unsigned(frame_val
) == 0:
1334 frame_ptr
= unsigned(dereference(frame_val
))
1338 @lldb_command('fullbt')
1339 def FullBackTrace(cmd_args
=[]):
1340 """ Show full backtrace across the interrupt boundary.
1341 Syntax: fullbt <frame ptr>
1342 Example: fullbt `$rbp`
1344 if len(cmd_args
) < 1:
1345 print FullBackTrace
.__doc
__
1347 print GetFullBackTrace(ArgumentStringToInt(cmd_args
[0]), prefix
="\t")
1349 @lldb_command('fullbtall')
1350 def FullBackTraceAll(cmd_args
=[]):
1351 """ Show full backtrace across the interrupt boundary for threads running on all processors.
1355 for processor
in IterateLinkedList(kern
.globals.processor_list
, 'processor_list') :
1356 print "\n" + GetProcessorSummary(processor
)
1357 active_thread
= processor
.active_thread
1358 if unsigned(active_thread
) != 0 :
1359 task_val
= active_thread
.task
1360 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1361 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1362 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1363 print "\t" + GetThreadSummary
.header
1364 print "\t" + GetThreadSummary(active_thread
)
1365 print "\tBacktrace:"
1367 ThreadVal
= GetLLDBThreadForKernelThread(active_thread
)
1369 FramePtr
= ThreadVal
.frames
[0].GetFP()
1371 print GetFullBackTrace(unsigned(FramePtr
), prefix
="\t")
1374 @lldb_command('symbolicate')
1375 def SymbolicateAddress(cmd_args
=[]):
1376 """ Symbolicate an address for symbol information from loaded symbols
1377 Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr"
1379 if len(cmd_args
) < 1:
1380 print "Invalid address.\nSyntax: symbolicate <address>"
1382 print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args
[0]))
1385 @lldb_command('showinitchild')
1386 def ShowInitChild(cmd_args
=None):
1387 """ Routine to print out all processes in the system
1388 which are children of init process
1390 headp
= kern
.globals.initproc
.p_children
1391 for pp
in IterateListEntry(headp
, 'struct proc *', 'p_sibling'):
1392 print GetProcInfo(pp
)
1395 @lldb_command('showproctree')
1396 def ShowProcTree(cmd_args
=None):
1397 """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes.
1398 If no argument is given, showproctree will print all the processes in the system.
1399 If pid is specified, showproctree prints all the descendants of the indicated process
1403 search_pid
= ArgumentStringToInt(cmd_args
[0])
1406 print "pid specified must be a positive number"
1407 print ShowProcTree
.__doc
__
1410 hdr_format
= "{0: <6s} {1: <14s} {2: <9s}\n"
1411 out_string
= hdr_format
.format("PID", "PROCESS", "POINTER")
1412 out_string
+= hdr_format
.format('='*3, '='*7, '='*7)
1413 proc
= GetProcForPid(search_pid
)
1414 out_string
+= "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc
.p_ppid
, proc
.p_pptr
.p_comm
, unsigned(proc
.p_pptr
))
1415 out_string
+= "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc
.p_pid
, proc
.p_comm
, unsigned(proc
))
1417 ShowProcTreeRecurse(proc
, "| ")
1421 def ShowProcTreeRecurse(proc
, prefix
=""):
1422 """ Prints descendants of a given proc in hierarchial tree form
1424 proc : core.value representing a struct proc * in the kernel
1426 str : String containing info about a given proc and its descendants in tree form
1428 if proc
.p_childrencnt
> 0:
1429 head_ptr
= proc
.p_children
.lh_first
1431 for p
in IterateListEntry(proc
.p_children
, 'struct proc *', 'p_sibling'):
1432 print prefix
+ "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p
.p_pid
, p
.p_comm
, unsigned(p
))
1433 ShowProcTreeRecurse(p
, prefix
+ "| ")
1435 @lldb_command('showthreadfortid')
1436 def ShowThreadForTid(cmd_args
=None):
1437 """ The thread structure contains a unique thread_id value for each thread.
1438 This command is used to retrieve the address of the thread structure(thread_t)
1439 corresponding to a given thread_id.
1442 print "Please provide thread_t whose tid you'd like to look up"
1443 print ShowThreadForTid
.__doc
__
1445 search_tid
= ArgumentStringToInt(cmd_args
[0])
1446 for taskp
in kern
.tasks
:
1447 for actp
in IterateQueue(taskp
.threads
, 'struct thread *', 'task_threads'):
1448 if search_tid
== int(actp
.thread_id
):
1449 print "Found {0: #019x}".format(actp
)
1450 print GetThreadSummary
.header
1451 print GetThreadSummary(actp
)
1453 print "Not a valid thread_id"
1455 def GetProcessorSummary(processor
):
1456 """ Internal function to print summary of processor
1457 params: processor - value representing struct processor *
1458 return: str - representing the details of given processor
1461 processor_state_str
= "INVALID"
1462 processor_state
= int(processor
.state
)
1464 processor_states
= {
1468 # 3 (formerly INACTIVE)
1474 if processor_state
in processor_states
:
1475 processor_state_str
= "{0: <11s} ".format(processor_states
[processor_state
])
1477 processor_recommended_str
= ""
1478 if int(processor
.is_recommended
) == 0:
1479 processor_recommended_str
= " (not recommended)"
1482 preemption_disable
= 0
1483 preemption_disable_str
= ""
1485 if kern
.arch
== 'x86_64':
1486 cpu_data
= kern
.globals.cpu_data_ptr
[processor
.cpu_id
]
1487 if (cpu_data
!= 0) :
1488 ast
= cpu_data
.cpu_pending_ast
1489 preemption_disable
= cpu_data
.cpu_preemption_level
1490 # On arm64, it's kern.globals.CpuDataEntries[processor.cpu_id].cpu_data_vaddr
1491 # but LLDB can't find CpuDataEntries...
1493 ast_str
= GetASTSummary(ast
)
1495 if (preemption_disable
!= 0) :
1496 preemption_disable_str
= "Preemption Disabled"
1498 out_str
= "Processor {: <#018x} cpu_id {:>#4x} AST: {:<6s} State {:<s}{:<s} {:<s}\n".format(
1499 processor
, int(processor
.cpu_id
), ast_str
, processor_state_str
, processor_recommended_str
,
1500 preemption_disable_str
)
1503 def GetLedgerEntrySummary(ledger_template
, ledger
, i
):
1504 """ Internal function to get internals of a ledger entry (*not* a ledger itself)
1505 params: ledger_template - value representing struct ledger_template_t for the task or thread
1506 ledger - value representing struct ledger_entry *
1507 return: str - formatted output information of ledger entries
1509 ledger_limit_infinity
= (uint64_t(0x1).value
<< 63) - 1
1510 lf_refill_scheduled
= 0x0400
1511 lf_tracking_max
= 0x4000
1514 now
= unsigned(kern
.globals.sched_tick
) / 20
1517 out_str
+= "{: >32s} {:<2d}:".format(ledger_template
.lt_entries
[i
].et_key
, i
)
1518 out_str
+= "{: >15d} ".format(unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
))
1519 if (ledger
.le_flags
& lf_tracking_max
):
1520 out_str
+= "{:9d} {:5d} ".format(ledger
._le
.le_maxtracking
.le_peaks
[0].le_max
, now
- unsigned(ledger
._le
.le_maxtracking
.le_peaks
[0].le_time
))
1524 if (ledger
.le_flags
& lf_tracking_max
):
1525 out_str
+= "{:12d} ".format(ledger
._le
.le_maxtracking
.le_lifetime_max
)
1528 out_str
+= "{:12d} {:12d} ".format(unsigned(ledger
.le_credit
), unsigned(ledger
.le_debit
))
1529 if (unsigned(ledger
.le_limit
) != ledger_limit_infinity
):
1530 out_str
+= "{:12d} ".format(unsigned(ledger
.le_limit
))
1534 if (ledger
.le_flags
& lf_refill_scheduled
):
1535 out_str
+= "{:15d} ".format(ledger
._le
.le_refill
.le_refill_period
)
1539 if (ledger
.le_flags
& lf_refill_scheduled
):
1540 out_str
+= "{:9d} ".format((unsigned(ledger
.le_limit
) * 100) / ledger
._le
.le_refill
.le_refill_period
)
1544 if (unsigned(ledger
.le_warn_level
) != ledger_limit_infinity
):
1545 out_str
+= "{:9d} ".format((unsigned(ledger
.le_warn_level
) * 100) / unsigned(ledger
.le_limit
))
1549 if ((unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
)) > unsigned(ledger
.le_limit
)):
1554 out_str
+= "{:#8x}\n".format(ledger
.le_flags
)
1557 def GetThreadLedgerSummary(thread_val
):
1558 """ Internal function to get a summary of ledger entries for the given thread
1559 params: thread - value representing struct thread *
1560 return: str - formatted output information for ledger entries of the input thread
1562 out_str
= " [{:#08x}]\n".format(thread_val
)
1563 ledgerp
= thread_val
.t_threadledger
1566 while i
!= ledgerp
.l_template
.lt_cnt
:
1567 out_str
+= GetLedgerEntrySummary(kern
.globals.thread_ledger_template
,
1568 ledgerp
.l_entries
[i
], i
)
1572 @header("{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >9s} {5: >6s} {6: >12s} {7: >11s} \
1573 {8: >7s} {9: >13s} {10: <15s} {11: <8s} {12: <9s} {13: <6s} {14: >6s}".format(
1574 "task [thread]", "entry", "#", "balance", "peakA", "(age)", "lifemax", "credit",
1575 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags"))
1576 def GetTaskLedgers(task_val
):
1577 """ Internal function to get summary of ledger entries from the task and its threads
1578 params: task_val - value representing struct task *
1579 return: str - formatted output information for ledger entries of the input task
1582 task_ledgerp
= task_val
.ledger
1584 out_str
+= "{: #08x} ".format(task_val
)
1585 pval
= Cast(task_val
.bsd_info
, 'proc *')
1587 out_str
+= "{: <5s}:\n".format(pval
.p_comm
)
1589 out_str
+= "Invalid process:\n"
1590 while i
!= task_ledgerp
.l_template
.lt_cnt
:
1591 out_str
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, task_ledgerp
.l_entries
[i
], i
)
1595 for thval
in IterateQueue(task_val
.threads
, 'thread *', 'task_threads'):
1596 out_str
+= GetThreadLedgerSummary(thval
)
1600 # Macro: showtaskledgers
1602 @lldb_command('showtaskledgers', 'F:')
1603 def ShowTaskLedgers(cmd_args
=None, cmd_options
={}):
1604 """ Routine to print a summary of ledger entries for the task and all of its threads
1605 Usage: showtaskledgers <address of task>
1606 or : showtaskledgers -F <name of task>
1608 if "-F" in cmd_options
:
1609 task_list
= FindTasksByName(cmd_options
["-F"])
1610 for tval
in task_list
:
1611 print GetTaskLedgers
.header
1612 print GetTaskLedgers(tval
)
1616 raise ArgumentError("No arguments passed.")
1617 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1619 raise ArgumentError("unknown arguments: %r" %cmd
_args
)
1620 print GetTaskLedgers
.header
1621 print GetTaskLedgers(tval
)
1623 # EndMacro: showtaskledgers
1625 # Macro: showalltaskledgers
1627 @lldb_command('showalltaskledgers')
1628 def ShowAllTaskLedgers(cmd_args
=None):
1629 """ Routine to print a summary of ledger entries for all tasks and respective threads
1630 Usage: showalltaskledgers
1632 for t
in kern
.tasks
:
1633 task_val
= unsigned(t
)
1634 ShowTaskLedgers([task_val
])
1636 # EndMacro: showalltaskledgers
1638 # Macro: showprocuuidpolicytable
1640 @lldb_type_summary(['proc_uuid_policy_entry'])
1641 @header("{0: <36s} {1: <10s}".format("uuid", "flags"))
1642 def GetProcUUIDPolicyEntrySummary(entry
):
1643 """ Summarizes the important fields in proc_uuid_policy_entry structure.
1644 params: entry: value - value object representing an entry
1645 returns: str - summary of the entry
1649 data
.append(int(entry
.uuid
[i
]))
1650 flags
= unsigned(entry
.flags
)
1651 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
)
1654 @lldb_command('showprocuuidpolicytable')
1655 def ShowProcUUIDPolicyTable(cmd_args
=None):
1656 """ Routine to print the proc UUID policy table
1657 Usage: showprocuuidpolicytable
1659 hashslots
= unsigned(kern
.globals.proc_uuid_policy_hash_mask
)
1660 print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary
.header
1661 for i
in range(0, hashslots
+1):
1662 headp
= addressof(kern
.globals.proc_uuid_policy_hashtbl
[i
])
1664 for entry
in IterateListEntry(headp
, 'struct proc_uuid_policy_entry *', 'entries'):
1665 print "{0: >2d}.{1: <5d} ".format(i
, entrynum
) + GetProcUUIDPolicyEntrySummary(entry
)
1669 # EndMacro: showprocuuidpolicytable
1671 @lldb_command('showalltaskpolicy')
1672 def ShowAllTaskPolicy(cmd_args
=None):
1674 Routine to print a summary listing of all the tasks
1675 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1676 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1677 io_policy -> RAGE - rapid aging of vnodes requested
1678 NORM - normal I/O explicitly requested (this is the default)
1679 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1680 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1683 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1684 for t
in kern
.tasks
:
1685 pval
= Cast(t
.bsd_info
, 'proc *')
1686 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1687 requested_strings
= [
1688 ["int_darwinbg", "DBG-int"],
1689 ["ext_darwinbg", "DBG-ext"],
1690 ["int_iotier", "iotier-int"],
1691 ["ext_iotier", "iotier-ext"],
1692 ["int_iopassive", "passive-int"],
1693 ["ext_iopassive", "passive-ext"],
1694 ["bg_iotier", "bg-iotier"],
1695 ["terminated", "terminated"],
1696 ["th_pidbind_bg", "bg-pidbind"],
1697 ["t_apptype", "apptype"],
1698 ["t_boosted", "boosted"],
1700 ["t_tal_enabled", "tal-enabled"],
1701 ["t_base_latency_qos", "latency-base"],
1702 ["t_over_latency_qos", "latency-override"],
1703 ["t_base_through_qos", "throughput-base"],
1704 ["t_over_through_qos", "throughput-override"]
1708 for value
in requested_strings
:
1709 if t
.requested_policy
.__getattr
__(value
[0]) :
1710 requested
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1714 suppression_strings
= [
1715 ["t_sup_active", "active"],
1716 ["t_sup_lowpri_cpu", "lowpri-cpu"],
1717 ["t_sup_timer", "timer-throttling"],
1718 ["t_sup_disk", "disk-throttling"],
1719 ["t_sup_cpu_limit", "cpu-limits"],
1720 ["t_sup_suspend", "suspend"],
1721 ["t_sup_bg_sockets", "bg-sockets"]
1725 for value
in suppression_strings
:
1726 if t
.requested_policy
.__getattr
__(value
[0]) :
1727 suppression
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1731 effective_strings
= [
1732 ["darwinbg", "background"],
1733 ["lowpri_cpu", "lowpri-cpu"],
1734 ["io_tier", "iotier"],
1735 ["io_passive", "passive"],
1736 ["all_sockets_bg", "bg-allsockets"],
1737 ["new_sockets_bg", "bg-newsockets"],
1738 ["bg_iotier", "bg-iotier"],
1739 ["terminated", "terminated"],
1740 ["t_gpu_deny", "gpu-deny"],
1741 ["t_tal_engaged", "tal-engaged"],
1742 ["t_suspended", "suspended"],
1743 ["t_watchers_bg", "bg-watchers"],
1744 ["t_latency_qos", "latency-qos"],
1745 ["t_through_qos", "throughput-qos"],
1746 ["t_sup_active", "suppression-active"],
1751 for value
in effective_strings
:
1752 if t
.effective_policy
.__getattr
__(value
[0]) :
1753 effective
+=value
[1] + ": " + str(t
.effective_policy
.__getattr
__(value
[0])) + " "
1757 print "requested: " + requested
1758 print "suppression: " + suppression
1759 print "effective: " + effective
1762 @lldb_type_summary(['wait_queue', 'wait_queue_t'])
1763 @header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask"))
1764 def GetWaitQSummary(waitq
):
1765 """ Summarizes the important fields in task structure.
1766 params: task: value - value object representing a task in kernel
1767 returns: str - summary of the task
1770 format_string
= '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
1774 if (waitq
.wq_fifo
== 1) :
1779 if (waitq
.wq_prepost
== 1) :
1782 if (waitq
.wq_type
== 0x3) :
1784 elif (waitq
.wq_type
== 0x2) :
1789 out_string
+= format_string
.format(waitq
, unsigned(waitq
.wq_interlock
.lock_data
), policy
, 0, 0, unsigned(waitq
.wq_eventmask
))
1791 out_string
+= "\n" + GetThreadSummary
.header
1793 for thread
in IterateQueue(waitq
.wq_queue
, "thread_t", "links"):
1794 out_string
+= "\n" + GetThreadSummary(thread
)
1799 @lldb_command('showallsuspendedtasks', '')
1800 def ShowSuspendedTasks(cmd_args
=[], options
={}):
1801 """ Show a list of suspended tasks with their process name summary.
1803 print GetTaskSummary
.header
+ ' ' + GetProcSummary
.header
1804 for t
in kern
.tasks
:
1805 if t
.suspend_count
> 0:
1806 print GetTaskSummary(t
) + ' ' + GetProcSummary(Cast(t
.bsd_info
, 'proc *'))
1810 @lldb_command('showallpte')
1811 def ShowAllPte(cmd_args
=None):
1812 """ Prints out the physical address of the pte for all tasks
1814 head_taskp
= addressof(kern
.globals.tasks
)
1815 taskp
= Cast(head_taskp
.next
, 'task *')
1816 while taskp
!= head_taskp
:
1817 procp
= Cast(taskp
.bsd_info
, 'proc *')
1818 out_str
= "task = {:#x} pte = {:#x}\t".format(taskp
, taskp
.map.pmap
.ttep
)
1820 out_str
+= "{:s}\n".format(procp
.p_comm
)
1824 taskp
= Cast(taskp
.tasks
.next
, 'struct task *')
1826 # EndMacro: showallpte
1828 # Macro: showallrefcounts
1829 @lldb_command('showallrefcounts')
1830 @header("{0: <20s} {1: ^10s}".format("task", "ref_count"))
1831 def ShowAllRefCounts(cmd_args
=None):
1832 """ Prints the ref_count of all tasks
1835 head_taskp
= addressof(kern
.globals.tasks
)
1836 taskp
= Cast(head_taskp
.next
, 'task *')
1837 print ShowAllRefCounts
.header
1838 while taskp
!= head_taskp
:
1839 out_str
+= "{: <#20x}".format(taskp
)
1840 out_str
+= "{: ^10d}\n".format(taskp
.ref_count
)
1841 taskp
= Cast(taskp
.tasks
.next
, 'task *')
1843 # EndMacro: showallrefcounts
1845 # Macro: showallrunnablethreads
1846 @lldb_command('showallrunnablethreads')
1847 def ShowAllRunnableThreads(cmd_args
=None):
1848 """ Prints the sched usage information for all threads of each task
1851 for taskp
in kern
.tasks
:
1852 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1853 if int(actp
.state
& 0x4):
1854 ShowActStack([unsigned(actp
)])
1856 # EndMacro: showallrunnablethreads
1858 # Macro: showallschedusage
1859 @lldb_command('showallschedusage')
1860 @header("{0:<20s} {1:^10s} {2:^10s} {3:^15s}".format("Thread", "Priority", "State", "sched_usage"))
1861 def ShowAllSchedUsage(cmd_args
=None):
1862 """ Prints the sched usage information for all threads of each task
1865 for taskp
in kern
.tasks
:
1866 ShowTask([unsigned(taskp
)])
1867 print ShowAllSchedUsage
.header
1868 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1869 out_str
= "{: <#20x}".format(actp
)
1870 out_str
+= "{: ^10s}".format(str(int(actp
.sched_pri
)))
1871 state
= int(actp
.state
)
1872 thread_state_chars
= {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'}
1874 state_str
+= thread_state_chars
[int(state
& 0x1)]
1875 state_str
+= thread_state_chars
[int(state
& 0x2)]
1876 state_str
+= thread_state_chars
[int(state
& 0x4)]
1877 state_str
+= thread_state_chars
[int(state
& 0x8)]
1878 state_str
+= thread_state_chars
[int(state
& 0x10)]
1879 state_str
+= thread_state_chars
[int(state
& 0x20)]
1880 state_str
+= thread_state_chars
[int(state
& 0x40)]
1881 state_str
+= thread_state_chars
[int(state
& 0x80)]
1882 out_str
+= "{: ^10s}".format(state_str
)
1883 out_str
+= "{: >15d}".format(actp
.sched_usage
)
1884 print out_str
+ "\n"
1887 # EndMacro: showallschedusage
1889 #Macro: showprocfilessummary
1890 @lldb_command('showprocfilessummary')
1891 @header("{0: <20s} {1: <20s} {2: >10s}".format("Process", "Name", "Number of Open Files"))
1892 def ShowProcFilesSummary(cmd_args
=None):
1893 """ Display the summary of open file descriptors for all processes in task list
1894 Usage: showprocfilessummary
1896 print ShowProcFilesSummary
.header
1897 for proc
in kern
.procs
:
1898 proc_filedesc
= proc
.p_fd
1899 proc_ofiles
= proc_filedesc
.fd_ofiles
1900 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
1903 if proc_filedesc
.fd_nfiles
!= 0:
1904 while count
<= proc_lastfile
:
1905 if unsigned(proc_ofiles
[count
]) != 0:
1906 proc_file_count
+= 1
1908 print "{0: <#020x} {1: <20s} {2: >10d}".format(proc
, proc
.p_comm
, proc_file_count
)
1910 #EndMacro: showprocfilessummary
1912 @lldb_command('workinguserstacks')
1913 def WorkingUserStacks(cmd_args
=None):
1914 """ Print out the user stack for each thread in a task, followed by the user libraries.
1915 Syntax: (lldb) workinguserstacks <task_t>
1918 print "Insufficient arguments" + ShowTaskUserStacks
.__doc
__
1920 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1921 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1922 pval
= Cast(task
.bsd_info
, 'proc *')
1923 print GetTaskSummary(task
) + " " + GetProcSummary(pval
) + "\n \n"
1924 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1925 print "For thread 0x{0:x}".format(thval
)
1927 ShowThreadUserStack([hex(thval
)])
1928 except Exception as exc_err
:
1929 print "Failed to show user stack for thread 0x{0:x}".format(thval
)
1933 print "Enable debugging ('(lldb) xnudebug debug') to see detailed trace."
1934 WorkingUserLibraries([hex(task
)])
1937 @static_var("exec_load_path", 0)
1938 @lldb_command("workingkuserlibraries")
1939 def WorkingUserLibraries(cmd_args
=None):
1940 """ Show binary images known by dyld in target task
1941 For a given user task, inspect the dyld shared library state and print information about all Mach-O images.
1942 Syntax: (lldb)workinguserlibraries <task_t>
1945 print "Insufficient arguments"
1946 print ShowTaskUserLibraries
.__doc
__
1949 print "{0: <18s} {1: <12s} {2: <36s} {3: <50s}".format('address','type','uuid','path')
1950 out_format
= "0x{0:0>16x} {1: <12s} {2: <36s} {3: <50s}"
1951 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t')
1952 is_task_64
= int(task
.t_flags
) & 0x1
1953 dyld_all_image_infos_address
= unsigned(task
.all_image_info_addr
)
1955 if dyld_all_image_infos_address
== 0:
1956 print "No dyld shared library information available for task"
1958 vers_info_data
= GetUserDataAsString(task
, dyld_all_image_infos_address
, 112)
1959 version
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
1960 cur_data_offset
+= 4
1962 print "Unknown dyld all_image_infos version number %d" % version
1963 image_info_count
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
1964 WorkingUserLibraries
.exec_load_path
= 0
1966 image_info_size
= 24
1967 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 8, "uint64_t")
1968 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 8*4, "uint64_t")
1969 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 8*13, "uint64_t")
1971 image_info_size
= 12
1972 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 4*2, "uint32_t")
1973 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 4*5, "uint32_t")
1974 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 4*14, "uint32_t")
1975 # Account for ASLR slide before dyld can fix the structure
1976 dyld_load_address
= dyld_load_address
+ (dyld_all_image_infos_address
- dyld_all_image_infos_address_from_struct
)
1979 while i
< image_info_count
:
1980 image_info_address
= image_info_array_address
+ i
* image_info_size
1981 img_data
= GetUserDataAsString(task
, image_info_address
, image_info_size
)
1983 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint64_t")
1984 image_info_path
= _ExtractDataFromString(img_data
, 8, "uint64_t")
1986 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint32_t")
1987 image_info_path
= _ExtractDataFromString(img_data
, 4, "uint32_t")
1988 PrintImageInfo(task
, image_info_addr
, image_info_path
)
1991 # load_path might get set when the main executable is processed.
1992 if WorkingUserLibraries
.exec_load_path
!= 0:
1993 PrintImageInfo(task
, dyld_load_address
, WorkingUserLibraries
.exec_load_path
)
1996 # Macro: showstackaftertask
1997 @lldb_command('showstackaftertask','F:')
1998 def Showstackaftertask(cmd_args
=None,cmd_options
={}):
1999 """ Routine to print the thread stacks for all tasks succeeding a given task
2000 Usage: showstackaftertask <0xaddress of task>
2001 or: showstackaftertask -F <taskname>
2003 if "-F" in cmd_options
:
2004 # Find the task pointer corresponding to its task name
2005 find_task_str
= cmd_options
["-F"]
2006 task_list
= FindTasksByName(find_task_str
)
2008 # Iterate through the list of tasks and print all task stacks thereafter
2009 for tval
in task_list
:
2010 ListTaskStacks(tval
)
2014 raise ArgumentError("Insufficient arguments")
2015 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
2017 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
2019 ListTaskStacks(tval
)
2023 # EndMacro: showstackaftertask
2025 def ListTaskStacks(task
):
2026 """ Search for a given task and print the list of all task stacks thereafter.
2028 # Initialize local variable task_flag to mark when a given task is found.
2031 for t
in kern
.tasks
:
2032 if (task_flag
== 1):
2038 # Macro: showstackafterthread
2039 @lldb_command('showstackafterthread')
2040 def Showstackafterthread(cmd_args
= None):
2041 """ Routine to print the stacks of all threads succeeding a given thread.
2042 Usage: Showstackafterthread <0xaddress of thread>
2044 # local variable thread_flag is used to mark when a given thread is found.
2047 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
2049 raise ArgumentError("No arguments passed")
2050 # Iterate through list of all tasks to look up a given thread
2051 for t
in kern
.tasks
:
2053 pval
= Cast(t
.bsd_info
, 'proc *')
2054 print GetTaskSummary
.header
+ " "+ GetProcSummary
.header
2055 print GetTaskSummary(t
) + " "+ GetProcSummary(pval
)
2057 # Look up for a given thread from the the list of threads of a given task
2058 for thval
in IterateQueue(t
.threads
, 'thread *', 'task_threads'):
2059 if (thread_flag
==1):
2061 print " " + GetThreadSummary
.header
2062 print " " + GetThreadSummary(thval
)
2063 print GetThreadBackTrace(thval
, prefix
="\t")+"\n"
2066 if(thval
==threadval
):
2067 pval
= Cast(t
.bsd_info
, 'proc *')
2068 process_name
= "{:s}".format(pval
.p_comm
)
2070 print " *** Continuing to dump the thread stacks from the process *** :" + " " + process_name