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
187 thread_state_chars
= {0x0:'', 0x1:'P', 0x2:'Q', 0x4:'U', 0x8:'H', 0x10:'Y', 0x20:'A',
188 0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M',
189 0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S',
190 0x20000: 'D', 0x40000: 'I', 0x80000: 'E', 0x100000: 'R', 0x200000: 'N'}
193 while mask
<= 0x80000:
194 state_str
+= thread_state_chars
[int(state
& mask
)]
200 @lldb_type_summary(['kcdata_descriptor *', 'kcdata_descriptor_t'])
201 @header("{0: <20s} {1: <20s} {2: <20s} {3: <10s} {4: <5s}".format("kcdata_descriptor", "begin_addr", "cur_pos", "size", "flags"))
202 def GetKCDataSummary(kcdata
):
203 """ Summarizes kcdata_descriptor structure
204 params: kcdata: value - value object representing kcdata_descriptor
205 returns: str - summary of the kcdata object
207 format_string
= "{0: <#020x} {1: <#020x} {2: <#020x} {3: <10d} {4: <#05x}"
208 return format_string
.format(kcdata
, kcdata
.kcd_addr_begin
, kcdata
.kcd_addr_end
, kcdata
.kcd_length
, kcdata
.kcd_flags
)
211 @lldb_type_summary(['task', 'task_t'])
212 @header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags"))
213 def GetTaskSummary(task
, showcorpse
=False):
214 """ Summarizes the important fields in task structure.
215 params: task: value - value object representing a task in kernel
216 returns: str - summary of the task
219 format_string
= '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}'
220 thread_count
= int(task
.thread_count
)
222 if hasattr(task
, "suppression_generation") and (int(task
.suppression_generation
) & 0x1) == 0x1:
224 if hasattr(task
, "effective_policy") and int(task
.effective_policy
.tep_sup_active
) == 1:
226 if hasattr(task
, "suspend_count") and int(task
.suspend_count
) > 0:
228 if hasattr(task
, 'task_imp_base') and unsigned(task
.task_imp_base
):
229 tib
= task
.task_imp_base
230 if int(tib
.iit_receiver
) == 1:
232 if int(tib
.iit_donor
) == 1:
234 if int(tib
.iit_assertcnt
) > 0:
237 # check if corpse flag is set
238 if unsigned(task
.t_flags
) & 0x20:
240 if unsigned(task
.t_flags
) & 0x40:
243 out_string
+= format_string
.format(task
, task
.map, task
.itk_space
, thread_count
, task_flags
)
244 if showcorpse
is True and unsigned(task
.corpse_info
) != 0:
245 out_string
+= " " + GetKCDataSummary(task
.corpse_info
)
248 def GetThreadName(thread
):
249 """ Get the name of a thread, if possible. Returns the empty string
252 if int(thread
.uthread
) != 0:
253 uthread
= Cast(thread
.uthread
, 'uthread *')
254 if int(uthread
.pth_name
) != 0 :
255 th_name_strval
= Cast(uthread
.pth_name
, 'char *')
256 if len(str(th_name_strval
)) > 0 :
257 return str(th_name_strval
)
261 @lldb_type_summary(['thread *', 'thread_t'])
262 @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'))
263 def GetThreadSummary(thread
):
264 """ Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct.
265 params: thread: value - value objecte representing a thread in kernel
266 returns: str - summary of a thread
274 A - Terminated and on termination queue
285 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}"
286 thread_ptr_str
= str("{0: <#020x}".format(thread
))
287 if int(thread
.static_param
) :
288 thread_ptr_str
+="[WQ]"
289 thread_id
= hex(thread
.thread_id
)
290 processor
= hex(thread
.last_processor
)
291 base_priority
= str(int(thread
.base_pri
))
292 sched_priority
= str(int(thread
.sched_pri
))
294 mode
= str(thread
.sched_mode
)
295 if "TIMESHARE" in mode
:
296 sched_mode
+="timeshare"
297 elif "FIXED" in mode
:
299 elif "REALTIME" in mode
:
300 sched_mode
+="realtime"
302 if (unsigned(thread
.bound_processor
) != 0):
306 if (unsigned(thread
.sched_flags
) & 0x0004):
310 thread_name
= GetThreadName(thread
)
311 if int(thread
.uthread
) != 0:
312 uthread
= Cast(thread
.uthread
, 'uthread *')
314 #check for io_policy flags
315 if int(uthread
.uu_flag
) & 0x400:
316 io_policy_str
+='RAGE '
318 #now flags for task_policy
322 if int(thread
.effective_policy
.thep_darwinbg
) != 0:
324 if int(thread
.effective_policy
.thep_io_tier
) != 0:
326 if int(thread
.effective_policy
.thep_io_passive
) != 0:
328 if int(thread
.effective_policy
.thep_terminated
) != 0:
331 state
= int(thread
.state
)
332 thread_state_chars
= {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
336 state_str
+= thread_state_chars
[int(state
& mask
)]
339 if int(thread
.inspection
):
342 ast
= int(thread
.ast
) |
int(thread
.reason
)
343 ast_str
= GetASTSummary(ast
)
345 #wait queue information
349 if ( state
& 0x1 ) != 0:
350 #we need to look at the waitqueue as well
351 wait_queue_str
= str("{0: <#020x}".format(int(hex(thread
.waitq
), 16)))
352 wait_event_str
= str("{0: <#020x}".format(int(hex(thread
.wait_event
), 16)))
353 wait_event_str_sym
= kern
.Symbolicate(int(hex(thread
.wait_event
), 16))
354 if len(wait_event_str_sym
) > 0:
355 wait_event_str
= wait_event_str
.strip() + " <" + wait_event_str_sym
+ ">"
356 if int(thread
.uthread
) != 0 :
357 uthread
= Cast(thread
.uthread
, 'uthread *')
358 if int(uthread
.uu_wmesg
) != 0:
359 wait_message
= str(Cast(uthread
.uu_wmesg
, 'char *'))
361 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
)
365 def GetTaskRoleString(role
):
367 0 : "TASK_UNSPECIFIED",
368 1 : "TASK_FOREGROUND_APPLICATION",
369 2 : "TASK_BACKGROUND_APPLICATION",
370 3 : "TASK_CONTROL_APPLICATION",
371 4 : "TASK_GRAPHICS_SERVER",
372 5 : "TASK_THROTTLE_APPLICATION",
373 6 : "TASK_NONUI_APPLICATION",
374 7 : "TASK_DEFAULT_APPLICATION",
376 return role_strs
[int(role
)]
378 def GetCoalitionFlagString(coal
):
380 if (coal
.privileged
):
381 flags
.append('privileged')
382 if (coal
.termrequested
):
383 flags
.append('termrequested')
384 if (coal
.terminated
):
385 flags
.append('terminated')
387 flags
.append('reaped')
389 flags
.append('notified')
391 flags
.append('efficient')
392 return "|".join(flags
)
394 def GetCoalitionTasks(queue
, coal_type
, thread_details
=False):
396 0x0 : "SFI_CLASS_UNSPECIFIED",
397 0x1 : "SFI_CLASS_DARWIN_BG",
398 0x2 : "SFI_CLASS_APP_NAP",
399 0x3 : "SFI_CLASS_MANAGED_FOCAL",
400 0x4 : "SFI_CLASS_MANAGED_NONFOCAL",
401 0x5 : "SFI_CLASS_DEFAULT_FOCAL",
402 0x6 : "SFI_CLASS_DEFAULT_NONFOCAL",
403 0x7 : "SFI_CLASS_KERNEL",
404 0x8 : "SFI_CLASS_OPTED_OUT",
405 0x9 : "SFI_CLASS_UTILITY",
406 0xA : "SFI_CLASS_LEGACY_FOCAL",
407 0xB : "SFI_CLASS_LEGACY_NONFOCAL",
408 0xC : "SFI_CLASS_USER_INITIATED_FOCAL",
409 0xD : "SFI_CLASS_USER_INITIATED_NONFOCAL",
410 0xE : "SFI_CLASS_USER_INTERACTIVE_FOCAL",
411 0xF : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL",
412 0x10 : "SFI_CLASS_MAINTENANCE",
415 field_name
= 'task_coalition'
416 for task
in IterateLinkageChain(queue
, 'task *', field_name
, coal_type
* sizeof('queue_chain_t')):
417 task_str
= "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task
),task
,GetProcNameForTask(task
),GetTaskRoleString(task
.effective_policy
.tep_role
))
419 for thread
in IterateQueue(task
.threads
, "thread_t", "task_threads"):
420 task_str
+= "\n\t\t\t|-> thread:" + hex(thread
) + ", " + sfi_strs
[int(thread
.sfi_class
)]
421 tasks
.append(task_str
)
424 def GetCoalitionTypeString(type):
425 """ Convert a coalition type field into a string
426 Currently supported types (from <mach/coalition.h>):
427 COALITION_TYPE_RESOURCE
428 COALITION_TYPE_JETSAM
430 if type == 0: # COALITION_TYPE_RESOURCE
436 def GetResourceCoalitionSummary(coal
, verbose
=False):
437 """ Summarize a resource coalition
439 out_string
= "Resource Coalition:\n\t Ledger:\n"
440 thread_details
= False
441 if config
['verbosity'] > vSCRIPT
:
442 thread_details
= True
443 ledgerp
= coal
.r
.ledger
444 if verbose
and unsigned(ledgerp
) != 0:
446 while i
!= ledgerp
.l_template
.lt_cnt
:
448 out_string
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, ledgerp
.l_entries
[i
], i
)
450 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
)
451 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
)
452 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
)
453 out_string
+= "\n\t cpu_ptime {0: <d}".format(coal
.r
.cpu_ptime
)
455 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_DEFAULT] {0: <d}".format(coal
.r
.cpu_time_eqos
[0])
456 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_MAINTENANCE] {0: <d}".format(coal
.r
.cpu_time_eqos
[1])
457 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_BACKGROUND] {0: <d}".format(coal
.r
.cpu_time_eqos
[2])
458 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_UTILITY] {0: <d}".format(coal
.r
.cpu_time_eqos
[3])
459 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_LEGACY] {0: <d}".format(coal
.r
.cpu_time_eqos
[4])
460 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_USER_INITIATED] {0: <d}".format(coal
.r
.cpu_time_eqos
[5])
461 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_USER_INTERACTIVE] {0: <d}".format(coal
.r
.cpu_time_eqos
[6])
462 out_string
+= "\n\t Tasks:\n\t\t"
463 tasks
= GetCoalitionTasks(addressof(coal
.r
.tasks
), 0, thread_details
)
464 out_string
+= "\n\t\t".join(tasks
)
467 def GetJetsamCoalitionSummary(coal
, verbose
=False):
468 out_string
= "Jetsam Coalition:"
469 thread_details
= False
470 if config
['verbosity'] > vSCRIPT
:
471 thread_details
= True
472 if unsigned(coal
.j
.leader
) == 0:
473 out_string
+= "\n\t NO Leader!"
475 out_string
+= "\n\t Leader:\n\t\t"
476 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
))
477 out_string
+= "\n\t Extensions:\n\t\t"
478 tasks
= GetCoalitionTasks(addressof(coal
.j
.extensions
), 1, thread_details
)
479 out_string
+= "\n\t\t".join(tasks
)
480 out_string
+= "\n\t XPC Services:\n\t\t"
481 tasks
= GetCoalitionTasks(addressof(coal
.j
.services
), 1, thread_details
)
482 out_string
+= "\n\t\t".join(tasks
)
483 out_string
+= "\n\t Other Tasks:\n\t\t"
484 tasks
= GetCoalitionTasks(addressof(coal
.j
.other
), 1, thread_details
)
485 out_string
+= "\n\t\t".join(tasks
)
486 out_string
+= "\n\t Thread Group: {0: <#020x}\n".format(coal
.j
.thread_group
)
489 @lldb_type_summary(['coalition_t', 'coalition *'])
490 @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"))
491 def GetCoalitionSummary(coal
):
492 if unsigned(coal
) == 0:
493 return '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'.format(0, "", -1, -1, -1, -1, -1, "")
495 format_string
= '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'
496 type_string
= GetCoalitionTypeString(coal
.type)
497 flag_string
= GetCoalitionFlagString(coal
)
498 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
)
501 def GetCoalitionInfo(coal
, verbose
=False):
502 """ returns a string describing a coalition, including details about the particular coalition type.
504 coal : value object representing a coalition in the kernel
506 str : A string describing the coalition.
508 if unsigned(coal
) == 0:
509 return "<null coalition>"
510 typestr
= GetCoalitionTypeString(coal
.type)
511 flagstr
= GetCoalitionFlagString(coal
)
513 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
)
514 if coal
.type == 0: # COALITION_TYPE_RESOURCE
515 out_string
+= GetResourceCoalitionSummary(coal
, verbose
)
516 elif coal
.type == 1: # COALITION_TYPE_JETSAM
517 out_string
+= GetJetsamCoalitionSummary(coal
, verbose
)
519 out_string
+= "Unknown Type"
523 # Macro: showcoalitioninfo
525 @lldb_command('showcoalitioninfo')
526 def ShowCoalitionInfo(cmd_args
=None, cmd_options
={}):
527 """ Display more detailed information about a coalition
528 Usage: showcoalitioninfo <address of coalition>
531 if config
['verbosity'] > vHUMAN
:
534 raise ArgumentError("No arguments passed")
535 coal
= kern
.GetValueFromAddress(cmd_args
[0], 'coalition *')
537 print "unknown arguments:", str(cmd_args
)
539 print GetCoalitionInfo(coal
, verbose
)
541 # EndMacro: showcoalitioninfo
543 # Macro: showallcoalitions
545 @lldb_command('showallcoalitions')
546 def ShowAllCoalitions(cmd_args
=None):
547 """ Print a summary listing of all the coalitions
550 print GetCoalitionSummary
.header
551 for c
in kern
.coalitions
:
552 print GetCoalitionSummary(c
)
554 # EndMacro: showallcoalitions
556 # Macro: showallthreadgroups
558 @lldb_type_summary(['struct thread_group *', 'thread_group *'])
559 @header("{0: <20s} {1: <5s} {2: <16s} {3: <5s} {4: <8s} {5: <20s}".format("thread_group", "id", "name", "refc", "flags", "recommendation"))
560 def GetThreadGroupSummary(tg
):
561 if unsigned(tg
) == 0:
562 return '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'.format(0, -1, "", -1, "", -1)
564 format_string
= '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'
566 if (tg
.tg_flags
& 0x1):
568 if (tg
.tg_flags
& 0x2):
570 out_string
+= format_string
.format(tg
, tg
.tg_id
, tg
.tg_name
, tg
.tg_refcount
, tg_flags
, tg
.tg_recommendation
)
573 @lldb_command('showallthreadgroups')
574 def ShowAllThreadGroups(cmd_args
=None):
575 """ Print a summary listing of all thread groups
578 print GetThreadGroupSummary
.header
579 for tg
in kern
.thread_groups
:
580 print GetThreadGroupSummary(tg
)
582 # EndMacro: showallthreadgroups
584 # Macro: showtaskcoalitions
586 @lldb_command('showtaskcoalitions', 'F:')
587 def ShowTaskCoalitions(cmd_args
=None, cmd_options
={}):
591 if "-F" in cmd_options
:
592 task_list
= FindTasksByName(cmd_options
["-F"])
594 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
597 raise ArgumentError("No arguments passed")
599 if len(task_list
) > 0:
600 print GetCoalitionSummary
.header
601 for task
in task_list
:
602 print GetCoalitionSummary(task
.coalition
[0])
603 print GetCoalitionSummary(task
.coalition
[1])
605 # EndMacro: showtaskcoalitions
607 @lldb_type_summary(['proc', 'proc *'])
608 @header("{0: >6s} {1: ^20s} {2: >14s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command"))
609 def GetProcSummary(proc
):
610 """ Summarize the process data.
612 proc : value - value representaitng a proc * in kernel
614 str - string summary of the process.
617 format_string
= "{0: >6d} {1: >#020x} {2: >14s} {3: >2d} {4: >2d} {5: >2d} {6: <20s}"
618 pval
= proc
.GetSBValue()
619 #code.interact(local=locals())
620 if str(pval
.GetType()) != str(gettype('proc *')) :
621 return "Unknown type " + str(pval
.GetType()) + " " + str(hex(proc
))
623 out_string
+= "Process " + hex(proc
) + " is not valid."
625 pid
= int(proc
.p_pid
)
626 proc_addr
= int(hex(proc
), 16)
628 if int(proc
.p_lflag
) & 0x400000 :
629 proc_rage_str
= "RAGE"
631 task
= Cast(proc
.task
, 'task *')
635 if int(task
.effective_policy
.tep_darwinbg
) != 0:
637 if int(task
.effective_policy
.tep_lowpri_cpu
) != 0:
640 if int(task
.effective_policy
.tep_io_tier
) != 0:
642 if int(task
.effective_policy
.tep_io_passive
) != 0:
644 if int(task
.effective_policy
.tep_terminated
) != 0:
647 if int(task
.effective_policy
.tep_latency_qos
) != 0:
649 if int(task
.effective_policy
.tep_sup_active
) != 0:
654 work_queue
= Cast(proc
.p_wqptr
, 'workqueue *')
655 if proc
.p_wqptr
!= 0 :
656 wq_num_threads
= int(work_queue
.wq_nthreads
)
657 wq_idle_threads
= int(work_queue
.wq_thidlecount
)
658 wq_req_threads
= int(work_queue
.wq_reqcount
)
667 process_name
= str(proc
.p_comm
)
668 if process_name
== 'xpcproxy':
669 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
670 thread_name
= GetThreadName(thread
)
672 process_name
+= ' (' + thread_name
+ ')'
674 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
)
677 @lldb_type_summary(['tty_dev_t', 'tty_dev_t *'])
678 @header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","master", "slave", "open", "free", "name", "revoke"))
679 def GetTTYDevSummary(tty_dev
):
680 """ Summarizes the important fields in tty_dev_t structure.
681 params: tty_dev: value - value object representing a tty_dev_t in kernel
682 returns: str - summary of the tty_dev
685 format_string
= "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"
686 open_fn
= kern
.Symbolicate(int(hex(tty_dev
.open), 16))
687 free_fn
= kern
.Symbolicate(int(hex(tty_dev
.free
), 16))
688 name_fn
= kern
.Symbolicate(int(hex(tty_dev
.name
), 16))
689 revoke_fn
= kern
.Symbolicate(int(hex(tty_dev
.revoke
), 16))
690 out_string
+= format_string
.format(tty_dev
, tty_dev
.master
, tty_dev
.slave
, open_fn
, free_fn
, name_fn
, revoke_fn
)
695 @lldb_command('showtask', 'F:')
696 def ShowTask(cmd_args
=None, cmd_options
={}):
697 """ Routine to print a summary listing of given task
698 Usage: showtask <address of task>
699 or : showtask -F <name of task>
702 if "-F" in cmd_options
:
703 task_list
= FindTasksByName(cmd_options
['-F'])
706 raise ArgumentError("Invalid arguments passed.")
708 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
710 raise ("Unknown arguments: %r" % cmd_args
)
711 task_list
.append(tval
)
713 for tval
in task_list
:
714 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
715 pval
= Cast(tval
.bsd_info
, 'proc *')
716 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
722 @lldb_command('showpid')
723 def ShowPid(cmd_args
=None):
724 """ Routine to print a summary listing of task corresponding to given pid
725 Usage: showpid <pid value>
728 raise ArgumentError("No arguments passed")
729 pidval
= ArgumentStringToInt(cmd_args
[0])
731 pval
= Cast(t
.bsd_info
, 'proc *')
732 if pval
and pval
.p_pid
== pidval
:
733 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
734 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
741 @lldb_command('showproc')
742 def ShowProc(cmd_args
=None):
743 """ Routine to print a summary listing of task corresponding to given proc
744 Usage: showproc <address of proc>
747 raise ArgumentError("No arguments passed")
748 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
750 print "unknown arguments:", str(cmd_args
)
752 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
753 tval
= Cast(pval
.task
, 'task *')
754 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
758 # Macro: showprocinfo
760 @lldb_command('showprocinfo')
761 def ShowProcInfo(cmd_args
=None):
762 """ Routine to display name, pid, parent & task for the given proc address
763 It also shows the Cred, Flags and state of the process
764 Usage: showprocinfo <address of proc>
767 raise ArgumentError("No arguments passed")
768 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
770 print "unknown arguments:", str(cmd_args
)
772 print GetProcInfo(pval
)
774 # EndMacro: showprocinfo
776 #Macro: showprocfiles
778 @lldb_command('showprocfiles')
779 def ShowProcFiles(cmd_args
=None):
780 """ Given a proc_t pointer, display the list of open file descriptors for the referenced process.
781 Usage: showprocfiles <proc_t>
784 print ShowProcFiles
.__doc
__
786 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t')
787 proc_filedesc
= proc
.p_fd
788 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
789 proc_ofiles
= proc_filedesc
.fd_ofiles
790 if unsigned(proc_ofiles
) == 0:
791 print 'No open files for proc {0: <s}'.format(cmd_args
[0])
793 print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')
794 print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")
797 while count
<= proc_lastfile
:
798 if unsigned(proc_ofiles
[count
]) != 0:
800 proc_fd_flags
= proc_ofiles
[count
].f_flags
801 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
802 out_str
+= "{0: <5d} ".format(count
)
803 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
))
804 out_str
+= "0x{0:0>8x} ".format(unsigned(proc_fd_flags
))
805 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
806 if proc_fd_ftype
in xnudefines
.filetype_strings
:
807 out_str
+= "{0: <8s} ".format(xnudefines
.filetype_strings
[proc_fd_ftype
])
809 out_str
+= "?: {0: <5d} ".format(proc_fd_ftype
)
810 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
.fg_data
))
811 if proc_fd_ftype
== 1:
812 fd_name
= Cast(proc_fd_fglob
.fg_data
, 'struct vnode *').v_name
813 out_str
+= "{0: <64s}".format(fd_name
)
818 #EndMacro: showprocfiles
822 @lldb_command('showtty')
823 def ShowTTY(cmd_args
=None):
824 """ Display information about a struct tty
825 Usage: showtty <tty struct>
828 print ShowTTY
.__doc
__
831 tty
= kern
.GetValueFromAddress(cmd_args
[0], 'struct tty *')
832 print "TTY structure at: {0: <s}".format(cmd_args
[0])
833 print "Last input to raw queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_rawq
.c_cs
), tty
.t_rawq
.c_cs
)
834 print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_canq
.c_cs
), tty
.t_canq
.c_cs
)
835 print "Last output data: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_outq
.c_cs
), tty
.t_outq
.c_cs
)
837 ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'],
838 ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'],
839 ['', 'TS_BUSY (Draining output)'],
840 ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'],
841 ['', 'TS_FLUSH (Outq has been flushed during DMA)'],
842 ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'],
843 ['', 'TS_TBLOCK (Further input blocked)'],
844 ['', 'TS_TIMEOUT (Wait for output char processing)'],
845 ['', 'TS_TTSTOP (Output paused)'],
846 ['', 'TS_WOPEN (Open in progress)'],
847 ['', 'TS_XCLUDE (Tty requires exclusivity)'],
848 ['', 'TS_BKSL (State for lowercase \\ work)'],
849 ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'],
850 ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'],
851 ['', 'TS_LNCH (Next character is literal)'],
852 ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'],
853 ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'],
854 ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'],
855 ['', 'TS_SNOOP (Device is being snooped on)'],
856 ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'],
857 ['', 'TS_ZOMBIE (Connection lost)'],
858 ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'],
859 ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'],
860 ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)']
864 tty_state
= unsigned(tty
.t_state
)
867 if tty_state
& mask
!= 0:
868 if len(tty_state_info
[index
][1]) > 0:
869 print '\t' + tty_state_info
[index
][1]
871 if len(tty_state_info
[index
][0]) > 0:
872 print '\t' + tty_state_info
[index
][0]
875 print "Flags: 0x{0:0>8x}".format(unsigned(tty
.t_flags
))
876 print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty
.t_pgrp
))
877 print "Enclosing session: 0x{0:0>16x}".format(unsigned(tty
.t_session
))
879 print "\tInput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_iflag
))
880 print "\tOutput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_oflag
))
881 print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_cflag
))
882 print "\tLocal Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_lflag
))
883 print "\tInput Speed: {0: <8d}".format(tty
.t_termios
.c_ispeed
)
884 print "\tOutput Speed: {0: <8d}".format(tty
.t_termios
.c_ospeed
)
885 print "High Watermark: {0: <d} bytes".format(tty
.t_hiwat
)
886 print "Low Watermark : {0: <d} bytes".format(tty
.t_lowat
)
890 #Macro showallttydevs
892 @lldb_command('showallttydevs')
893 def ShowAllTTYDevs(cmd_args
=[], cmd_options
={}):
894 """ Show a list of ttydevs registered in the system.
898 tty_dev_head
= kern
.globals.tty_dev_head
899 tty_dev
= tty_dev_head
900 print GetTTYDevSummary
.header
901 while unsigned(tty_dev
) != 0:
902 print GetTTYDevSummary(tty_dev
)
903 tty_dev
= tty_dev
.next
906 #EndMacro: showallttydevs
908 #Macro: dumpthread_terminate_queue
910 @lldb_command('dumpthread_terminate_queue')
911 def DumpThreadTerminateQueue(cmd_args
=None):
912 """ Displays the contents of the specified call_entry queue.
913 Usage: dumpthread_terminate_queue
917 print GetThreadSummary
.header
918 for th
in IterateQueue(addressof(kern
.globals.thread_terminate_queue
), 'struct thread *', 'q_link'):
919 print GetThreadSummary(th
)
921 print "{0: <d} entries!".format(count
)
923 #EndMacro: dumpthread_terminate_queue
925 #Macro: dumpcrashed_thread_queue
927 @lldb_command('dumpcrashed_thread_queue')
928 def DumpCrashedThreadsQueue(cmd_args
=None):
929 """ Displays the contents of the specified call_entry queue.
930 Usage: dumpcrashed_thread_queue
934 print GetThreadSummary
.header
935 for th
in IterateQueue(addressof(kern
.globals.crashed_threads_queue
), 'struct thread *', 'q_link'):
936 print GetThreadSummary(th
)
938 print "{0: <d} entries!".format(count
)
940 #EndMacro: dumpcrashed_thread_queue
942 #Macro: dumpcallqueue
944 @lldb_command('dumpcallqueue')
945 def DumpCallQueue(cmd_args
=None):
946 """ Displays the contents of the specified call_entry queue.
947 Usage: dumpcallqueue <queue_head_t *>
950 raise ArgumentError("Invalid arguments")
952 print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
953 callhead
= kern
.GetValueFromAddress(cmd_args
[0], 'queue_head_t *')
955 for callentry
in IterateQueue(callhead
, 'struct call_entry *', 'q_link'):
956 print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format(
957 unsigned(callentry
), unsigned(callentry
.param0
), unsigned(callentry
.param1
),
958 unsigned(callentry
.deadline
), unsigned(callentry
.func
))
960 print "{0: <d} entries!".format(count
)
962 #EndMacro: dumpcallqueue
964 @lldb_command('showalltasklogicalwrites')
965 def ShowAllTaskIOStats(cmd_args
=None):
966 """ Commad to print I/O stats for all tasks
968 print "{0: <20s} {1: <20s} {2: <20s} {3: <20s} {4: <20s} {5: <20s}".format("task", "Immediate Writes", "Deferred Writes", "Invalidated Writes", "Metadata Writes", "name")
970 pval
= Cast(t
.bsd_info
, 'proc *')
971 print "{0: <#18x} {1: >20d} {2: >20d} {3: >20d} {4: >20d} {5: <20s}".format(t
,
972 t
.task_immediate_writes
,
973 t
.task_deferred_writes
,
974 t
.task_invalidated_writes
,
975 t
.task_metadata_writes
,
979 @lldb_command('showalltasks','C')
980 def ShowAllTasks(cmd_args
=None, cmd_options
={}):
981 """ Routine to print a summary listing of all the tasks
982 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
983 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
984 io_policy -> RAGE - rapid aging of vnodes requested
985 NORM - normal I/O explicitly requested (this is the default)
986 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
987 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
988 Usage: (lldb) showalltasks -C : describe the corpse structure
993 if '-C' in cmd_options
:
995 extra_hdr
+= " " + GetKCDataSummary
.header
997 print GetTaskSummary
.header
+ extra_hdr
+ " " + GetProcSummary
.header
999 pval
= Cast(t
.bsd_info
, 'proc *')
1000 out_str
= GetTaskSummary(t
, showcorpse
) + " " + GetProcSummary(pval
)
1004 @lldb_command('taskforpmap')
1005 def TaskForPmap(cmd_args
=None):
1006 """ Find the task whose pmap corresponds to <pmap>.
1007 Syntax: (lldb) taskforpmap <pmap>
1008 Multiple -v's can be specified for increased verbosity
1010 if cmd_args
== None or len(cmd_args
) < 1:
1011 raise ArgumentError("Too few arguments to taskforpmap.")
1012 pmap
= kern
.GetValueFromAddress(cmd_args
[0], 'pmap_t')
1013 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1014 for tasklist
in [kern
.tasks
, kern
.terminated_tasks
]:
1016 if t
.map.pmap
== pmap
:
1017 pval
= Cast(t
.bsd_info
, 'proc *')
1018 out_str
= GetTaskSummary(t
) + " " + GetProcSummary(pval
)
1021 @lldb_command('showterminatedtasks')
1022 def ShowTerminatedTasks(cmd_args
=None):
1023 """ Routine to print a summary listing of all the terminated tasks
1024 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1025 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1026 io_policy -> RAGE - rapid aging of vnodes requested
1027 NORM - normal I/O explicitly requested (this is the default)
1028 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1029 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1030 syntax: (lldb)showallterminatedtasks
1033 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1034 for t
in kern
.terminated_tasks
:
1035 pval
= Cast(t
.bsd_info
, 'proc *')
1036 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1039 # Macro: showtaskstacks
1041 def ShowTaskStacks(task
):
1042 """ Print a task with summary and stack information for each of its threads
1045 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1046 pval
= Cast(task
.bsd_info
, 'proc *')
1047 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1048 for th
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1049 print " " + GetThreadSummary
.header
1050 print " " + GetThreadSummary(th
)
1051 print GetThreadBackTrace(th
, prefix
=" ") + "\n"
1053 def FindTasksByName(searchstr
, ignore_case
=True):
1054 """ Search the list of tasks by name.
1056 searchstr: str - a regex like string to search for task
1057 ignore_case: bool - If False then exact matching will be enforced
1059 [] - array of task object. Empty if not found any
1063 re_options
= re
.IGNORECASE
1064 search_regex
= re
.compile(searchstr
, re_options
)
1066 for t
in kern
.tasks
:
1067 pval
= Cast(t
.bsd_info
, "proc *")
1068 process_name
= "{:s}".format(pval
.p_comm
)
1069 if search_regex
.search(process_name
):
1073 @lldb_command('showtaskstacks', 'F:')
1074 def ShowTaskStacksCmdHelper(cmd_args
=None, cmd_options
={}):
1075 """ Routine to print out the stack for each thread in a task
1076 Usage: showtaskstacks <0xaddress of task>
1077 or: showtaskstacks -F launchd
1080 if "-F" in cmd_options
:
1081 find_task_str
= cmd_options
["-F"]
1082 task_list
= FindTasksByName(find_task_str
)
1083 for tval
in task_list
:
1084 ShowTaskStacks(tval
)
1088 raise ArgumentError("No arguments passed")
1090 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1092 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
1094 ShowTaskStacks(tval
)
1097 # EndMacro: showtaskstacks
1099 def CheckTaskProcRefs(task
, proc
):
1100 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1101 if int(thread
.uthread
) == 0:
1103 uthread
= Cast(thread
.uthread
, 'uthread *')
1104 refcount
= int(uthread
.uu_proc_refcount
)
1105 uu_ref_index
= int(uthread
.uu_pindex
)
1108 for ref
in range(0, uu_ref_index
):
1109 if unsigned(uthread
.uu_proc_ps
[ref
]) == unsigned(proc
):
1110 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1111 pval
= Cast(task
.bsd_info
, 'proc *')
1112 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1113 print "\t" + GetThreadSummary
.header
1114 print "\t" + GetThreadSummary(thread
) + "\n"
1116 for frame
in range (0, 10):
1117 trace_addr
= unsigned(uthread
.uu_proc_pcs
[ref
][frame
])
1118 symbol_arr
= kern
.SymbolicateFromAddress(unsigned(trace_addr
))
1120 symbol_str
= str(symbol_arr
[0].addr
)
1123 print '{0: <#x} {1: <s}'.format(trace_addr
, symbol_str
)
1126 @lldb_command('showprocrefs')
1127 def ShowProcRefs(cmd_args
= None):
1128 """ Display information on threads/BTs that could be holding a reference on the specified proc
1129 NOTE: We can't say affirmatively if any of these references are still held since
1130 there's no way to pair references with drop-refs in the current infrastructure.
1131 Usage: showprocrefs <proc>
1133 if cmd_args
== None or len(cmd_args
) < 1:
1134 raise ArgumentError("No arguments passed")
1136 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
1138 for t
in kern
.tasks
:
1139 CheckTaskProcRefs(t
, proc
)
1140 for t
in kern
.terminated_tasks
:
1141 CheckTaskProcRefs(t
, proc
)
1145 @lldb_command('showallthreads')
1146 def ShowAllThreads(cmd_args
= None):
1147 """ Display info about all threads in the system
1149 for t
in kern
.tasks
:
1150 ShowTaskThreads([str(int(t
))])
1153 for t
in kern
.terminated_tasks
:
1154 print "Terminated: \n"
1155 ShowTaskThreads([str(int(t
))])
1160 @lldb_command('showtaskthreads', "F:")
1161 def ShowTaskThreads(cmd_args
= None, cmd_options
={}):
1162 """ Display thread information for a given task
1163 Usage: showtaskthreads <0xaddress of task>
1164 or: showtaskthreads -F <name>
1167 if "-F" in cmd_options
:
1168 task_list
= FindTasksByName(cmd_options
["-F"])
1170 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1173 raise ArgumentError("No arguments passed")
1175 for task
in task_list
:
1176 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1177 pval
= Cast(task
.bsd_info
, 'proc *')
1178 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1179 print "\t" + GetThreadSummary
.header
1180 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1181 print "\t" + GetThreadSummary(thval
)
1184 @lldb_command('showact')
1185 def ShowAct(cmd_args
=None):
1186 """ Routine to print out the state of a specific thread.
1187 usage: showact <activation>
1190 raise ArgumentError("No arguments passed")
1191 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1192 print GetThreadSummary
.header
1193 print GetThreadSummary(threadval
)
1195 @lldb_command('showactstack')
1196 def ShowActStack(cmd_args
=None):
1197 """ Routine to print out the stack of a specific thread.
1198 usage: showactstack <activation>
1201 raise ArgumentError("No arguments passed")
1202 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1203 print GetThreadSummary
.header
1204 print GetThreadSummary(threadval
)
1205 print GetThreadBackTrace(threadval
, prefix
="\t")
1208 @lldb_command('switchtoact')
1209 def SwitchToAct(cmd_args
=None):
1210 """ Switch to different context specified by activation
1211 This command allows gdb to examine the execution context and call
1212 stack for the specified activation. For example, to view the backtrace
1213 for an activation issue "switchtoact <address>", followed by "bt".
1214 Before resuming execution, issue a "resetctx" command, to
1215 return to the original execution context.
1217 if cmd_args
is None or len(cmd_args
) < 1:
1218 raise ArgumentError("No arguments passed")
1219 thval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1220 lldbthread
= GetLLDBThreadForKernelThread(thval
)
1221 print GetThreadSummary
.header
1222 print GetThreadSummary(thval
)
1223 LazyTarget
.GetProcess().selected_thread
= lldbthread
1224 if not LazyTarget
.GetProcess().SetSelectedThread(lldbthread
):
1225 print "Failed to switch thread."
1228 @lldb_command('switchtoregs')
1229 def SwitchToRegs(cmd_args
=None):
1230 """ Routine to switch to a register state.
1231 Usage: (lldb) switchtoregs <struct arm_saved_state[64] *>
1232 This command creates a fake thread in lldb with the saved register state.
1233 Note: This command ONLY works for ARM based kernel setup.
1236 if cmd_args
== None or len(cmd_args
) < 1:
1237 raise ArgumentError("No arguments passed")
1239 lldb_process
= LazyTarget
.GetProcess()
1241 saved_state
= ArgumentStringToInt(cmd_args
[0])
1242 # any change to this logic requires change in operating_system.py as well
1243 fake_thread_id
= 0xdead0000 |
(saved_state
& ~
0xffff0000)
1244 fake_thread_id
= fake_thread_id
& 0xdeadffff
1245 lldb_process
.CreateOSPluginThread(0xdeadbeef, saved_state
)
1246 lldbthread
= lldb_process
.GetThreadByID(int(fake_thread_id
))
1248 if not lldbthread
.IsValid():
1249 print "Failed to create thread"
1252 lldb_process
.selected_thread
= lldbthread
1253 if not lldb_process
.SetSelectedThread(lldbthread
):
1254 print "Failed to switch thread"
1255 print "Switched to Fake thread created from register state at 0x%x" % saved_state
1259 # Macro: showallstacks
1260 @lldb_command('showallstacks')
1261 def ShowAllStacks(cmd_args
=None):
1262 """Routine to print out the stack for each thread in the system.
1264 for t
in kern
.tasks
:
1270 # EndMacro: showallstacks
1272 # Macro: showcurrentstacks
1273 @lldb_command('showcurrentstacks')
1274 def ShowCurrentStacks(cmd_args
=None):
1275 """ Routine to print out the thread running on each cpu (incl. its stack)
1277 processor_list
= kern
.GetGlobalVariable('processor_list')
1278 current_processor
= processor_list
1279 while unsigned(current_processor
) > 0:
1280 print "\n" + GetProcessorSummary(current_processor
)
1281 active_thread
= current_processor
.active_thread
1282 if unsigned(active_thread
) != 0 :
1283 task_val
= active_thread
.task
1284 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1285 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1286 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1287 print "\t" + GetThreadSummary
.header
1288 print "\t" + GetThreadSummary(active_thread
)
1289 print "\tBacktrace:"
1290 print GetThreadBackTrace(active_thread
, prefix
="\t")
1291 current_processor
= current_processor
.processor_list
1293 # EndMacro: showcurrentstacks
1295 @lldb_command('showcurrentthreads')
1296 def ShowCurrentThreads(cmd_args
=None):
1297 """ Display info about threads running on each cpu """
1298 processor_list
= kern
.GetGlobalVariable('processor_list')
1299 current_processor
= processor_list
1300 while unsigned(current_processor
) > 0:
1301 print GetProcessorSummary(current_processor
)
1302 active_thread
= current_processor
.active_thread
1303 if unsigned(active_thread
) != 0 :
1304 task_val
= active_thread
.task
1305 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1306 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1307 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1308 print "\t" + GetThreadSummary
.header
1309 print "\t" + GetThreadSummary(active_thread
)
1310 current_processor
= current_processor
.processor_list
1313 def GetFullBackTrace(frame_addr
, verbosity
= vHUMAN
, prefix
= ""):
1314 """ Get backtrace across interrupt context.
1315 params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7)
1316 prefix - str - prefix for each line of output.
1321 frame_ptr
= frame_addr
1322 previous_frame_ptr
= 0
1323 # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
1324 mh_execute_addr
= int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
1325 while frame_ptr
and frame_ptr
!= previous_frame_ptr
and bt_count
< 128:
1326 if (not kern
.arch
.startswith('arm') and frame_ptr
< mh_execute_addr
) or (kern
.arch
.startswith('arm') and frame_ptr
> mh_execute_addr
):
1328 pc_val
= kern
.GetValueFromAddress(frame_ptr
+ kern
.ptrsize
,'uintptr_t *')
1329 pc_val
= unsigned(dereference(pc_val
))
1330 out_string
+= prefix
+ GetSourceInformationForAddress(pc_val
) + "\n"
1332 previous_frame_ptr
= frame_ptr
1333 frame_val
= kern
.GetValueFromAddress((frame_ptr
), 'uintptr_t *')
1334 if unsigned(frame_val
) == 0:
1336 frame_ptr
= unsigned(dereference(frame_val
))
1340 @lldb_command('fullbt')
1341 def FullBackTrace(cmd_args
=[]):
1342 """ Show full backtrace across the interrupt boundary.
1343 Syntax: fullbt <frame ptr>
1344 Example: fullbt `$rbp`
1346 if len(cmd_args
) < 1:
1347 print FullBackTrace
.__doc
__
1349 print GetFullBackTrace(ArgumentStringToInt(cmd_args
[0]), prefix
="\t")
1351 @lldb_command('fullbtall')
1352 def FullBackTraceAll(cmd_args
=[]):
1353 """ Show full backtrace across the interrupt boundary for threads running on all processors.
1357 for processor
in IterateLinkedList(kern
.globals.processor_list
, 'processor_list') :
1358 print "\n" + GetProcessorSummary(processor
)
1359 active_thread
= processor
.active_thread
1360 if unsigned(active_thread
) != 0 :
1361 task_val
= active_thread
.task
1362 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1363 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1364 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1365 print "\t" + GetThreadSummary
.header
1366 print "\t" + GetThreadSummary(active_thread
)
1367 print "\tBacktrace:"
1369 ThreadVal
= GetLLDBThreadForKernelThread(active_thread
)
1371 FramePtr
= ThreadVal
.frames
[0].GetFP()
1373 print GetFullBackTrace(unsigned(FramePtr
), prefix
="\t")
1376 @lldb_command('symbolicate')
1377 def SymbolicateAddress(cmd_args
=[]):
1378 """ Symbolicate an address for symbol information from loaded symbols
1379 Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr"
1381 if len(cmd_args
) < 1:
1382 print "Invalid address.\nSyntax: symbolicate <address>"
1384 print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args
[0]))
1387 @lldb_command('showinitchild')
1388 def ShowInitChild(cmd_args
=None):
1389 """ Routine to print out all processes in the system
1390 which are children of init process
1392 headp
= kern
.globals.initproc
.p_children
1393 for pp
in IterateListEntry(headp
, 'struct proc *', 'p_sibling'):
1394 print GetProcInfo(pp
)
1397 @lldb_command('showproctree')
1398 def ShowProcTree(cmd_args
=None):
1399 """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes.
1400 If no argument is given, showproctree will print all the processes in the system.
1401 If pid is specified, showproctree prints all the descendants of the indicated process
1405 search_pid
= ArgumentStringToInt(cmd_args
[0])
1408 print "pid specified must be a positive number"
1409 print ShowProcTree
.__doc
__
1412 hdr_format
= "{0: <6s} {1: <14s} {2: <9s}\n"
1413 out_string
= hdr_format
.format("PID", "PROCESS", "POINTER")
1414 out_string
+= hdr_format
.format('='*3, '='*7, '='*7)
1415 proc
= GetProcForPid(search_pid
)
1416 out_string
+= "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc
.p_ppid
, proc
.p_pptr
.p_comm
, unsigned(proc
.p_pptr
))
1417 out_string
+= "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc
.p_pid
, proc
.p_comm
, unsigned(proc
))
1419 ShowProcTreeRecurse(proc
, "| ")
1423 def ShowProcTreeRecurse(proc
, prefix
=""):
1424 """ Prints descendants of a given proc in hierarchial tree form
1426 proc : core.value representing a struct proc * in the kernel
1428 str : String containing info about a given proc and its descendants in tree form
1430 if proc
.p_childrencnt
> 0:
1431 head_ptr
= proc
.p_children
.lh_first
1433 for p
in IterateListEntry(proc
.p_children
, 'struct proc *', 'p_sibling'):
1434 print prefix
+ "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p
.p_pid
, p
.p_comm
, unsigned(p
))
1435 ShowProcTreeRecurse(p
, prefix
+ "| ")
1437 @lldb_command('showthreadfortid')
1438 def ShowThreadForTid(cmd_args
=None):
1439 """ The thread structure contains a unique thread_id value for each thread.
1440 This command is used to retrieve the address of the thread structure(thread_t)
1441 corresponding to a given thread_id.
1444 print "Please provide thread_t whose tid you'd like to look up"
1445 print ShowThreadForTid
.__doc
__
1447 search_tid
= ArgumentStringToInt(cmd_args
[0])
1448 for taskp
in kern
.tasks
:
1449 for actp
in IterateQueue(taskp
.threads
, 'struct thread *', 'task_threads'):
1450 if search_tid
== int(actp
.thread_id
):
1451 print "Found {0: #019x}".format(actp
)
1452 print GetThreadSummary
.header
1453 print GetThreadSummary(actp
)
1455 print "Not a valid thread_id"
1457 def GetProcessorSummary(processor
):
1458 """ Internal function to print summary of processor
1459 params: processor - value representing struct processor *
1460 return: str - representing the details of given processor
1463 processor_state_str
= "INVALID"
1464 processor_state
= int(processor
.state
)
1466 processor_states
= {
1470 # 3 (formerly INACTIVE)
1476 if processor_state
in processor_states
:
1477 processor_state_str
= "{0: <11s} ".format(processor_states
[processor_state
])
1479 processor_recommended_str
= ""
1480 if int(processor
.is_recommended
) == 0:
1481 processor_recommended_str
= " (not recommended)"
1484 preemption_disable
= 0
1485 preemption_disable_str
= ""
1487 if kern
.arch
== 'x86_64':
1488 cpu_data
= kern
.globals.cpu_data_ptr
[processor
.cpu_id
]
1489 if (cpu_data
!= 0) :
1490 ast
= cpu_data
.cpu_pending_ast
1491 preemption_disable
= cpu_data
.cpu_preemption_level
1492 # On arm64, it's kern.globals.CpuDataEntries[processor.cpu_id].cpu_data_vaddr
1493 # but LLDB can't find CpuDataEntries...
1495 ast_str
= GetASTSummary(ast
)
1497 if (preemption_disable
!= 0) :
1498 preemption_disable_str
= "Preemption Disabled"
1500 out_str
= "Processor {: <#018x} cpu_id {:>#4x} AST: {:<6s} State {:<s}{:<s} {:<s}\n".format(
1501 processor
, int(processor
.cpu_id
), ast_str
, processor_state_str
, processor_recommended_str
,
1502 preemption_disable_str
)
1505 def GetLedgerEntrySummary(ledger_template
, ledger
, i
, show_footprint_interval_max
=False):
1506 """ Internal function to get internals of a ledger entry (*not* a ledger itself)
1507 params: ledger_template - value representing struct ledger_template_t for the task or thread
1508 ledger - value representing struct ledger_entry *
1509 return: str - formatted output information of ledger entries
1511 ledger_limit_infinity
= (uint64_t(0x1).value
<< 63) - 1
1512 lf_refill_scheduled
= 0x0400
1513 lf_tracking_max
= 0x4000
1516 now
= unsigned(kern
.globals.sched_tick
) / 20
1519 out_str
+= "{: >32s} {:<2d}:".format(ledger_template
.lt_entries
[i
].et_key
, i
)
1520 out_str
+= "{: >15d} ".format(unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
))
1521 if (ledger
.le_flags
& lf_tracking_max
):
1522 if (show_footprint_interval_max
):
1523 out_str
+= "{:12d} ".format(ledger
._le
._le
_max
.le_interval_max
)
1524 out_str
+= "{:14d} ".format(ledger
._le
._le
_max
.le_lifetime_max
)
1526 if (show_footprint_interval_max
):
1529 out_str
+= "{:12d} {:12d} ".format(unsigned(ledger
.le_credit
), unsigned(ledger
.le_debit
))
1530 if (unsigned(ledger
.le_limit
) != ledger_limit_infinity
):
1531 out_str
+= "{:12d} ".format(unsigned(ledger
.le_limit
))
1535 if (ledger
.le_flags
& lf_refill_scheduled
):
1536 out_str
+= "{:15d} ".format(ledger
._le
.le_refill
.le_refill_period
)
1540 if (ledger
.le_flags
& lf_refill_scheduled
):
1541 out_str
+= "{:9d} ".format((unsigned(ledger
.le_limit
) * 100) / ledger
._le
.le_refill
.le_refill_period
)
1545 if (unsigned(ledger
.le_warn_level
) != ledger_limit_infinity
):
1546 out_str
+= "{:9d} ".format((unsigned(ledger
.le_warn_level
) * 100) / unsigned(ledger
.le_limit
))
1550 if ((unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
)) > unsigned(ledger
.le_limit
)):
1555 out_str
+= "{:#8x}\n".format(ledger
.le_flags
)
1558 def GetThreadLedgerSummary(thread_val
):
1559 """ Internal function to get a summary of ledger entries for the given thread
1560 params: thread - value representing struct thread *
1561 return: str - formatted output information for ledger entries of the input thread
1563 out_str
= " [{:#08x}]\n".format(thread_val
)
1564 ledgerp
= thread_val
.t_threadledger
1567 while i
!= ledgerp
.l_template
.lt_cnt
:
1568 out_str
+= GetLedgerEntrySummary(kern
.globals.thread_ledger_template
,
1569 ledgerp
.l_entries
[i
], i
)
1573 def GetTaskLedgers(task_val
, show_footprint_interval_max
=False):
1574 """ Internal function to get summary of ledger entries from the task and its threads
1575 params: task_val - value representing struct task *
1576 return: str - formatted output information for ledger entries of the input task
1579 task_ledgerp
= task_val
.ledger
1581 out_str
+= "{: #08x} ".format(task_val
)
1582 pval
= Cast(task_val
.bsd_info
, 'proc *')
1584 out_str
+= "{: <5s}:\n".format(pval
.p_comm
)
1586 out_str
+= "Invalid process:\n"
1587 while i
!= task_ledgerp
.l_template
.lt_cnt
:
1588 out_str
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, task_ledgerp
.l_entries
[i
], i
, show_footprint_interval_max
)
1592 for thval
in IterateQueue(task_val
.threads
, 'thread *', 'task_threads'):
1593 out_str
+= GetThreadLedgerSummary(thval
)
1597 # Macro: showtaskledgers
1599 @lldb_command('showtaskledgers', 'F:I')
1600 def ShowTaskLedgers(cmd_args
=None, cmd_options
={}):
1601 """ Routine to print a summary of ledger entries for the task and all of its threads
1602 or : showtaskledgers [ -I ] [ -F ] <task>
1604 -I: show footprint interval max (DEV/DEBUG only)
1605 -F: specify task via name instead of address
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 show_footprint_interval_max
= False
1618 if "-I" in cmd_options
:
1619 show_footprint_interval_max
= True
1620 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1622 raise ArgumentError("unknown arguments: %r" %cmd
_args
)
1623 if (show_footprint_interval_max
):
1624 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(
1625 "task [thread]", "entry", "#", "balance", "intrvl_max", "lifetime_max", "credit",
1626 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")
1628 print "{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(
1629 "task [thread]", "entry", "#", "balance", "lifetime_max", "credit",
1630 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")
1631 print GetTaskLedgers(tval
, show_footprint_interval_max
)
1633 # EndMacro: showtaskledgers
1635 # Macro: showalltaskledgers
1637 @lldb_command('showalltaskledgers')
1638 def ShowAllTaskLedgers(cmd_args
=None, cmd_options
={}):
1639 """ Routine to print a summary of ledger entries for all tasks and respective threads
1640 Usage: showalltaskledgers
1642 for t
in kern
.tasks
:
1643 task_val
= unsigned(t
)
1644 ShowTaskLedgers([task_val
], cmd_options
=cmd_options
)
1646 # EndMacro: showalltaskledgers
1648 # Macro: showprocuuidpolicytable
1650 @lldb_type_summary(['proc_uuid_policy_entry'])
1651 @header("{0: <36s} {1: <10s}".format("uuid", "flags"))
1652 def GetProcUUIDPolicyEntrySummary(entry
):
1653 """ Summarizes the important fields in proc_uuid_policy_entry structure.
1654 params: entry: value - value object representing an entry
1655 returns: str - summary of the entry
1659 data
.append(int(entry
.uuid
[i
]))
1660 flags
= unsigned(entry
.flags
)
1661 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
)
1664 @lldb_command('showprocuuidpolicytable')
1665 def ShowProcUUIDPolicyTable(cmd_args
=None):
1666 """ Routine to print the proc UUID policy table
1667 Usage: showprocuuidpolicytable
1669 hashslots
= unsigned(kern
.globals.proc_uuid_policy_hash_mask
)
1670 print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary
.header
1671 for i
in range(0, hashslots
+1):
1672 headp
= addressof(kern
.globals.proc_uuid_policy_hashtbl
[i
])
1674 for entry
in IterateListEntry(headp
, 'struct proc_uuid_policy_entry *', 'entries'):
1675 print "{0: >2d}.{1: <5d} ".format(i
, entrynum
) + GetProcUUIDPolicyEntrySummary(entry
)
1679 # EndMacro: showprocuuidpolicytable
1681 @lldb_command('showalltaskpolicy')
1682 def ShowAllTaskPolicy(cmd_args
=None):
1684 Routine to print a summary listing of all the tasks
1685 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1686 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1687 io_policy -> RAGE - rapid aging of vnodes requested
1688 NORM - normal I/O explicitly requested (this is the default)
1689 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1690 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1693 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1694 for t
in kern
.tasks
:
1695 pval
= Cast(t
.bsd_info
, 'proc *')
1696 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1697 requested_strings
= [
1698 ["int_darwinbg", "DBG-int"],
1699 ["ext_darwinbg", "DBG-ext"],
1700 ["int_iotier", "iotier-int"],
1701 ["ext_iotier", "iotier-ext"],
1702 ["int_iopassive", "passive-int"],
1703 ["ext_iopassive", "passive-ext"],
1704 ["bg_iotier", "bg-iotier"],
1705 ["terminated", "terminated"],
1706 ["th_pidbind_bg", "bg-pidbind"],
1707 ["t_apptype", "apptype"],
1708 ["t_boosted", "boosted"],
1710 ["t_tal_enabled", "tal-enabled"],
1711 ["t_base_latency_qos", "latency-base"],
1712 ["t_over_latency_qos", "latency-override"],
1713 ["t_base_through_qos", "throughput-base"],
1714 ["t_over_through_qos", "throughput-override"]
1718 for value
in requested_strings
:
1719 if t
.requested_policy
.__getattr
__(value
[0]) :
1720 requested
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1724 suppression_strings
= [
1725 ["t_sup_active", "active"],
1726 ["t_sup_lowpri_cpu", "lowpri-cpu"],
1727 ["t_sup_timer", "timer-throttling"],
1728 ["t_sup_disk", "disk-throttling"],
1729 ["t_sup_cpu_limit", "cpu-limits"],
1730 ["t_sup_suspend", "suspend"],
1731 ["t_sup_bg_sockets", "bg-sockets"]
1735 for value
in suppression_strings
:
1736 if t
.requested_policy
.__getattr
__(value
[0]) :
1737 suppression
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1741 effective_strings
= [
1742 ["darwinbg", "background"],
1743 ["lowpri_cpu", "lowpri-cpu"],
1744 ["io_tier", "iotier"],
1745 ["io_passive", "passive"],
1746 ["all_sockets_bg", "bg-allsockets"],
1747 ["new_sockets_bg", "bg-newsockets"],
1748 ["bg_iotier", "bg-iotier"],
1749 ["terminated", "terminated"],
1750 ["t_gpu_deny", "gpu-deny"],
1751 ["t_tal_engaged", "tal-engaged"],
1752 ["t_suspended", "suspended"],
1753 ["t_watchers_bg", "bg-watchers"],
1754 ["t_latency_qos", "latency-qos"],
1755 ["t_through_qos", "throughput-qos"],
1756 ["t_sup_active", "suppression-active"],
1761 for value
in effective_strings
:
1762 if t
.effective_policy
.__getattr
__(value
[0]) :
1763 effective
+=value
[1] + ": " + str(t
.effective_policy
.__getattr
__(value
[0])) + " "
1767 print "requested: " + requested
1768 print "suppression: " + suppression
1769 print "effective: " + effective
1772 @lldb_type_summary(['wait_queue', 'wait_queue_t'])
1773 @header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask"))
1774 def GetWaitQSummary(waitq
):
1775 """ Summarizes the important fields in task structure.
1776 params: task: value - value object representing a task in kernel
1777 returns: str - summary of the task
1780 format_string
= '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
1784 if (waitq
.wq_fifo
== 1) :
1789 if (waitq
.wq_prepost
== 1) :
1792 if (waitq
.wq_type
== 0x3) :
1794 elif (waitq
.wq_type
== 0x2) :
1799 out_string
+= format_string
.format(waitq
, unsigned(waitq
.wq_interlock
.lock_data
), policy
, 0, 0, unsigned(waitq
.wq_eventmask
))
1801 out_string
+= "\n" + GetThreadSummary
.header
1803 for thread
in IterateQueue(waitq
.wq_queue
, "thread_t", "links"):
1804 out_string
+= "\n" + GetThreadSummary(thread
)
1809 @lldb_command('showallsuspendedtasks', '')
1810 def ShowSuspendedTasks(cmd_args
=[], options
={}):
1811 """ Show a list of suspended tasks with their process name summary.
1813 print GetTaskSummary
.header
+ ' ' + GetProcSummary
.header
1814 for t
in kern
.tasks
:
1815 if t
.suspend_count
> 0:
1816 print GetTaskSummary(t
) + ' ' + GetProcSummary(Cast(t
.bsd_info
, 'proc *'))
1820 @lldb_command('showallpte')
1821 def ShowAllPte(cmd_args
=None):
1822 """ Prints out the physical address of the pte for all tasks
1824 head_taskp
= addressof(kern
.globals.tasks
)
1825 taskp
= Cast(head_taskp
.next
, 'task *')
1826 while taskp
!= head_taskp
:
1827 procp
= Cast(taskp
.bsd_info
, 'proc *')
1828 out_str
= "task = {:#x} pte = {:#x}\t".format(taskp
, taskp
.map.pmap
.ttep
)
1830 out_str
+= "{:s}\n".format(procp
.p_comm
)
1834 taskp
= Cast(taskp
.tasks
.next
, 'struct task *')
1836 # EndMacro: showallpte
1838 # Macro: showallrefcounts
1839 @lldb_command('showallrefcounts')
1840 @header("{0: <20s} {1: ^10s}".format("task", "ref_count"))
1841 def ShowAllRefCounts(cmd_args
=None):
1842 """ Prints the ref_count of all tasks
1845 head_taskp
= addressof(kern
.globals.tasks
)
1846 taskp
= Cast(head_taskp
.next
, 'task *')
1847 print ShowAllRefCounts
.header
1848 while taskp
!= head_taskp
:
1849 out_str
+= "{: <#20x}".format(taskp
)
1850 out_str
+= "{: ^10d}\n".format(taskp
.ref_count
)
1851 taskp
= Cast(taskp
.tasks
.next
, 'task *')
1853 # EndMacro: showallrefcounts
1855 # Macro: showallrunnablethreads
1856 @lldb_command('showallrunnablethreads')
1857 def ShowAllRunnableThreads(cmd_args
=None):
1858 """ Prints the sched usage information for all threads of each task
1861 for taskp
in kern
.tasks
:
1862 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1863 if int(actp
.state
& 0x4):
1864 ShowActStack([unsigned(actp
)])
1866 # EndMacro: showallrunnablethreads
1868 # Macro: showallschedusage
1869 @lldb_command('showallschedusage')
1870 @header("{0:<20s} {1:^10s} {2:^10s} {3:^15s}".format("Thread", "Priority", "State", "sched_usage"))
1871 def ShowAllSchedUsage(cmd_args
=None):
1872 """ Prints the sched usage information for all threads of each task
1875 for taskp
in kern
.tasks
:
1876 ShowTask([unsigned(taskp
)])
1877 print ShowAllSchedUsage
.header
1878 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1879 out_str
= "{: <#20x}".format(actp
)
1880 out_str
+= "{: ^10s}".format(str(int(actp
.sched_pri
)))
1881 state
= int(actp
.state
)
1882 thread_state_chars
= {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'}
1884 state_str
+= thread_state_chars
[int(state
& 0x1)]
1885 state_str
+= thread_state_chars
[int(state
& 0x2)]
1886 state_str
+= thread_state_chars
[int(state
& 0x4)]
1887 state_str
+= thread_state_chars
[int(state
& 0x8)]
1888 state_str
+= thread_state_chars
[int(state
& 0x10)]
1889 state_str
+= thread_state_chars
[int(state
& 0x20)]
1890 state_str
+= thread_state_chars
[int(state
& 0x40)]
1891 state_str
+= thread_state_chars
[int(state
& 0x80)]
1892 out_str
+= "{: ^10s}".format(state_str
)
1893 out_str
+= "{: >15d}".format(actp
.sched_usage
)
1894 print out_str
+ "\n"
1897 # EndMacro: showallschedusage
1899 #Macro: showprocfilessummary
1900 @lldb_command('showprocfilessummary')
1901 @header("{0: <20s} {1: <20s} {2: >10s}".format("Process", "Name", "Number of Open Files"))
1902 def ShowProcFilesSummary(cmd_args
=None):
1903 """ Display the summary of open file descriptors for all processes in task list
1904 Usage: showprocfilessummary
1906 print ShowProcFilesSummary
.header
1907 for proc
in kern
.procs
:
1908 proc_filedesc
= proc
.p_fd
1909 proc_ofiles
= proc_filedesc
.fd_ofiles
1910 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
1913 if proc_filedesc
.fd_nfiles
!= 0:
1914 while count
<= proc_lastfile
:
1915 if unsigned(proc_ofiles
[count
]) != 0:
1916 proc_file_count
+= 1
1918 print "{0: <#020x} {1: <20s} {2: >10d}".format(proc
, proc
.p_comm
, proc_file_count
)
1920 #EndMacro: showprocfilessummary
1922 @lldb_command('workinguserstacks')
1923 def WorkingUserStacks(cmd_args
=None):
1924 """ Print out the user stack for each thread in a task, followed by the user libraries.
1925 Syntax: (lldb) workinguserstacks <task_t>
1928 print "Insufficient arguments" + ShowTaskUserStacks
.__doc
__
1930 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1931 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1932 pval
= Cast(task
.bsd_info
, 'proc *')
1933 print GetTaskSummary(task
) + " " + GetProcSummary(pval
) + "\n \n"
1934 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1935 print "For thread 0x{0:x}".format(thval
)
1937 ShowThreadUserStack([hex(thval
)])
1938 except Exception as exc_err
:
1939 print "Failed to show user stack for thread 0x{0:x}".format(thval
)
1943 print "Enable debugging ('(lldb) xnudebug debug') to see detailed trace."
1944 WorkingUserLibraries([hex(task
)])
1947 @static_var("exec_load_path", 0)
1948 @lldb_command("workingkuserlibraries")
1949 def WorkingUserLibraries(cmd_args
=None):
1950 """ Show binary images known by dyld in target task
1951 For a given user task, inspect the dyld shared library state and print information about all Mach-O images.
1952 Syntax: (lldb)workinguserlibraries <task_t>
1955 print "Insufficient arguments"
1956 print ShowTaskUserLibraries
.__doc
__
1959 print "{0: <18s} {1: <12s} {2: <36s} {3: <50s}".format('address','type','uuid','path')
1960 out_format
= "0x{0:0>16x} {1: <12s} {2: <36s} {3: <50s}"
1961 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t')
1962 is_task_64
= int(task
.t_flags
) & 0x1
1963 dyld_all_image_infos_address
= unsigned(task
.all_image_info_addr
)
1965 if dyld_all_image_infos_address
== 0:
1966 print "No dyld shared library information available for task"
1968 vers_info_data
= GetUserDataAsString(task
, dyld_all_image_infos_address
, 112)
1969 version
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
1970 cur_data_offset
+= 4
1972 print "Unknown dyld all_image_infos version number %d" % version
1973 image_info_count
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
1974 WorkingUserLibraries
.exec_load_path
= 0
1976 image_info_size
= 24
1977 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 8, "uint64_t")
1978 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 8*4, "uint64_t")
1979 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 8*13, "uint64_t")
1981 image_info_size
= 12
1982 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 4*2, "uint32_t")
1983 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 4*5, "uint32_t")
1984 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 4*14, "uint32_t")
1985 # Account for ASLR slide before dyld can fix the structure
1986 dyld_load_address
= dyld_load_address
+ (dyld_all_image_infos_address
- dyld_all_image_infos_address_from_struct
)
1989 while i
< image_info_count
:
1990 image_info_address
= image_info_array_address
+ i
* image_info_size
1991 img_data
= GetUserDataAsString(task
, image_info_address
, image_info_size
)
1993 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint64_t")
1994 image_info_path
= _ExtractDataFromString(img_data
, 8, "uint64_t")
1996 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint32_t")
1997 image_info_path
= _ExtractDataFromString(img_data
, 4, "uint32_t")
1998 PrintImageInfo(task
, image_info_addr
, image_info_path
)
2001 # load_path might get set when the main executable is processed.
2002 if WorkingUserLibraries
.exec_load_path
!= 0:
2003 PrintImageInfo(task
, dyld_load_address
, WorkingUserLibraries
.exec_load_path
)
2006 # Macro: showstackaftertask
2007 @lldb_command('showstackaftertask','F:')
2008 def Showstackaftertask(cmd_args
=None,cmd_options
={}):
2009 """ Routine to print the thread stacks for all tasks succeeding a given task
2010 Usage: showstackaftertask <0xaddress of task>
2011 or: showstackaftertask -F <taskname>
2013 if "-F" in cmd_options
:
2014 # Find the task pointer corresponding to its task name
2015 find_task_str
= cmd_options
["-F"]
2016 task_list
= FindTasksByName(find_task_str
)
2018 # Iterate through the list of tasks and print all task stacks thereafter
2019 for tval
in task_list
:
2020 ListTaskStacks(tval
)
2024 raise ArgumentError("Insufficient arguments")
2025 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
2027 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
2029 ListTaskStacks(tval
)
2033 # EndMacro: showstackaftertask
2035 def ListTaskStacks(task
):
2036 """ Search for a given task and print the list of all task stacks thereafter.
2038 # Initialize local variable task_flag to mark when a given task is found.
2041 for t
in kern
.tasks
:
2042 if (task_flag
== 1):
2048 # Macro: showstackafterthread
2049 @lldb_command('showstackafterthread')
2050 def Showstackafterthread(cmd_args
= None):
2051 """ Routine to print the stacks of all threads succeeding a given thread.
2052 Usage: Showstackafterthread <0xaddress of thread>
2054 # local variable thread_flag is used to mark when a given thread is found.
2057 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
2059 raise ArgumentError("No arguments passed")
2060 # Iterate through list of all tasks to look up a given thread
2061 for t
in kern
.tasks
:
2063 pval
= Cast(t
.bsd_info
, 'proc *')
2064 print GetTaskSummary
.header
+ " "+ GetProcSummary
.header
2065 print GetTaskSummary(t
) + " "+ GetProcSummary(pval
)
2067 # Look up for a given thread from the the list of threads of a given task
2068 for thval
in IterateQueue(t
.threads
, 'thread *', 'task_threads'):
2069 if (thread_flag
==1):
2071 print " " + GetThreadSummary
.header
2072 print " " + GetThreadSummary(thval
)
2073 print GetThreadBackTrace(thval
, prefix
="\t")+"\n"
2076 if(thval
==threadval
):
2077 pval
= Cast(t
.bsd_info
, 'proc *')
2078 process_name
= "{:s}".format(pval
.p_comm
)
2080 print " *** Continuing to dump the thread stacks from the process *** :" + " " + process_name