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
176 T - AST_TELEMETRY_USER
177 T - AST_TELEMETRY_KERNEL
178 T - AST_TELEMETRY_WINDOWED
188 thread_state_chars
= {0x0:'', 0x1:'P', 0x2:'Q', 0x4:'U', 0x8:'H', 0x10:'Y', 0x20:'A',
189 0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M', 0x400: 'r',
190 0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S',
191 0x20000: 'D', 0x40000: 'I', 0x80000: 'E', 0x100000: 'R', 0x200000: 'N'}
194 while mask
<= 0x80000:
195 state_str
+= thread_state_chars
[int(state
& mask
)]
201 @lldb_type_summary(['kcdata_descriptor *', 'kcdata_descriptor_t'])
202 @header("{0: <20s} {1: <20s} {2: <20s} {3: <10s} {4: <5s}".format("kcdata_descriptor", "begin_addr", "cur_pos", "size", "flags"))
203 def GetKCDataSummary(kcdata
):
204 """ Summarizes kcdata_descriptor structure
205 params: kcdata: value - value object representing kcdata_descriptor
206 returns: str - summary of the kcdata object
208 format_string
= "{0: <#020x} {1: <#020x} {2: <#020x} {3: <10d} {4: <#05x}"
209 return format_string
.format(kcdata
, kcdata
.kcd_addr_begin
, kcdata
.kcd_addr_end
, kcdata
.kcd_length
, kcdata
.kcd_flags
)
212 @lldb_type_summary(['task', 'task_t'])
213 @header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags"))
214 def GetTaskSummary(task
, showcorpse
=False):
215 """ Summarizes the important fields in task structure.
216 params: task: value - value object representing a task in kernel
217 returns: str - summary of the task
220 format_string
= '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}'
221 thread_count
= int(task
.thread_count
)
223 if hasattr(task
, "suppression_generation") and (int(task
.suppression_generation
) & 0x1) == 0x1:
225 if hasattr(task
, "effective_policy") and int(task
.effective_policy
.tep_sup_active
) == 1:
227 if hasattr(task
, "suspend_count") and int(task
.suspend_count
) > 0:
229 if hasattr(task
, 'task_imp_base') and unsigned(task
.task_imp_base
):
230 tib
= task
.task_imp_base
231 if int(tib
.iit_receiver
) == 1:
233 if int(tib
.iit_donor
) == 1:
235 if int(tib
.iit_assertcnt
) > 0:
238 # check if corpse flag is set
239 if unsigned(task
.t_flags
) & 0x20:
241 if unsigned(task
.t_flags
) & 0x40:
244 out_string
+= format_string
.format(task
, task
.map, task
.itk_space
, thread_count
, task_flags
)
245 if showcorpse
is True and unsigned(task
.corpse_info
) != 0:
246 out_string
+= " " + GetKCDataSummary(task
.corpse_info
)
249 def GetThreadName(thread
):
250 """ Get the name of a thread, if possible. Returns the empty string
253 if int(thread
.uthread
) != 0:
254 uthread
= Cast(thread
.uthread
, 'uthread *')
255 if int(uthread
.pth_name
) != 0 :
256 th_name_strval
= Cast(uthread
.pth_name
, 'char *')
257 if len(str(th_name_strval
)) > 0 :
258 return str(th_name_strval
)
262 @lldb_type_summary(['thread *', 'thread_t'])
263 @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'))
264 def GetThreadSummary(thread
):
265 """ Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct.
266 params: thread: value - value objecte representing a thread in kernel
267 returns: str - summary of a thread
275 A - Terminated and on termination queue
286 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}"
287 thread_ptr_str
= str("{0: <#020x}".format(thread
))
288 if int(thread
.static_param
) :
289 thread_ptr_str
+="[WQ]"
290 thread_id
= hex(thread
.thread_id
)
291 processor
= hex(thread
.last_processor
)
292 base_priority
= str(int(thread
.base_pri
))
293 sched_priority
= str(int(thread
.sched_pri
))
295 mode
= str(thread
.sched_mode
)
296 if "TIMESHARE" in mode
:
297 sched_mode
+="timeshare"
298 elif "FIXED" in mode
:
300 elif "REALTIME" in mode
:
301 sched_mode
+="realtime"
303 if (unsigned(thread
.bound_processor
) != 0):
307 if (unsigned(thread
.sched_flags
) & 0x0004):
311 thread_name
= GetThreadName(thread
)
312 if int(thread
.uthread
) != 0:
313 uthread
= Cast(thread
.uthread
, 'uthread *')
315 #check for io_policy flags
316 if int(uthread
.uu_flag
) & 0x400:
317 io_policy_str
+='RAGE '
319 #now flags for task_policy
323 if int(thread
.effective_policy
.thep_darwinbg
) != 0:
325 if int(thread
.effective_policy
.thep_io_tier
) != 0:
327 if int(thread
.effective_policy
.thep_io_passive
) != 0:
329 if int(thread
.effective_policy
.thep_terminated
) != 0:
332 state
= int(thread
.state
)
333 thread_state_chars
= {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
337 state_str
+= thread_state_chars
[int(state
& mask
)]
340 if int(thread
.inspection
):
343 ast
= int(thread
.ast
) |
int(thread
.reason
)
344 ast_str
= GetASTSummary(ast
)
346 #wait queue information
350 if ( state
& 0x1 ) != 0:
351 #we need to look at the waitqueue as well
352 wait_queue_str
= str("{0: <#020x}".format(int(hex(thread
.waitq
), 16)))
353 wait_event_str
= str("{0: <#020x}".format(int(hex(thread
.wait_event
), 16)))
354 wait_event_str_sym
= kern
.Symbolicate(int(hex(thread
.wait_event
), 16))
355 if len(wait_event_str_sym
) > 0:
356 wait_event_str
= wait_event_str
.strip() + " <" + wait_event_str_sym
+ ">"
357 if int(thread
.uthread
) != 0 :
358 uthread
= Cast(thread
.uthread
, 'uthread *')
359 if int(uthread
.uu_wmesg
) != 0:
360 wait_message
= str(Cast(uthread
.uu_wmesg
, 'char *'))
362 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
)
366 def GetTaskRoleString(role
):
368 0 : "TASK_UNSPECIFIED",
369 1 : "TASK_FOREGROUND_APPLICATION",
370 2 : "TASK_BACKGROUND_APPLICATION",
371 3 : "TASK_CONTROL_APPLICATION",
372 4 : "TASK_GRAPHICS_SERVER",
373 5 : "TASK_THROTTLE_APPLICATION",
374 6 : "TASK_NONUI_APPLICATION",
375 7 : "TASK_DEFAULT_APPLICATION",
377 return role_strs
[int(role
)]
379 def GetCoalitionFlagString(coal
):
381 if (coal
.privileged
):
382 flags
.append('privileged')
383 if (coal
.termrequested
):
384 flags
.append('termrequested')
385 if (coal
.terminated
):
386 flags
.append('terminated')
388 flags
.append('reaped')
390 flags
.append('notified')
392 flags
.append('efficient')
393 return "|".join(flags
)
395 def GetCoalitionTasks(queue
, coal_type
, thread_details
=False):
397 0x0 : "SFI_CLASS_UNSPECIFIED",
398 0x1 : "SFI_CLASS_DARWIN_BG",
399 0x2 : "SFI_CLASS_APP_NAP",
400 0x3 : "SFI_CLASS_MANAGED_FOCAL",
401 0x4 : "SFI_CLASS_MANAGED_NONFOCAL",
402 0x5 : "SFI_CLASS_DEFAULT_FOCAL",
403 0x6 : "SFI_CLASS_DEFAULT_NONFOCAL",
404 0x7 : "SFI_CLASS_KERNEL",
405 0x8 : "SFI_CLASS_OPTED_OUT",
406 0x9 : "SFI_CLASS_UTILITY",
407 0xA : "SFI_CLASS_LEGACY_FOCAL",
408 0xB : "SFI_CLASS_LEGACY_NONFOCAL",
409 0xC : "SFI_CLASS_USER_INITIATED_FOCAL",
410 0xD : "SFI_CLASS_USER_INITIATED_NONFOCAL",
411 0xE : "SFI_CLASS_USER_INTERACTIVE_FOCAL",
412 0xF : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL",
413 0x10 : "SFI_CLASS_MAINTENANCE",
416 field_name
= 'task_coalition'
417 for task
in IterateLinkageChain(queue
, 'task *', field_name
, coal_type
* sizeof('queue_chain_t')):
418 task_str
= "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task
),task
,GetProcNameForTask(task
),GetTaskRoleString(task
.effective_policy
.tep_role
))
420 for thread
in IterateQueue(task
.threads
, "thread_t", "task_threads"):
421 task_str
+= "\n\t\t\t|-> thread:" + hex(thread
) + ", " + sfi_strs
[int(thread
.sfi_class
)]
422 tasks
.append(task_str
)
425 def GetCoalitionTypeString(type):
426 """ Convert a coalition type field into a string
427 Currently supported types (from <mach/coalition.h>):
428 COALITION_TYPE_RESOURCE
429 COALITION_TYPE_JETSAM
431 if type == 0: # COALITION_TYPE_RESOURCE
437 def GetResourceCoalitionSummary(coal
, verbose
=False):
438 """ Summarize a resource coalition
440 out_string
= "Resource Coalition:\n\t Ledger:\n"
441 thread_details
= False
442 if config
['verbosity'] > vSCRIPT
:
443 thread_details
= True
444 ledgerp
= coal
.r
.ledger
445 if verbose
and unsigned(ledgerp
) != 0:
447 while i
!= ledgerp
.l_template
.lt_cnt
:
449 out_string
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, ledgerp
.l_entries
[i
], i
)
451 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
)
452 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
)
453 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
)
454 out_string
+= "\n\t cpu_ptime {0: <d}".format(coal
.r
.cpu_ptime
)
456 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_DEFAULT] {0: <d}".format(coal
.r
.cpu_time_eqos
[0])
457 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_MAINTENANCE] {0: <d}".format(coal
.r
.cpu_time_eqos
[1])
458 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_BACKGROUND] {0: <d}".format(coal
.r
.cpu_time_eqos
[2])
459 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_UTILITY] {0: <d}".format(coal
.r
.cpu_time_eqos
[3])
460 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_LEGACY] {0: <d}".format(coal
.r
.cpu_time_eqos
[4])
461 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_USER_INITIATED] {0: <d}".format(coal
.r
.cpu_time_eqos
[5])
462 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_USER_INTERACTIVE] {0: <d}".format(coal
.r
.cpu_time_eqos
[6])
463 out_string
+= "\n\t Tasks:\n\t\t"
464 tasks
= GetCoalitionTasks(addressof(coal
.r
.tasks
), 0, thread_details
)
465 out_string
+= "\n\t\t".join(tasks
)
468 def GetJetsamCoalitionSummary(coal
, verbose
=False):
469 out_string
= "Jetsam Coalition:"
470 thread_details
= False
471 if config
['verbosity'] > vSCRIPT
:
472 thread_details
= True
473 if unsigned(coal
.j
.leader
) == 0:
474 out_string
+= "\n\t NO Leader!"
476 out_string
+= "\n\t Leader:\n\t\t"
477 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
))
478 out_string
+= "\n\t Extensions:\n\t\t"
479 tasks
= GetCoalitionTasks(addressof(coal
.j
.extensions
), 1, thread_details
)
480 out_string
+= "\n\t\t".join(tasks
)
481 out_string
+= "\n\t XPC Services:\n\t\t"
482 tasks
= GetCoalitionTasks(addressof(coal
.j
.services
), 1, thread_details
)
483 out_string
+= "\n\t\t".join(tasks
)
484 out_string
+= "\n\t Other Tasks:\n\t\t"
485 tasks
= GetCoalitionTasks(addressof(coal
.j
.other
), 1, thread_details
)
486 out_string
+= "\n\t\t".join(tasks
)
487 out_string
+= "\n\t Thread Group: {0: <#020x}\n".format(coal
.j
.thread_group
)
490 @lldb_type_summary(['coalition_t', 'coalition *'])
491 @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"))
492 def GetCoalitionSummary(coal
):
493 if unsigned(coal
) == 0:
494 return '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'.format(0, "", -1, -1, -1, -1, -1, "")
496 format_string
= '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'
497 type_string
= GetCoalitionTypeString(coal
.type)
498 flag_string
= GetCoalitionFlagString(coal
)
499 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
)
502 def GetCoalitionInfo(coal
, verbose
=False):
503 """ returns a string describing a coalition, including details about the particular coalition type.
505 coal : value object representing a coalition in the kernel
507 str : A string describing the coalition.
509 if unsigned(coal
) == 0:
510 return "<null coalition>"
511 typestr
= GetCoalitionTypeString(coal
.type)
512 flagstr
= GetCoalitionFlagString(coal
)
514 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
)
515 if coal
.type == 0: # COALITION_TYPE_RESOURCE
516 out_string
+= GetResourceCoalitionSummary(coal
, verbose
)
517 elif coal
.type == 1: # COALITION_TYPE_JETSAM
518 out_string
+= GetJetsamCoalitionSummary(coal
, verbose
)
520 out_string
+= "Unknown Type"
524 # Macro: showcoalitioninfo
526 @lldb_command('showcoalitioninfo')
527 def ShowCoalitionInfo(cmd_args
=None, cmd_options
={}):
528 """ Display more detailed information about a coalition
529 Usage: showcoalitioninfo <address of coalition>
532 if config
['verbosity'] > vHUMAN
:
535 raise ArgumentError("No arguments passed")
536 coal
= kern
.GetValueFromAddress(cmd_args
[0], 'coalition *')
538 print "unknown arguments:", str(cmd_args
)
540 print GetCoalitionInfo(coal
, verbose
)
542 # EndMacro: showcoalitioninfo
544 # Macro: showallcoalitions
546 @lldb_command('showallcoalitions')
547 def ShowAllCoalitions(cmd_args
=None):
548 """ Print a summary listing of all the coalitions
551 print GetCoalitionSummary
.header
552 for c
in kern
.coalitions
:
553 print GetCoalitionSummary(c
)
555 # EndMacro: showallcoalitions
557 # Macro: showallthreadgroups
559 @lldb_type_summary(['struct thread_group *', 'thread_group *'])
560 @header("{0: <20s} {1: <5s} {2: <16s} {3: <5s} {4: <8s} {5: <20s}".format("thread_group", "id", "name", "refc", "flags", "recommendation"))
561 def GetThreadGroupSummary(tg
):
562 if unsigned(tg
) == 0:
563 return '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'.format(0, -1, "", -1, "", -1)
565 format_string
= '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'
567 if (tg
.tg_flags
& 0x1):
569 if (tg
.tg_flags
& 0x2):
571 out_string
+= format_string
.format(tg
, tg
.tg_id
, tg
.tg_name
, tg
.tg_refcount
, tg_flags
, tg
.tg_recommendation
)
574 @lldb_command('showallthreadgroups')
575 def ShowAllThreadGroups(cmd_args
=None):
576 """ Print a summary listing of all thread groups
579 print GetThreadGroupSummary
.header
580 for tg
in kern
.thread_groups
:
581 print GetThreadGroupSummary(tg
)
583 # EndMacro: showallthreadgroups
585 # Macro: showtaskcoalitions
587 @lldb_command('showtaskcoalitions', 'F:')
588 def ShowTaskCoalitions(cmd_args
=None, cmd_options
={}):
592 if "-F" in cmd_options
:
593 task_list
= FindTasksByName(cmd_options
["-F"])
595 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
598 raise ArgumentError("No arguments passed")
600 if len(task_list
) > 0:
601 print GetCoalitionSummary
.header
602 for task
in task_list
:
603 print GetCoalitionSummary(task
.coalition
[0])
604 print GetCoalitionSummary(task
.coalition
[1])
606 # EndMacro: showtaskcoalitions
608 @lldb_type_summary(['proc', 'proc *'])
609 @header("{0: >6s} {1: <18s} {2: >11s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command"))
610 def GetProcSummary(proc
):
611 """ Summarize the process data.
613 proc : value - value representaitng a proc * in kernel
615 str - string summary of the process.
618 format_string
= "{0: >6d} {1: <#018x} {2: >11s} {3: >2d} {4: >2d} {5: >2d} {6: <20s}"
619 pval
= proc
.GetSBValue()
620 #code.interact(local=locals())
621 if str(pval
.GetType()) != str(gettype('proc *')) :
622 return "Unknown type " + str(pval
.GetType()) + " " + str(hex(proc
))
624 out_string
+= "Process " + hex(proc
) + " is not valid."
626 pid
= int(proc
.p_pid
)
627 proc_addr
= int(hex(proc
), 16)
629 if int(proc
.p_lflag
) & 0x400000 :
630 proc_rage_str
= "RAGE"
632 task
= Cast(proc
.task
, 'task *')
636 if int(task
.effective_policy
.tep_darwinbg
) != 0:
638 if int(task
.effective_policy
.tep_lowpri_cpu
) != 0:
641 if int(task
.effective_policy
.tep_io_tier
) != 0:
643 if int(task
.effective_policy
.tep_io_passive
) != 0:
645 if int(task
.effective_policy
.tep_terminated
) != 0:
648 if int(task
.effective_policy
.tep_latency_qos
) != 0:
650 if int(task
.effective_policy
.tep_sup_active
) != 0:
655 work_queue
= Cast(proc
.p_wqptr
, 'workqueue *')
656 if proc
.p_wqptr
!= 0 :
657 wq_num_threads
= int(work_queue
.wq_nthreads
)
658 wq_idle_threads
= int(work_queue
.wq_thidlecount
)
659 wq_req_threads
= int(work_queue
.wq_reqcount
)
668 process_name
= str(proc
.p_comm
)
669 if process_name
== 'xpcproxy':
670 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
671 thread_name
= GetThreadName(thread
)
673 process_name
+= ' (' + thread_name
+ ')'
675 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
)
678 @lldb_type_summary(['tty_dev_t', 'tty_dev_t *'])
679 @header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","master", "slave", "open", "free", "name", "revoke"))
680 def GetTTYDevSummary(tty_dev
):
681 """ Summarizes the important fields in tty_dev_t structure.
682 params: tty_dev: value - value object representing a tty_dev_t in kernel
683 returns: str - summary of the tty_dev
686 format_string
= "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"
687 open_fn
= kern
.Symbolicate(int(hex(tty_dev
.open), 16))
688 free_fn
= kern
.Symbolicate(int(hex(tty_dev
.free
), 16))
689 name_fn
= kern
.Symbolicate(int(hex(tty_dev
.name
), 16))
690 revoke_fn
= kern
.Symbolicate(int(hex(tty_dev
.revoke
), 16))
691 out_string
+= format_string
.format(tty_dev
, tty_dev
.master
, tty_dev
.slave
, open_fn
, free_fn
, name_fn
, revoke_fn
)
696 @lldb_command('showtask', 'F:')
697 def ShowTask(cmd_args
=None, cmd_options
={}):
698 """ Routine to print a summary listing of given task
699 Usage: showtask <address of task>
700 or : showtask -F <name of task>
703 if "-F" in cmd_options
:
704 task_list
= FindTasksByName(cmd_options
['-F'])
707 raise ArgumentError("Invalid arguments passed.")
709 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
711 raise ("Unknown arguments: %r" % cmd_args
)
712 task_list
.append(tval
)
714 for tval
in task_list
:
715 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
716 pval
= Cast(tval
.bsd_info
, 'proc *')
717 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
723 @lldb_command('showpid')
724 def ShowPid(cmd_args
=None):
725 """ Routine to print a summary listing of task corresponding to given pid
726 Usage: showpid <pid value>
729 raise ArgumentError("No arguments passed")
730 pidval
= ArgumentStringToInt(cmd_args
[0])
732 pval
= Cast(t
.bsd_info
, 'proc *')
733 if pval
and pval
.p_pid
== pidval
:
734 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
735 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
742 @lldb_command('showproc')
743 def ShowProc(cmd_args
=None):
744 """ Routine to print a summary listing of task corresponding to given proc
745 Usage: showproc <address of proc>
748 raise ArgumentError("No arguments passed")
749 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
751 print "unknown arguments:", str(cmd_args
)
753 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
754 tval
= Cast(pval
.task
, 'task *')
755 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
759 # Macro: showprocinfo
761 @lldb_command('showprocinfo')
762 def ShowProcInfo(cmd_args
=None):
763 """ Routine to display name, pid, parent & task for the given proc address
764 It also shows the Cred, Flags and state of the process
765 Usage: showprocinfo <address of proc>
768 raise ArgumentError("No arguments passed")
769 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
771 print "unknown arguments:", str(cmd_args
)
773 print GetProcInfo(pval
)
775 # EndMacro: showprocinfo
777 #Macro: showprocfiles
779 @lldb_command('showprocfiles')
780 def ShowProcFiles(cmd_args
=None):
781 """ Given a proc_t pointer, display the list of open file descriptors for the referenced process.
782 Usage: showprocfiles <proc_t>
785 print ShowProcFiles
.__doc
__
787 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t')
788 proc_filedesc
= proc
.p_fd
789 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
790 proc_ofiles
= proc_filedesc
.fd_ofiles
791 if unsigned(proc_ofiles
) == 0:
792 print 'No open files for proc {0: <s}'.format(cmd_args
[0])
794 print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')
795 print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")
798 while count
<= proc_lastfile
:
799 if unsigned(proc_ofiles
[count
]) != 0:
801 proc_fd_flags
= proc_ofiles
[count
].f_flags
802 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
803 out_str
+= "{0: <5d} ".format(count
)
804 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
))
805 out_str
+= "0x{0:0>8x} ".format(unsigned(proc_fd_flags
))
806 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
807 if proc_fd_ftype
in xnudefines
.filetype_strings
:
808 out_str
+= "{0: <8s} ".format(xnudefines
.filetype_strings
[proc_fd_ftype
])
810 out_str
+= "?: {0: <5d} ".format(proc_fd_ftype
)
811 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
.fg_data
))
812 if proc_fd_ftype
== 1:
813 fd_name
= Cast(proc_fd_fglob
.fg_data
, 'struct vnode *').v_name
814 out_str
+= "{0: <64s}".format(fd_name
)
819 #EndMacro: showprocfiles
823 @lldb_command('showtty')
824 def ShowTTY(cmd_args
=None):
825 """ Display information about a struct tty
826 Usage: showtty <tty struct>
829 print ShowTTY
.__doc
__
832 tty
= kern
.GetValueFromAddress(cmd_args
[0], 'struct tty *')
833 print "TTY structure at: {0: <s}".format(cmd_args
[0])
834 print "Last input to raw queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_rawq
.c_cs
), tty
.t_rawq
.c_cs
)
835 print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_canq
.c_cs
), tty
.t_canq
.c_cs
)
836 print "Last output data: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_outq
.c_cs
), tty
.t_outq
.c_cs
)
838 ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'],
839 ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'],
840 ['', 'TS_BUSY (Draining output)'],
841 ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'],
842 ['', 'TS_FLUSH (Outq has been flushed during DMA)'],
843 ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'],
844 ['', 'TS_TBLOCK (Further input blocked)'],
845 ['', 'TS_TIMEOUT (Wait for output char processing)'],
846 ['', 'TS_TTSTOP (Output paused)'],
847 ['', 'TS_WOPEN (Open in progress)'],
848 ['', 'TS_XCLUDE (Tty requires exclusivity)'],
849 ['', 'TS_BKSL (State for lowercase \\ work)'],
850 ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'],
851 ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'],
852 ['', 'TS_LNCH (Next character is literal)'],
853 ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'],
854 ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'],
855 ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'],
856 ['', 'TS_SNOOP (Device is being snooped on)'],
857 ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'],
858 ['', 'TS_ZOMBIE (Connection lost)'],
859 ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'],
860 ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'],
861 ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)']
865 tty_state
= unsigned(tty
.t_state
)
868 if tty_state
& mask
!= 0:
869 if len(tty_state_info
[index
][1]) > 0:
870 print '\t' + tty_state_info
[index
][1]
872 if len(tty_state_info
[index
][0]) > 0:
873 print '\t' + tty_state_info
[index
][0]
876 print "Flags: 0x{0:0>8x}".format(unsigned(tty
.t_flags
))
877 print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty
.t_pgrp
))
878 print "Enclosing session: 0x{0:0>16x}".format(unsigned(tty
.t_session
))
880 print "\tInput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_iflag
))
881 print "\tOutput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_oflag
))
882 print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_cflag
))
883 print "\tLocal Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_lflag
))
884 print "\tInput Speed: {0: <8d}".format(tty
.t_termios
.c_ispeed
)
885 print "\tOutput Speed: {0: <8d}".format(tty
.t_termios
.c_ospeed
)
886 print "High Watermark: {0: <d} bytes".format(tty
.t_hiwat
)
887 print "Low Watermark : {0: <d} bytes".format(tty
.t_lowat
)
891 #Macro showallttydevs
893 @lldb_command('showallttydevs')
894 def ShowAllTTYDevs(cmd_args
=[], cmd_options
={}):
895 """ Show a list of ttydevs registered in the system.
899 tty_dev_head
= kern
.globals.tty_dev_head
900 tty_dev
= tty_dev_head
901 print GetTTYDevSummary
.header
902 while unsigned(tty_dev
) != 0:
903 print GetTTYDevSummary(tty_dev
)
904 tty_dev
= tty_dev
.next
907 #EndMacro: showallttydevs
909 #Macro: dumpthread_terminate_queue
911 @lldb_command('dumpthread_terminate_queue')
912 def DumpThreadTerminateQueue(cmd_args
=None):
913 """ Displays the contents of the specified call_entry queue.
914 Usage: dumpthread_terminate_queue
918 print GetThreadSummary
.header
919 for th
in IterateMPSCQueue(addressof(kern
.globals.thread_terminate_queue
.mpd_queue
), 'struct thread', 'mpsc_links'):
920 print GetThreadSummary(th
)
922 print "{0: <d} entries!".format(count
)
924 #EndMacro: dumpthread_terminate_queue
926 #Macro: dumpcrashed_thread_queue
928 @lldb_command('dumpcrashed_thread_queue')
929 def DumpCrashedThreadsQueue(cmd_args
=None):
930 """ Displays the contents of the specified call_entry queue.
931 Usage: dumpcrashed_thread_queue
935 print GetThreadSummary
.header
936 for th
in IterateQueue(addressof(kern
.globals.crashed_threads_queue
), 'struct thread *', 'q_link'):
937 print GetThreadSummary(th
)
939 print "{0: <d} entries!".format(count
)
941 #EndMacro: dumpcrashed_thread_queue
943 #Macro: dumpcallqueue
945 @lldb_command('dumpcallqueue')
946 def DumpCallQueue(cmd_args
=None):
947 """ Displays the contents of the specified call_entry queue.
948 Usage: dumpcallqueue <queue_head_t *>
951 raise ArgumentError("Invalid arguments")
953 print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
954 callhead
= kern
.GetValueFromAddress(cmd_args
[0], 'queue_head_t *')
956 for callentry
in IterateQueue(callhead
, 'struct call_entry *', 'q_link'):
957 print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format(
958 unsigned(callentry
), unsigned(callentry
.param0
), unsigned(callentry
.param1
),
959 unsigned(callentry
.deadline
), unsigned(callentry
.func
))
961 print "{0: <d} entries!".format(count
)
963 #EndMacro: dumpcallqueue
965 @lldb_command('showalltasklogicalwrites')
966 def ShowAllTaskIOStats(cmd_args
=None):
967 """ Commad to print I/O stats for all tasks
969 print "{0: <20s} {1: <20s} {2: <20s} {3: <20s} {4: <20s} {5: <20s} {6: <20s} {7: <20s} {8: <20s} {9: <20s}".format("task", "Immediate Writes", "Deferred Writes", "Invalidated Writes", "Metadata Writes", "Immediate Writes to External", "Deferred Writes to External", "Invalidated Writes to External", "Metadata Writes to External", "name")
971 pval
= Cast(t
.bsd_info
, 'proc *')
972 print "{0: <#18x} {1: >20d} {2: >20d} {3: >20d} {4: >20d} {5: <20s} {6: <20s} {7: <20s} {8: <20s} {9: <20s}".format(t
,
973 t
.task_writes_counters_internal
.task_immediate_writes
,
974 t
.task_writes_counters_internal
.task_deferred_writes
,
975 t
.task_writes_counters_internal
.task_invalidated_writes
,
976 t
.task_writes_counters_internal
.task_metadata_writes
,
977 t
.task_writes_counters_external
.task_immediate_writes
,
978 t
.task_writes_counters_external
.task_deferred_writes
,
979 t
.task_writes_counters_external
.task_invalidated_writes
,
980 t
.task_writes_counters_external
.task_metadata_writes
,
984 @lldb_command('showalltasks','C', fancy
=True)
985 def ShowAllTasks(cmd_args
=None, cmd_options
={}, O
=None):
986 """ Routine to print a summary listing of all the tasks
987 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
988 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
989 io_policy -> RAGE - rapid aging of vnodes requested
990 NORM - normal I/O explicitly requested (this is the default)
991 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
992 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
993 Usage: (lldb) showalltasks -C : describe the corpse structure
998 if '-C' in cmd_options
:
1000 extra_hdr
+= " " + GetKCDataSummary
.header
1002 with O
.table(GetTaskSummary
.header
+ extra_hdr
+ " " + GetProcSummary
.header
):
1003 for t
in kern
.tasks
:
1004 pval
= Cast(t
.bsd_info
, 'proc *')
1005 print GetTaskSummary(t
, showcorpse
) + " " + GetProcSummary(pval
)
1009 @lldb_command('taskforpmap')
1010 def TaskForPmap(cmd_args
=None):
1011 """ Find the task whose pmap corresponds to <pmap>.
1012 Syntax: (lldb) taskforpmap <pmap>
1013 Multiple -v's can be specified for increased verbosity
1015 if cmd_args
== None or len(cmd_args
) < 1:
1016 raise ArgumentError("Too few arguments to taskforpmap.")
1017 pmap
= kern
.GetValueFromAddress(cmd_args
[0], 'pmap_t')
1018 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1019 for tasklist
in [kern
.tasks
, kern
.terminated_tasks
]:
1021 if t
.map.pmap
== pmap
:
1022 pval
= Cast(t
.bsd_info
, 'proc *')
1023 out_str
= GetTaskSummary(t
) + " " + GetProcSummary(pval
)
1026 @lldb_command('showterminatedtasks')
1027 def ShowTerminatedTasks(cmd_args
=None):
1028 """ Routine to print a summary listing of all the terminated tasks
1029 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1030 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1031 io_policy -> RAGE - rapid aging of vnodes requested
1032 NORM - normal I/O explicitly requested (this is the default)
1033 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1034 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1035 syntax: (lldb)showallterminatedtasks
1038 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1039 for t
in kern
.terminated_tasks
:
1040 pval
= Cast(t
.bsd_info
, 'proc *')
1041 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1044 # Macro: showtaskstacks
1046 def ShowTaskStacks(task
):
1047 """ Print a task with summary and stack information for each of its threads
1050 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1051 pval
= Cast(task
.bsd_info
, 'proc *')
1052 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1053 for th
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1054 print " " + GetThreadSummary
.header
1055 print " " + GetThreadSummary(th
)
1056 print GetThreadBackTrace(th
, prefix
=" ") + "\n"
1058 def FindTasksByName(searchstr
, ignore_case
=True):
1059 """ Search the list of tasks by name.
1061 searchstr: str - a regex like string to search for task
1062 ignore_case: bool - If False then exact matching will be enforced
1064 [] - array of task object. Empty if not found any
1068 re_options
= re
.IGNORECASE
1069 search_regex
= re
.compile(searchstr
, re_options
)
1071 for t
in kern
.tasks
:
1072 pval
= Cast(t
.bsd_info
, "proc *")
1073 process_name
= "{:s}".format(pval
.p_comm
)
1074 if search_regex
.search(process_name
):
1078 @lldb_command('showtaskstacks', 'F:')
1079 def ShowTaskStacksCmdHelper(cmd_args
=None, cmd_options
={}):
1080 """ Routine to print out the stack for each thread in a task
1081 Usage: showtaskstacks <0xaddress of task>
1082 or: showtaskstacks -F launchd
1085 if "-F" in cmd_options
:
1086 find_task_str
= cmd_options
["-F"]
1087 task_list
= FindTasksByName(find_task_str
)
1088 for tval
in task_list
:
1089 ShowTaskStacks(tval
)
1093 raise ArgumentError("No arguments passed")
1095 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1097 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
1099 ShowTaskStacks(tval
)
1102 # EndMacro: showtaskstacks
1104 def CheckTaskProcRefs(task
, proc
):
1105 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1106 if int(thread
.uthread
) == 0:
1108 uthread
= Cast(thread
.uthread
, 'uthread *')
1109 refcount
= int(uthread
.uu_proc_refcount
)
1110 uu_ref_index
= int(uthread
.uu_pindex
)
1113 for ref
in range(0, uu_ref_index
):
1114 if unsigned(uthread
.uu_proc_ps
[ref
]) == unsigned(proc
):
1115 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1116 pval
= Cast(task
.bsd_info
, 'proc *')
1117 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1118 print "\t" + GetThreadSummary
.header
1119 print "\t" + GetThreadSummary(thread
) + "\n"
1121 for frame
in range (0, 10):
1122 trace_addr
= unsigned(uthread
.uu_proc_pcs
[ref
][frame
])
1123 symbol_arr
= kern
.SymbolicateFromAddress(unsigned(trace_addr
))
1125 symbol_str
= str(symbol_arr
[0].addr
)
1128 print '{0: <#x} {1: <s}'.format(trace_addr
, symbol_str
)
1131 @lldb_command('showprocrefs')
1132 def ShowProcRefs(cmd_args
= None):
1133 """ Display information on threads/BTs that could be holding a reference on the specified proc
1134 NOTE: We can't say affirmatively if any of these references are still held since
1135 there's no way to pair references with drop-refs in the current infrastructure.
1136 Usage: showprocrefs <proc>
1138 if cmd_args
== None or len(cmd_args
) < 1:
1139 raise ArgumentError("No arguments passed")
1141 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
1143 for t
in kern
.tasks
:
1144 CheckTaskProcRefs(t
, proc
)
1145 for t
in kern
.terminated_tasks
:
1146 CheckTaskProcRefs(t
, proc
)
1150 @lldb_command('showallthreads')
1151 def ShowAllThreads(cmd_args
= None):
1152 """ Display info about all threads in the system
1154 for t
in kern
.tasks
:
1155 ShowTaskThreads([str(int(t
))])
1158 for t
in kern
.terminated_tasks
:
1159 print "Terminated: \n"
1160 ShowTaskThreads([str(int(t
))])
1165 @lldb_command('showtaskthreads', "F:")
1166 def ShowTaskThreads(cmd_args
= None, cmd_options
={}):
1167 """ Display thread information for a given task
1168 Usage: showtaskthreads <0xaddress of task>
1169 or: showtaskthreads -F <name>
1172 if "-F" in cmd_options
:
1173 task_list
= FindTasksByName(cmd_options
["-F"])
1175 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1178 raise ArgumentError("No arguments passed")
1180 for task
in task_list
:
1181 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1182 pval
= Cast(task
.bsd_info
, 'proc *')
1183 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1184 print "\t" + GetThreadSummary
.header
1185 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1186 print "\t" + GetThreadSummary(thval
)
1189 @lldb_command('showact')
1190 def ShowAct(cmd_args
=None):
1191 """ Routine to print out the state of a specific thread.
1192 usage: showact <activation>
1195 raise ArgumentError("No arguments passed")
1196 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1197 print GetThreadSummary
.header
1198 print GetThreadSummary(threadval
)
1200 @lldb_command('showactstack')
1201 def ShowActStack(cmd_args
=None):
1202 """ Routine to print out the stack of a specific thread.
1203 usage: showactstack <activation>
1206 raise ArgumentError("No arguments passed")
1207 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1208 print GetThreadSummary
.header
1209 print GetThreadSummary(threadval
)
1210 print GetThreadBackTrace(threadval
, prefix
="\t")
1213 @lldb_command('switchtoact')
1214 def SwitchToAct(cmd_args
=None):
1215 """ Switch to different context specified by activation
1216 This command allows gdb to examine the execution context and call
1217 stack for the specified activation. For example, to view the backtrace
1218 for an activation issue "switchtoact <address>", followed by "bt".
1219 Before resuming execution, issue a "resetctx" command, to
1220 return to the original execution context.
1222 if cmd_args
is None or len(cmd_args
) < 1:
1223 raise ArgumentError("No arguments passed")
1224 thval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1225 lldbthread
= GetLLDBThreadForKernelThread(thval
)
1226 print GetThreadSummary
.header
1227 print GetThreadSummary(thval
)
1228 LazyTarget
.GetProcess().selected_thread
= lldbthread
1229 if not LazyTarget
.GetProcess().SetSelectedThread(lldbthread
):
1230 print "Failed to switch thread."
1233 @lldb_command('switchtoregs')
1234 def SwitchToRegs(cmd_args
=None):
1235 """ Routine to switch to a register state.
1236 Usage: (lldb) switchtoregs <struct arm_saved_state[64] *>
1237 This command creates a fake thread in lldb with the saved register state.
1238 Note: This command ONLY works for ARM based kernel setup.
1241 if cmd_args
== None or len(cmd_args
) < 1:
1242 raise ArgumentError("No arguments passed")
1244 lldb_process
= LazyTarget
.GetProcess()
1246 saved_state
= ArgumentStringToInt(cmd_args
[0])
1247 # any change to this logic requires change in operating_system.py as well
1248 fake_thread_id
= 0xdead0000 |
(saved_state
& ~
0xffff0000)
1249 fake_thread_id
= fake_thread_id
& 0xdeadffff
1250 lldb_process
.CreateOSPluginThread(0xdeadbeef, saved_state
)
1251 lldbthread
= lldb_process
.GetThreadByID(int(fake_thread_id
))
1253 if not lldbthread
.IsValid():
1254 print "Failed to create thread"
1257 lldb_process
.selected_thread
= lldbthread
1258 if not lldb_process
.SetSelectedThread(lldbthread
):
1259 print "Failed to switch thread"
1260 print "Switched to Fake thread created from register state at 0x%x" % saved_state
1264 # Macro: showallstacks
1265 @lldb_command('showallstacks')
1266 def ShowAllStacks(cmd_args
=None):
1267 """Routine to print out the stack for each thread in the system.
1269 for t
in kern
.tasks
:
1275 # EndMacro: showallstacks
1277 # Macro: showcurrentstacks
1278 @lldb_command('showcurrentstacks')
1279 def ShowCurrentStacks(cmd_args
=None):
1280 """ Routine to print out the thread running on each cpu (incl. its stack)
1282 processor_list
= kern
.GetGlobalVariable('processor_list')
1283 current_processor
= processor_list
1284 while unsigned(current_processor
) > 0:
1285 print "\n" + GetProcessorSummary(current_processor
)
1286 active_thread
= current_processor
.active_thread
1287 if unsigned(active_thread
) != 0 :
1288 task_val
= active_thread
.task
1289 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1290 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1291 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1292 print "\t" + GetThreadSummary
.header
1293 print "\t" + GetThreadSummary(active_thread
)
1294 print "\tBacktrace:"
1295 print GetThreadBackTrace(active_thread
, prefix
="\t")
1296 current_processor
= current_processor
.processor_list
1298 # EndMacro: showcurrentstacks
1300 @lldb_command('showcurrentthreads')
1301 def ShowCurrentThreads(cmd_args
=None):
1302 """ Display info about threads running on each cpu """
1303 processor_list
= kern
.GetGlobalVariable('processor_list')
1304 current_processor
= processor_list
1305 while unsigned(current_processor
) > 0:
1306 print GetProcessorSummary(current_processor
)
1307 active_thread
= current_processor
.active_thread
1308 if unsigned(active_thread
) != 0 :
1309 task_val
= active_thread
.task
1310 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1311 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1312 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1313 print "\t" + GetThreadSummary
.header
1314 print "\t" + GetThreadSummary(active_thread
)
1315 current_processor
= current_processor
.processor_list
1318 def GetFullBackTrace(frame_addr
, verbosity
= vHUMAN
, prefix
= ""):
1319 """ Get backtrace across interrupt context.
1320 params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7)
1321 prefix - str - prefix for each line of output.
1326 frame_ptr
= frame_addr
1327 previous_frame_ptr
= 0
1328 # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
1329 mh_execute_addr
= int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
1330 while frame_ptr
and frame_ptr
!= previous_frame_ptr
and bt_count
< 128:
1331 if (not kern
.arch
.startswith('arm') and frame_ptr
< mh_execute_addr
) or (kern
.arch
.startswith('arm') and frame_ptr
> mh_execute_addr
):
1333 pc_val
= kern
.GetValueFromAddress(frame_ptr
+ kern
.ptrsize
,'uintptr_t *')
1334 pc_val
= unsigned(dereference(pc_val
))
1335 out_string
+= prefix
+ GetSourceInformationForAddress(pc_val
) + "\n"
1337 previous_frame_ptr
= frame_ptr
1338 frame_val
= kern
.GetValueFromAddress((frame_ptr
), 'uintptr_t *')
1339 if unsigned(frame_val
) == 0:
1341 frame_ptr
= unsigned(dereference(frame_val
))
1345 @lldb_command('fullbt')
1346 def FullBackTrace(cmd_args
=[]):
1347 """ Show full backtrace across the interrupt boundary.
1348 Syntax: fullbt <frame ptr>
1349 Example: fullbt `$rbp`
1351 if len(cmd_args
) < 1:
1352 print FullBackTrace
.__doc
__
1354 print GetFullBackTrace(ArgumentStringToInt(cmd_args
[0]), prefix
="\t")
1356 @lldb_command('fullbtall')
1357 def FullBackTraceAll(cmd_args
=[]):
1358 """ Show full backtrace across the interrupt boundary for threads running on all processors.
1362 for processor
in IterateLinkedList(kern
.globals.processor_list
, 'processor_list') :
1363 print "\n" + GetProcessorSummary(processor
)
1364 active_thread
= processor
.active_thread
1365 if unsigned(active_thread
) != 0 :
1366 task_val
= active_thread
.task
1367 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1368 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1369 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1370 print "\t" + GetThreadSummary
.header
1371 print "\t" + GetThreadSummary(active_thread
)
1372 print "\tBacktrace:"
1374 ThreadVal
= GetLLDBThreadForKernelThread(active_thread
)
1376 FramePtr
= ThreadVal
.frames
[0].GetFP()
1378 print GetFullBackTrace(unsigned(FramePtr
), prefix
="\t")
1381 @lldb_command('symbolicate')
1382 def SymbolicateAddress(cmd_args
=[]):
1383 """ Symbolicate an address for symbol information from loaded symbols
1384 Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr"
1386 if len(cmd_args
) < 1:
1387 print "Invalid address.\nSyntax: symbolicate <address>"
1389 print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args
[0]))
1392 @lldb_command('showinitchild')
1393 def ShowInitChild(cmd_args
=None):
1394 """ Routine to print out all processes in the system
1395 which are children of init process
1397 headp
= kern
.globals.initproc
.p_children
1398 for pp
in IterateListEntry(headp
, 'struct proc *', 'p_sibling'):
1399 print GetProcInfo(pp
)
1402 @lldb_command('showproctree')
1403 def ShowProcTree(cmd_args
=None):
1404 """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes.
1405 If no argument is given, showproctree will print all the processes in the system.
1406 If pid is specified, showproctree prints all the descendants of the indicated process
1410 search_pid
= ArgumentStringToInt(cmd_args
[0])
1413 print "pid specified must be a positive number"
1414 print ShowProcTree
.__doc
__
1417 hdr_format
= "{0: <6s} {1: <14s} {2: <9s}\n"
1418 out_string
= hdr_format
.format("PID", "PROCESS", "POINTER")
1419 out_string
+= hdr_format
.format('='*3, '='*7, '='*7)
1420 proc
= GetProcForPid(search_pid
)
1421 out_string
+= "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc
.p_ppid
, proc
.p_pptr
.p_comm
, unsigned(proc
.p_pptr
))
1422 out_string
+= "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc
.p_pid
, proc
.p_comm
, unsigned(proc
))
1424 ShowProcTreeRecurse(proc
, "| ")
1428 def ShowProcTreeRecurse(proc
, prefix
=""):
1429 """ Prints descendants of a given proc in hierarchial tree form
1431 proc : core.value representing a struct proc * in the kernel
1433 str : String containing info about a given proc and its descendants in tree form
1435 if proc
.p_childrencnt
> 0:
1436 head_ptr
= proc
.p_children
.lh_first
1438 for p
in IterateListEntry(proc
.p_children
, 'struct proc *', 'p_sibling'):
1439 print prefix
+ "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p
.p_pid
, p
.p_comm
, unsigned(p
))
1440 ShowProcTreeRecurse(p
, prefix
+ "| ")
1442 @lldb_command('showthreadfortid')
1443 def ShowThreadForTid(cmd_args
=None):
1444 """ The thread structure contains a unique thread_id value for each thread.
1445 This command is used to retrieve the address of the thread structure(thread_t)
1446 corresponding to a given thread_id.
1449 print "Please provide thread_t whose tid you'd like to look up"
1450 print ShowThreadForTid
.__doc
__
1452 search_tid
= ArgumentStringToInt(cmd_args
[0])
1453 for taskp
in kern
.tasks
:
1454 for actp
in IterateQueue(taskp
.threads
, 'struct thread *', 'task_threads'):
1455 if search_tid
== int(actp
.thread_id
):
1456 print "Found {0: #019x}".format(actp
)
1457 print GetThreadSummary
.header
1458 print GetThreadSummary(actp
)
1460 print "Not a valid thread_id"
1462 def GetProcessorSummary(processor
):
1463 """ Internal function to print summary of processor
1464 params: processor - value representing struct processor *
1465 return: str - representing the details of given processor
1468 processor_state_str
= "INVALID"
1469 processor_state
= int(processor
.state
)
1471 processor_states
= {
1475 # 3 (formerly INACTIVE)
1481 if processor_state
in processor_states
:
1482 processor_state_str
= "{0: <11s} ".format(processor_states
[processor_state
])
1484 processor_recommended_str
= ""
1485 if int(processor
.is_recommended
) == 0:
1486 processor_recommended_str
= " (not recommended)"
1489 preemption_disable
= 0
1490 preemption_disable_str
= ""
1492 if kern
.arch
== 'x86_64':
1493 cpu_data
= kern
.globals.cpu_data_ptr
[processor
.cpu_id
]
1494 if (cpu_data
!= 0) :
1495 ast
= cpu_data
.cpu_pending_ast
1496 preemption_disable
= cpu_data
.cpu_preemption_level
1497 # On arm64, it's kern.globals.CpuDataEntries[processor.cpu_id].cpu_data_vaddr
1498 # but LLDB can't find CpuDataEntries...
1500 ast_str
= GetASTSummary(ast
)
1502 if (preemption_disable
!= 0) :
1503 preemption_disable_str
= "Preemption Disabled"
1505 out_str
= "Processor {: <#018x} cpu_id {:>#4x} AST: {:<6s} State {:<s}{:<s} {:<s}\n".format(
1506 processor
, int(processor
.cpu_id
), ast_str
, processor_state_str
, processor_recommended_str
,
1507 preemption_disable_str
)
1510 def GetLedgerEntrySummary(ledger_template
, ledger
, i
, show_footprint_interval_max
=False):
1511 """ Internal function to get internals of a ledger entry (*not* a ledger itself)
1512 params: ledger_template - value representing struct ledger_template_t for the task or thread
1513 ledger - value representing struct ledger_entry *
1514 return: str - formatted output information of ledger entries
1516 ledger_limit_infinity
= (uint64_t(0x1).value
<< 63) - 1
1517 lf_refill_scheduled
= 0x0400
1518 lf_tracking_max
= 0x4000
1521 now
= unsigned(kern
.globals.sched_tick
) / 20
1524 out_str
+= "{: >32s} {:<2d}:".format(ledger_template
.lt_entries
[i
].et_key
, i
)
1525 out_str
+= "{: >15d} ".format(unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
))
1526 if (ledger
.le_flags
& lf_tracking_max
):
1527 if (show_footprint_interval_max
):
1528 out_str
+= "{:12d} ".format(ledger
._le
._le
_max
.le_interval_max
)
1529 out_str
+= "{:14d} ".format(ledger
._le
._le
_max
.le_lifetime_max
)
1531 if (show_footprint_interval_max
):
1534 out_str
+= "{:12d} {:12d} ".format(unsigned(ledger
.le_credit
), unsigned(ledger
.le_debit
))
1535 if (unsigned(ledger
.le_limit
) != ledger_limit_infinity
):
1536 out_str
+= "{:12d} ".format(unsigned(ledger
.le_limit
))
1540 if (ledger
.le_flags
& lf_refill_scheduled
):
1541 out_str
+= "{:15d} ".format(ledger
._le
.le_refill
.le_refill_period
)
1545 if (ledger
.le_flags
& lf_refill_scheduled
):
1546 out_str
+= "{:9d} ".format((unsigned(ledger
.le_limit
) * 100) / ledger
._le
.le_refill
.le_refill_period
)
1550 if (unsigned(ledger
.le_warn_level
) != ledger_limit_infinity
):
1551 out_str
+= "{:9d} ".format((unsigned(ledger
.le_warn_level
) * 100) / unsigned(ledger
.le_limit
))
1555 if ((unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
)) > unsigned(ledger
.le_limit
)):
1560 out_str
+= "{:#8x}\n".format(ledger
.le_flags
)
1563 def GetThreadLedgerSummary(thread_val
):
1564 """ Internal function to get a summary of ledger entries for the given thread
1565 params: thread - value representing struct thread *
1566 return: str - formatted output information for ledger entries of the input thread
1568 out_str
= " [{:#08x}]\n".format(thread_val
)
1569 ledgerp
= thread_val
.t_threadledger
1572 while i
!= ledgerp
.l_template
.lt_cnt
:
1573 out_str
+= GetLedgerEntrySummary(kern
.globals.thread_ledger_template
,
1574 ledgerp
.l_entries
[i
], i
)
1578 def GetTaskLedgers(task_val
, show_footprint_interval_max
=False):
1579 """ Internal function to get summary of ledger entries from the task and its threads
1580 params: task_val - value representing struct task *
1581 return: str - formatted output information for ledger entries of the input task
1584 task_ledgerp
= task_val
.ledger
1586 out_str
+= "{: #08x} ".format(task_val
)
1587 pval
= Cast(task_val
.bsd_info
, 'proc *')
1589 out_str
+= "{: <5s}:\n".format(pval
.p_comm
)
1591 out_str
+= "Invalid process:\n"
1592 while i
!= task_ledgerp
.l_template
.lt_cnt
:
1593 out_str
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, task_ledgerp
.l_entries
[i
], i
, show_footprint_interval_max
)
1597 for thval
in IterateQueue(task_val
.threads
, 'thread *', 'task_threads'):
1598 out_str
+= GetThreadLedgerSummary(thval
)
1602 # Macro: showtaskledgers
1604 @lldb_command('showtaskledgers', 'F:I')
1605 def ShowTaskLedgers(cmd_args
=None, cmd_options
={}):
1606 """ Routine to print a summary of ledger entries for the task and all of its threads
1607 or : showtaskledgers [ -I ] [ -F ] <task>
1609 -I: show footprint interval max (DEV/DEBUG only)
1610 -F: specify task via name instead of address
1613 if "-F" in cmd_options
:
1614 task_list
= FindTasksByName(cmd_options
["-F"])
1615 for tval
in task_list
:
1616 print GetTaskLedgers
.header
1617 print GetTaskLedgers(tval
)
1621 raise ArgumentError("No arguments passed.")
1622 show_footprint_interval_max
= False
1623 if "-I" in cmd_options
:
1624 show_footprint_interval_max
= True
1625 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1627 raise ArgumentError("unknown arguments: %r" %cmd
_args
)
1628 if (show_footprint_interval_max
):
1629 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(
1630 "task [thread]", "entry", "#", "balance", "intrvl_max", "lifetime_max", "credit",
1631 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")
1633 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(
1634 "task [thread]", "entry", "#", "balance", "lifetime_max", "credit",
1635 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")
1636 print GetTaskLedgers(tval
, show_footprint_interval_max
)
1638 # EndMacro: showtaskledgers
1640 # Macro: showalltaskledgers
1642 @lldb_command('showalltaskledgers')
1643 def ShowAllTaskLedgers(cmd_args
=None, cmd_options
={}):
1644 """ Routine to print a summary of ledger entries for all tasks and respective threads
1645 Usage: showalltaskledgers
1647 for t
in kern
.tasks
:
1648 task_val
= unsigned(t
)
1649 ShowTaskLedgers([task_val
], cmd_options
=cmd_options
)
1651 # EndMacro: showalltaskledgers
1653 # Macro: showprocuuidpolicytable
1655 @lldb_type_summary(['proc_uuid_policy_entry'])
1656 @header("{0: <36s} {1: <10s}".format("uuid", "flags"))
1657 def GetProcUUIDPolicyEntrySummary(entry
):
1658 """ Summarizes the important fields in proc_uuid_policy_entry structure.
1659 params: entry: value - value object representing an entry
1660 returns: str - summary of the entry
1664 data
.append(int(entry
.uuid
[i
]))
1665 flags
= unsigned(entry
.flags
)
1666 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
)
1669 @lldb_command('showprocuuidpolicytable')
1670 def ShowProcUUIDPolicyTable(cmd_args
=None):
1671 """ Routine to print the proc UUID policy table
1672 Usage: showprocuuidpolicytable
1674 hashslots
= unsigned(kern
.globals.proc_uuid_policy_hash_mask
)
1675 print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary
.header
1676 for i
in range(0, hashslots
+1):
1677 headp
= addressof(kern
.globals.proc_uuid_policy_hashtbl
[i
])
1679 for entry
in IterateListEntry(headp
, 'struct proc_uuid_policy_entry *', 'entries'):
1680 print "{0: >2d}.{1: <5d} ".format(i
, entrynum
) + GetProcUUIDPolicyEntrySummary(entry
)
1684 # EndMacro: showprocuuidpolicytable
1686 @lldb_command('showalltaskpolicy')
1687 def ShowAllTaskPolicy(cmd_args
=None):
1689 Routine to print a summary listing of all the tasks
1690 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1691 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1692 io_policy -> RAGE - rapid aging of vnodes requested
1693 NORM - normal I/O explicitly requested (this is the default)
1694 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1695 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1698 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1699 for t
in kern
.tasks
:
1700 pval
= Cast(t
.bsd_info
, 'proc *')
1701 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1702 requested_strings
= [
1703 ["int_darwinbg", "DBG-int"],
1704 ["ext_darwinbg", "DBG-ext"],
1705 ["int_iotier", "iotier-int"],
1706 ["ext_iotier", "iotier-ext"],
1707 ["int_iopassive", "passive-int"],
1708 ["ext_iopassive", "passive-ext"],
1709 ["bg_iotier", "bg-iotier"],
1710 ["terminated", "terminated"],
1711 ["th_pidbind_bg", "bg-pidbind"],
1712 ["t_apptype", "apptype"],
1713 ["t_boosted", "boosted"],
1715 ["t_tal_enabled", "tal-enabled"],
1716 ["t_base_latency_qos", "latency-base"],
1717 ["t_over_latency_qos", "latency-override"],
1718 ["t_base_through_qos", "throughput-base"],
1719 ["t_over_through_qos", "throughput-override"]
1723 for value
in requested_strings
:
1724 if t
.requested_policy
.__getattr
__(value
[0]) :
1725 requested
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1729 suppression_strings
= [
1730 ["t_sup_active", "active"],
1731 ["t_sup_lowpri_cpu", "lowpri-cpu"],
1732 ["t_sup_timer", "timer-throttling"],
1733 ["t_sup_disk", "disk-throttling"],
1734 ["t_sup_cpu_limit", "cpu-limits"],
1735 ["t_sup_suspend", "suspend"],
1736 ["t_sup_bg_sockets", "bg-sockets"]
1740 for value
in suppression_strings
:
1741 if t
.requested_policy
.__getattr
__(value
[0]) :
1742 suppression
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1746 effective_strings
= [
1747 ["darwinbg", "background"],
1748 ["lowpri_cpu", "lowpri-cpu"],
1749 ["io_tier", "iotier"],
1750 ["io_passive", "passive"],
1751 ["all_sockets_bg", "bg-allsockets"],
1752 ["new_sockets_bg", "bg-newsockets"],
1753 ["bg_iotier", "bg-iotier"],
1754 ["terminated", "terminated"],
1755 ["t_gpu_deny", "gpu-deny"],
1756 ["t_tal_engaged", "tal-engaged"],
1757 ["t_suspended", "suspended"],
1758 ["t_watchers_bg", "bg-watchers"],
1759 ["t_latency_qos", "latency-qos"],
1760 ["t_through_qos", "throughput-qos"],
1761 ["t_sup_active", "suppression-active"],
1766 for value
in effective_strings
:
1767 if t
.effective_policy
.__getattr
__(value
[0]) :
1768 effective
+=value
[1] + ": " + str(t
.effective_policy
.__getattr
__(value
[0])) + " "
1772 print "requested: " + requested
1773 print "suppression: " + suppression
1774 print "effective: " + effective
1777 @lldb_type_summary(['wait_queue', 'wait_queue_t'])
1778 @header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask"))
1779 def GetWaitQSummary(waitq
):
1780 """ Summarizes the important fields in task structure.
1781 params: task: value - value object representing a task in kernel
1782 returns: str - summary of the task
1785 format_string
= '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
1789 if (waitq
.wq_fifo
== 1) :
1794 if (waitq
.wq_prepost
== 1) :
1797 if (waitq
.wq_type
== 0x3) :
1799 elif (waitq
.wq_type
== 0x2) :
1804 out_string
+= format_string
.format(waitq
, unsigned(waitq
.wq_interlock
.lock_data
), policy
, 0, 0, unsigned(waitq
.wq_eventmask
))
1806 out_string
+= "\n" + GetThreadSummary
.header
1808 for thread
in IterateQueue(waitq
.wq_queue
, "thread_t", "links"):
1809 out_string
+= "\n" + GetThreadSummary(thread
)
1814 @lldb_command('showallsuspendedtasks', '')
1815 def ShowSuspendedTasks(cmd_args
=[], options
={}):
1816 """ Show a list of suspended tasks with their process name summary.
1818 print GetTaskSummary
.header
+ ' ' + GetProcSummary
.header
1819 for t
in kern
.tasks
:
1820 if t
.suspend_count
> 0:
1821 print GetTaskSummary(t
) + ' ' + GetProcSummary(Cast(t
.bsd_info
, 'proc *'))
1825 @lldb_command('showallpte')
1826 def ShowAllPte(cmd_args
=None):
1827 """ Prints out the physical address of the pte for all tasks
1829 head_taskp
= addressof(kern
.globals.tasks
)
1830 taskp
= Cast(head_taskp
.next
, 'task *')
1831 while taskp
!= head_taskp
:
1832 procp
= Cast(taskp
.bsd_info
, 'proc *')
1833 out_str
= "task = {:#x} pte = {:#x}\t".format(taskp
, taskp
.map.pmap
.ttep
)
1835 out_str
+= "{:s}\n".format(procp
.p_comm
)
1839 taskp
= Cast(taskp
.tasks
.next
, 'struct task *')
1841 # EndMacro: showallpte
1843 # Macro: showallrefcounts
1844 @lldb_command('showallrefcounts')
1845 @header("{0: <20s} {1: ^10s}".format("task", "ref_count"))
1846 def ShowAllRefCounts(cmd_args
=None):
1847 """ Prints the ref_count of all tasks
1850 head_taskp
= addressof(kern
.globals.tasks
)
1851 taskp
= Cast(head_taskp
.next
, 'task *')
1852 print ShowAllRefCounts
.header
1853 while taskp
!= head_taskp
:
1854 out_str
+= "{: <#20x}".format(taskp
)
1855 out_str
+= "{: ^10d}\n".format(taskp
.ref_count
)
1856 taskp
= Cast(taskp
.tasks
.next
, 'task *')
1858 # EndMacro: showallrefcounts
1860 # Macro: showallrunnablethreads
1861 @lldb_command('showallrunnablethreads')
1862 def ShowAllRunnableThreads(cmd_args
=None):
1863 """ Prints the sched usage information for all threads of each task
1866 for taskp
in kern
.tasks
:
1867 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1868 if int(actp
.state
& 0x4):
1869 ShowActStack([unsigned(actp
)])
1871 # EndMacro: showallrunnablethreads
1873 # Macro: showallschedusage
1874 @lldb_command('showallschedusage')
1875 @header("{0:<20s} {1:^10s} {2:^10s} {3:^15s}".format("Thread", "Priority", "State", "sched_usage"))
1876 def ShowAllSchedUsage(cmd_args
=None):
1877 """ Prints the sched usage information for all threads of each task
1880 for taskp
in kern
.tasks
:
1881 ShowTask([unsigned(taskp
)])
1882 print ShowAllSchedUsage
.header
1883 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1884 out_str
= "{: <#20x}".format(actp
)
1885 out_str
+= "{: ^10s}".format(str(int(actp
.sched_pri
)))
1886 state
= int(actp
.state
)
1887 thread_state_chars
= {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'}
1889 state_str
+= thread_state_chars
[int(state
& 0x1)]
1890 state_str
+= thread_state_chars
[int(state
& 0x2)]
1891 state_str
+= thread_state_chars
[int(state
& 0x4)]
1892 state_str
+= thread_state_chars
[int(state
& 0x8)]
1893 state_str
+= thread_state_chars
[int(state
& 0x10)]
1894 state_str
+= thread_state_chars
[int(state
& 0x20)]
1895 state_str
+= thread_state_chars
[int(state
& 0x40)]
1896 state_str
+= thread_state_chars
[int(state
& 0x80)]
1897 out_str
+= "{: ^10s}".format(state_str
)
1898 out_str
+= "{: >15d}".format(actp
.sched_usage
)
1899 print out_str
+ "\n"
1902 # EndMacro: showallschedusage
1904 #Macro: showprocfilessummary
1905 @lldb_command('showprocfilessummary')
1906 @header("{0: <20s} {1: <20s} {2: >10s}".format("Process", "Name", "Number of Open Files"))
1907 def ShowProcFilesSummary(cmd_args
=None):
1908 """ Display the summary of open file descriptors for all processes in task list
1909 Usage: showprocfilessummary
1911 print ShowProcFilesSummary
.header
1912 for proc
in kern
.procs
:
1913 proc_filedesc
= proc
.p_fd
1914 proc_ofiles
= proc_filedesc
.fd_ofiles
1915 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
1918 if proc_filedesc
.fd_nfiles
!= 0:
1919 while count
<= proc_lastfile
:
1920 if unsigned(proc_ofiles
[count
]) != 0:
1921 proc_file_count
+= 1
1923 print "{0: <#020x} {1: <20s} {2: >10d}".format(proc
, proc
.p_comm
, proc_file_count
)
1925 #EndMacro: showprocfilessummary
1927 @lldb_command('workinguserstacks')
1928 def WorkingUserStacks(cmd_args
=None):
1929 """ Print out the user stack for each thread in a task, followed by the user libraries.
1930 Syntax: (lldb) workinguserstacks <task_t>
1933 print "Insufficient arguments" + ShowTaskUserStacks
.__doc
__
1935 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1936 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1937 pval
= Cast(task
.bsd_info
, 'proc *')
1938 print GetTaskSummary(task
) + " " + GetProcSummary(pval
) + "\n \n"
1939 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1940 print "For thread 0x{0:x}".format(thval
)
1942 ShowThreadUserStack([hex(thval
)])
1943 except Exception as exc_err
:
1944 print "Failed to show user stack for thread 0x{0:x}".format(thval
)
1948 print "Enable debugging ('(lldb) xnudebug debug') to see detailed trace."
1949 WorkingUserLibraries([hex(task
)])
1952 @static_var("exec_load_path", 0)
1953 @lldb_command("workingkuserlibraries")
1954 def WorkingUserLibraries(cmd_args
=None):
1955 """ Show binary images known by dyld in target task
1956 For a given user task, inspect the dyld shared library state and print information about all Mach-O images.
1957 Syntax: (lldb)workinguserlibraries <task_t>
1960 print "Insufficient arguments"
1961 print ShowTaskUserLibraries
.__doc
__
1964 print "{0: <18s} {1: <12s} {2: <36s} {3: <50s}".format('address','type','uuid','path')
1965 out_format
= "0x{0:0>16x} {1: <12s} {2: <36s} {3: <50s}"
1966 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t')
1967 is_task_64
= int(task
.t_flags
) & 0x1
1968 dyld_all_image_infos_address
= unsigned(task
.all_image_info_addr
)
1970 if dyld_all_image_infos_address
== 0:
1971 print "No dyld shared library information available for task"
1973 vers_info_data
= GetUserDataAsString(task
, dyld_all_image_infos_address
, 112)
1974 version
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
1975 cur_data_offset
+= 4
1977 print "Unknown dyld all_image_infos version number %d" % version
1978 image_info_count
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
1979 WorkingUserLibraries
.exec_load_path
= 0
1981 image_info_size
= 24
1982 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 8, "uint64_t")
1983 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 8*4, "uint64_t")
1984 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 8*13, "uint64_t")
1986 image_info_size
= 12
1987 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 4*2, "uint32_t")
1988 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 4*5, "uint32_t")
1989 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 4*14, "uint32_t")
1990 # Account for ASLR slide before dyld can fix the structure
1991 dyld_load_address
= dyld_load_address
+ (dyld_all_image_infos_address
- dyld_all_image_infos_address_from_struct
)
1994 while i
< image_info_count
:
1995 image_info_address
= image_info_array_address
+ i
* image_info_size
1996 img_data
= GetUserDataAsString(task
, image_info_address
, image_info_size
)
1998 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint64_t")
1999 image_info_path
= _ExtractDataFromString(img_data
, 8, "uint64_t")
2001 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint32_t")
2002 image_info_path
= _ExtractDataFromString(img_data
, 4, "uint32_t")
2003 PrintImageInfo(task
, image_info_addr
, image_info_path
)
2006 # load_path might get set when the main executable is processed.
2007 if WorkingUserLibraries
.exec_load_path
!= 0:
2008 PrintImageInfo(task
, dyld_load_address
, WorkingUserLibraries
.exec_load_path
)
2011 # Macro: showstackaftertask
2012 @lldb_command('showstackaftertask','F:')
2013 def Showstackaftertask(cmd_args
=None,cmd_options
={}):
2014 """ Routine to print the thread stacks for all tasks succeeding a given task
2015 Usage: showstackaftertask <0xaddress of task>
2016 or: showstackaftertask -F <taskname>
2018 if "-F" in cmd_options
:
2019 # Find the task pointer corresponding to its task name
2020 find_task_str
= cmd_options
["-F"]
2021 task_list
= FindTasksByName(find_task_str
)
2023 # Iterate through the list of tasks and print all task stacks thereafter
2024 for tval
in task_list
:
2025 ListTaskStacks(tval
)
2029 raise ArgumentError("Insufficient arguments")
2030 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
2032 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
2034 ListTaskStacks(tval
)
2038 # EndMacro: showstackaftertask
2040 def ListTaskStacks(task
):
2041 """ Search for a given task and print the list of all task stacks thereafter.
2043 # Initialize local variable task_flag to mark when a given task is found.
2046 for t
in kern
.tasks
:
2047 if (task_flag
== 1):
2053 # Macro: showstackafterthread
2054 @lldb_command('showstackafterthread')
2055 def Showstackafterthread(cmd_args
= None):
2056 """ Routine to print the stacks of all threads succeeding a given thread.
2057 Usage: Showstackafterthread <0xaddress of thread>
2059 # local variable thread_flag is used to mark when a given thread is found.
2062 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
2064 raise ArgumentError("No arguments passed")
2065 # Iterate through list of all tasks to look up a given thread
2066 for t
in kern
.tasks
:
2068 pval
= Cast(t
.bsd_info
, 'proc *')
2069 print GetTaskSummary
.header
+ " "+ GetProcSummary
.header
2070 print GetTaskSummary(t
) + " "+ GetProcSummary(pval
)
2072 # Look up for a given thread from the the list of threads of a given task
2073 for thval
in IterateQueue(t
.threads
, 'thread *', 'task_threads'):
2074 if (thread_flag
==1):
2076 print " " + GetThreadSummary
.header
2077 print " " + GetThreadSummary(thval
)
2078 print GetThreadBackTrace(thval
, prefix
="\t")+"\n"
2081 if(thval
==threadval
):
2082 pval
= Cast(t
.bsd_info
, 'proc *')
2083 process_name
= "{:s}".format(pval
.p_comm
)
2085 print " *** Continuing to dump the thread stacks from the process *** :" + " " + process_name