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 *
15 def GetProcName(proc
):
16 """ returns a string name of the process. Longer variant is preffered if provided.
18 proc: value object representing a proc in the kernel.
20 str: a string name of the process linked to the task.
22 name
= str(proc
.p_name
)
26 return str(proc
.p_comm
)
28 def GetProcNameForTask(task
):
29 """ returns a string name of the process. if proc is not valid "unknown" is returned
31 task: value object represeting a task in the kernel.
33 str : A string name of the process linked to the task
35 if not task
or not unsigned(task
.bsd_info
):
37 p
= Cast(task
.bsd_info
, 'proc *')
41 def GetProcPIDForTask(task
):
42 """ returns a int pid of the process. if the proc is not valid, val[5] from audit_token is returned.
44 task: value object representing a task in the kernel
46 int : pid of the process or -1 if not found
48 if task
and unsigned(task
.bsd_info
):
49 p
= Cast(task
.bsd_info
, 'proc *')
50 return unsigned(p
.p_pid
)
53 return unsigned(task
.audit_token
.val
[5])
57 def GetProcInfo(proc
):
58 """ returns a string name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields.
60 proc : value object representing a proc in the kernel
62 str : A string describing various information for process.
65 out_string
+= ("Process {p: <#020x}\n\tname {0: <32s}\n\tpid:{p.p_pid: <6d} " +
66 "task:{p.task: <#020x} p_stat:{p.p_stat: <6d} parent pid: {p.p_ppid: <6d}\n"
67 ).format(GetProcName(proc
), p
=proc
)
71 out_string
+= "Cred: euid {:d} ruid {:d} svuid {:d}\n".format(ucred
.cr_posix
.cr_uid
,
72 ucred
.cr_posix
.cr_ruid
,
73 ucred
.cr_posix
.cr_svuid
)
75 flags
= int(proc
.p_flag
)
76 out_string
+= "Flags: {0: <#020x}\n".format(flags
)
81 out_string
+= "\t" + xnudefines
.proc_flag_explain_strings
[i
] + "\n"
82 elif num
== 0x4: #special case for 32bit flag
83 out_string
+= "\t" + xnudefines
.proc_flag_explain_strings
[0] + "\n"
86 out_string
+= "State: "
87 state_val
= proc
.p_stat
88 if state_val
< 1 or state_val
> len(xnudefines
.proc_state_strings
) :
89 out_string
+= "(Unknown)"
91 out_string
+= xnudefines
.proc_state_strings
[int(state_val
)]
95 def GetProcNameForPid(pid
):
96 """ Finds the name of the process corresponding to a given pid
98 pid : int, pid you want to find the procname for
100 str : Name of the process corresponding to the pid, "Unknown" if not found
103 if int(p
.p_pid
) == int(pid
):
104 return GetProcName(p
)
107 def GetProcForPid(search_pid
):
108 """ Finds the value object representing a proc in the kernel based on its pid
110 search_pid : int, pid whose proc structure you want to find
112 value : The value object representing the proc, if a proc corresponding
113 to the given pid is found. Returns None otherwise
116 return kern
.globals.initproc
118 headp
= kern
.globals.allproc
119 for proc
in IterateListEntry(headp
, 'struct proc *', 'p_list'):
120 if proc
.p_pid
== search_pid
:
124 @lldb_command('allproc')
125 def AllProc(cmd_args
=None):
126 """ Walk through the allproc structure and print procinfo for each process structure.
128 cmd_args - [] : array of strings passed from lldb command prompt
130 for proc
in kern
.procs
:
131 print GetProcInfo(proc
)
134 @lldb_command('zombproc')
135 def ZombProc(cmd_args
=None):
136 """ Routine to print out all procs in the zombie list
138 cmd_args - [] : array of strings passed from lldb command prompt
140 if len(kern
.zombprocs
) != 0:
141 print "\nZombie Processes:"
142 for proc
in kern
.zombprocs
:
143 print GetProcInfo(proc
) + "\n\n"
145 @lldb_command('zombtasks')
146 def ZombTasks(cmd_args
=None):
147 """ Routine to print out all tasks in the zombie list
151 if len(kern
.zombprocs
) != 0:
152 header
= "\nZombie Tasks:\n"
153 header
+= GetTaskSummary
.header
+ " " + GetProcSummary
.header
154 for proc
in kern
.zombprocs
:
156 t
= Cast(proc
.task
, 'task *')
157 out_str
+= GetTaskSummary(t
) +" "+ GetProcSummary(proc
) + "\n"
162 @lldb_command('zombstacks')
163 def ZombStacks(cmd_args
=None):
164 """ Routine to print out all stacks of tasks that are exiting
167 for proc
in kern
.zombprocs
:
170 print "\nZombie Stacks:"
172 t
= Cast(proc
.task
, 'task *')
176 def GetASTSummary(ast
):
177 """ Summarizes an AST field
191 T - AST_TELEMETRY_USER
192 T - AST_TELEMETRY_KERNEL
193 T - AST_TELEMETRY_WINDOWED
203 thread_state_chars
= {0x0:'', 0x1:'P', 0x2:'Q', 0x4:'U', 0x8:'H', 0x10:'Y', 0x20:'A',
204 0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M', 0x400: 'r',
205 0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S',
206 0x20000: 'D', 0x40000: 'I', 0x80000: 'E', 0x100000: 'R', 0x200000: 'N'}
209 while mask
<= 0x80000:
210 state_str
+= thread_state_chars
[int(state
& mask
)]
216 @lldb_type_summary(['kcdata_descriptor *', 'kcdata_descriptor_t'])
217 @header("{0: <20s} {1: <20s} {2: <20s} {3: <10s} {4: <5s}".format("kcdata_descriptor", "begin_addr", "cur_pos", "size", "flags"))
218 def GetKCDataSummary(kcdata
):
219 """ Summarizes kcdata_descriptor structure
220 params: kcdata: value - value object representing kcdata_descriptor
221 returns: str - summary of the kcdata object
223 format_string
= "{0: <#020x} {1: <#020x} {2: <#020x} {3: <10d} {4: <#05x}"
224 return format_string
.format(kcdata
, kcdata
.kcd_addr_begin
, kcdata
.kcd_addr_end
, kcdata
.kcd_length
, kcdata
.kcd_flags
)
227 @lldb_type_summary(['task', 'task_t'])
228 @header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags"))
229 def GetTaskSummary(task
, showcorpse
=False):
230 """ Summarizes the important fields in task structure.
231 params: task: value - value object representing a task in kernel
232 returns: str - summary of the task
235 format_string
= '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}'
236 thread_count
= int(task
.thread_count
)
238 if hasattr(task
, "suppression_generation") and (int(task
.suppression_generation
) & 0x1) == 0x1:
240 if hasattr(task
, "effective_policy") and int(task
.effective_policy
.tep_sup_active
) == 1:
242 if hasattr(task
, "suspend_count") and int(task
.suspend_count
) > 0:
244 if hasattr(task
, 'task_imp_base') and unsigned(task
.task_imp_base
):
245 tib
= task
.task_imp_base
246 if int(tib
.iit_receiver
) == 1:
248 if int(tib
.iit_donor
) == 1:
250 if int(tib
.iit_assertcnt
) > 0:
253 # check if corpse flag is set
254 if unsigned(task
.t_flags
) & 0x20:
256 if unsigned(task
.t_flags
) & 0x40:
259 out_string
+= format_string
.format(task
, task
.map, task
.itk_space
, thread_count
, task_flags
)
260 if showcorpse
is True and unsigned(task
.corpse_info
) != 0:
261 out_string
+= " " + GetKCDataSummary(task
.corpse_info
)
264 def GetThreadName(thread
):
265 """ Get the name of a thread, if possible. Returns the empty string
268 if int(thread
.uthread
) != 0:
269 uthread
= Cast(thread
.uthread
, 'uthread *')
270 if int(uthread
.pth_name
) != 0 :
271 th_name_strval
= Cast(uthread
.pth_name
, 'char *')
272 if len(str(th_name_strval
)) > 0 :
273 return str(th_name_strval
)
277 @lldb_type_summary(['thread *', 'thread_t'])
278 @header("{0: <24s} {1: <10s} {2: <20s} {3: <6s} {4: <6s} {5: <15s} {6: <15s} {7: <8s} {8: <12s} {9: <32s} {10: <20s} {11: <20s} {12: <20s}".format('thread', 'thread_id', 'processor', 'base', 'pri', 'sched_mode', 'io_policy', 'state', 'ast', 'waitq', 'wait_event', 'wmesg', 'thread_name'))
279 def GetThreadSummary(thread
):
280 """ Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct.
281 params: thread: value - value objecte representing a thread in kernel
282 returns: str - summary of a thread
290 A - Terminated and on termination queue
301 format_string
= "{0: <24s} {1: <10s} {2: <20s} {3: <6s} {4: <6s} {5: <15s} {6: <15s} {7: <8s} {8: <12s} {9: <32s} {10: <20s} {11: <20s} {12: <20s}"
302 thread_ptr_str
= str("{0: <#020x}".format(thread
))
303 if int(thread
.static_param
) :
304 thread_ptr_str
+="[WQ]"
305 thread_id
= hex(thread
.thread_id
)
306 processor
= hex(thread
.last_processor
)
307 base_priority
= str(int(thread
.base_pri
))
308 sched_priority
= str(int(thread
.sched_pri
))
310 mode
= str(thread
.sched_mode
)
311 if "TIMESHARE" in mode
:
312 sched_mode
+="timeshare"
313 elif "FIXED" in mode
:
315 elif "REALTIME" in mode
:
316 sched_mode
+="realtime"
318 if (unsigned(thread
.bound_processor
) != 0):
322 if (unsigned(thread
.sched_flags
) & 0x0004):
326 thread_name
= GetThreadName(thread
)
327 if int(thread
.uthread
) != 0:
328 uthread
= Cast(thread
.uthread
, 'uthread *')
330 #check for io_policy flags
331 if int(uthread
.uu_flag
) & 0x400:
332 io_policy_str
+='RAGE '
334 #now flags for task_policy
338 if int(thread
.effective_policy
.thep_darwinbg
) != 0:
340 if int(thread
.effective_policy
.thep_io_tier
) != 0:
342 if int(thread
.effective_policy
.thep_io_passive
) != 0:
344 if int(thread
.effective_policy
.thep_terminated
) != 0:
347 state
= int(thread
.state
)
348 thread_state_chars
= {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
352 state_str
+= thread_state_chars
[int(state
& mask
)]
355 if int(thread
.inspection
):
358 ast
= int(thread
.ast
) |
int(thread
.reason
)
359 ast_str
= GetASTSummary(ast
)
361 #wait queue information
365 if ( state
& 0x1 ) != 0:
366 #we need to look at the waitqueue as well
367 wait_queue_str
= str("{0: <#020x}".format(int(hex(thread
.waitq
), 16)))
368 wait_event_str
= str("{0: <#020x}".format(int(hex(thread
.wait_event
), 16)))
369 wait_event_str_sym
= kern
.Symbolicate(int(hex(thread
.wait_event
), 16))
370 if len(wait_event_str_sym
) > 0:
371 wait_event_str
= wait_event_str
.strip() + " <" + wait_event_str_sym
+ ">"
372 if int(thread
.uthread
) != 0 :
373 uthread
= Cast(thread
.uthread
, 'uthread *')
374 if int(uthread
.uu_wmesg
) != 0:
375 wait_message
= str(Cast(uthread
.uu_wmesg
, 'char *'))
377 out_string
+= format_string
.format(thread_ptr_str
, thread_id
, processor
, base_priority
, sched_priority
, sched_mode
, io_policy_str
, state_str
, ast_str
, wait_queue_str
, wait_event_str
, wait_message
, thread_name
)
381 def GetTaskRoleString(role
):
383 0 : "TASK_UNSPECIFIED",
384 1 : "TASK_FOREGROUND_APPLICATION",
385 2 : "TASK_BACKGROUND_APPLICATION",
386 3 : "TASK_CONTROL_APPLICATION",
387 4 : "TASK_GRAPHICS_SERVER",
388 5 : "TASK_THROTTLE_APPLICATION",
389 6 : "TASK_NONUI_APPLICATION",
390 7 : "TASK_DEFAULT_APPLICATION",
392 return role_strs
[int(role
)]
394 def GetCoalitionFlagString(coal
):
396 if (coal
.privileged
):
397 flags
.append('privileged')
398 if (coal
.termrequested
):
399 flags
.append('termrequested')
400 if (coal
.terminated
):
401 flags
.append('terminated')
403 flags
.append('reaped')
405 flags
.append('notified')
407 flags
.append('efficient')
408 return "|".join(flags
)
410 def GetCoalitionTasks(queue
, coal_type
, thread_details
=False):
412 0x0 : "SFI_CLASS_UNSPECIFIED",
413 0x1 : "SFI_CLASS_DARWIN_BG",
414 0x2 : "SFI_CLASS_APP_NAP",
415 0x3 : "SFI_CLASS_MANAGED_FOCAL",
416 0x4 : "SFI_CLASS_MANAGED_NONFOCAL",
417 0x5 : "SFI_CLASS_DEFAULT_FOCAL",
418 0x6 : "SFI_CLASS_DEFAULT_NONFOCAL",
419 0x7 : "SFI_CLASS_KERNEL",
420 0x8 : "SFI_CLASS_OPTED_OUT",
421 0x9 : "SFI_CLASS_UTILITY",
422 0xA : "SFI_CLASS_LEGACY_FOCAL",
423 0xB : "SFI_CLASS_LEGACY_NONFOCAL",
424 0xC : "SFI_CLASS_USER_INITIATED_FOCAL",
425 0xD : "SFI_CLASS_USER_INITIATED_NONFOCAL",
426 0xE : "SFI_CLASS_USER_INTERACTIVE_FOCAL",
427 0xF : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL",
428 0x10 : "SFI_CLASS_MAINTENANCE",
431 field_name
= 'task_coalition'
432 for task
in IterateLinkageChain(queue
, 'task *', field_name
, coal_type
* sizeof('queue_chain_t')):
433 task_str
= "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task
),task
,GetProcNameForTask(task
),GetTaskRoleString(task
.effective_policy
.tep_role
))
435 for thread
in IterateQueue(task
.threads
, "thread_t", "task_threads"):
436 task_str
+= "\n\t\t\t|-> thread:" + hex(thread
) + ", " + sfi_strs
[int(thread
.sfi_class
)]
437 tasks
.append(task_str
)
440 def GetCoalitionTypeString(type):
441 """ Convert a coalition type field into a string
442 Currently supported types (from <mach/coalition.h>):
443 COALITION_TYPE_RESOURCE
444 COALITION_TYPE_JETSAM
446 if type == 0: # COALITION_TYPE_RESOURCE
452 def GetResourceCoalitionSummary(coal
, verbose
=False):
453 """ Summarize a resource coalition
455 out_string
= "Resource Coalition:\n\t Ledger:\n"
456 thread_details
= False
457 if config
['verbosity'] > vSCRIPT
:
458 thread_details
= True
459 ledgerp
= coal
.r
.ledger
460 if verbose
and unsigned(ledgerp
) != 0:
462 while i
!= ledgerp
.l_template
.lt_cnt
:
464 out_string
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, ledgerp
.l_entries
[i
], i
)
466 out_string
+= "\t bytesread {0: <d}\n\t byteswritten {1: <d}\n\t gpu_time {2: <d}".format(coal
.r
.bytesread
, coal
.r
.byteswritten
, coal
.r
.gpu_time
)
467 out_string
+= "\n\t total_tasks {0: <d}\n\t dead_tasks {1: <d}\n\t active_tasks {2: <d}".format(coal
.r
.task_count
, coal
.r
.dead_task_count
, coal
.r
.task_count
- coal
.r
.dead_task_count
)
468 out_string
+= "\n\t last_became_nonempty_time {0: <d}\n\t time_nonempty {1: <d}".format(coal
.r
.last_became_nonempty_time
, coal
.r
.time_nonempty
)
469 out_string
+= "\n\t cpu_ptime {0: <d}".format(coal
.r
.cpu_ptime
)
471 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_DEFAULT] {0: <d}".format(coal
.r
.cpu_time_eqos
[0])
472 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_MAINTENANCE] {0: <d}".format(coal
.r
.cpu_time_eqos
[1])
473 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_BACKGROUND] {0: <d}".format(coal
.r
.cpu_time_eqos
[2])
474 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_UTILITY] {0: <d}".format(coal
.r
.cpu_time_eqos
[3])
475 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_LEGACY] {0: <d}".format(coal
.r
.cpu_time_eqos
[4])
476 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_USER_INITIATED] {0: <d}".format(coal
.r
.cpu_time_eqos
[5])
477 out_string
+= "\n\t cpu_time_effective[THREAD_QOS_USER_INTERACTIVE] {0: <d}".format(coal
.r
.cpu_time_eqos
[6])
478 out_string
+= "\n\t Tasks:\n\t\t"
479 tasks
= GetCoalitionTasks(addressof(coal
.r
.tasks
), 0, thread_details
)
480 out_string
+= "\n\t\t".join(tasks
)
483 def GetJetsamCoalitionSummary(coal
, verbose
=False):
484 out_string
= "Jetsam Coalition:"
485 thread_details
= False
486 if config
['verbosity'] > vSCRIPT
:
487 thread_details
= True
488 if unsigned(coal
.j
.leader
) == 0:
489 out_string
+= "\n\t NO Leader!"
491 out_string
+= "\n\t Leader:\n\t\t"
492 out_string
+= "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(coal
.j
.leader
),coal
.j
.leader
,GetProcNameForTask(coal
.j
.leader
),GetTaskRoleString(coal
.j
.leader
.effective_policy
.tep_role
))
493 out_string
+= "\n\t Extensions:\n\t\t"
494 tasks
= GetCoalitionTasks(addressof(coal
.j
.extensions
), 1, thread_details
)
495 out_string
+= "\n\t\t".join(tasks
)
496 out_string
+= "\n\t XPC Services:\n\t\t"
497 tasks
= GetCoalitionTasks(addressof(coal
.j
.services
), 1, thread_details
)
498 out_string
+= "\n\t\t".join(tasks
)
499 out_string
+= "\n\t Other Tasks:\n\t\t"
500 tasks
= GetCoalitionTasks(addressof(coal
.j
.other
), 1, thread_details
)
501 out_string
+= "\n\t\t".join(tasks
)
502 out_string
+= "\n\t Thread Group: {0: <#020x}\n".format(coal
.j
.thread_group
)
505 @lldb_type_summary(['coalition_t', 'coalition *'])
506 @header("{0: <20s} {1: <15s} {2: <10s} {3: <10s} {4: <10s} {5: <12s} {6: <12s} {7: <20s}".format("coalition", "type", "id", "ref count", "act count", "focal cnt", "nonfocal cnt","flags"))
507 def GetCoalitionSummary(coal
):
508 if unsigned(coal
) == 0:
509 return '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'.format(0, "", -1, -1, -1, -1, -1, "")
511 format_string
= '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'
512 type_string
= GetCoalitionTypeString(coal
.type)
513 flag_string
= GetCoalitionFlagString(coal
)
514 out_string
+= format_string
.format(coal
, type_string
, coal
.id, coal
.ref_count
, coal
.active_count
, coal
.focal_task_count
, coal
.nonfocal_task_count
, flag_string
)
517 def GetCoalitionInfo(coal
, verbose
=False):
518 """ returns a string describing a coalition, including details about the particular coalition type.
520 coal : value object representing a coalition in the kernel
522 str : A string describing the coalition.
524 if unsigned(coal
) == 0:
525 return "<null coalition>"
526 typestr
= GetCoalitionTypeString(coal
.type)
527 flagstr
= GetCoalitionFlagString(coal
)
529 out_string
+= "Coalition {c: <#020x}\n\tID {c.id: <d}\n\tType {c.type: <d} ({t: <s})\n\tRefCount {c.ref_count: <d}\n\tActiveCount {c.active_count: <d}\n\tFocal Tasks: {c.focal_task_count: <d}\n\tNon-Focal Tasks: {c.nonfocal_task_count: <d}\n\tFlags {f: <s}\n\t".format(c
=coal
,t
=typestr
,f
=flagstr
)
530 if coal
.type == 0: # COALITION_TYPE_RESOURCE
531 out_string
+= GetResourceCoalitionSummary(coal
, verbose
)
532 elif coal
.type == 1: # COALITION_TYPE_JETSAM
533 out_string
+= GetJetsamCoalitionSummary(coal
, verbose
)
535 out_string
+= "Unknown Type"
539 # Macro: showcoalitioninfo
541 @lldb_command('showcoalitioninfo')
542 def ShowCoalitionInfo(cmd_args
=None, cmd_options
={}):
543 """ Display more detailed information about a coalition
544 Usage: showcoalitioninfo <address of coalition>
547 if config
['verbosity'] > vHUMAN
:
550 raise ArgumentError("No arguments passed")
551 coal
= kern
.GetValueFromAddress(cmd_args
[0], 'coalition *')
553 print "unknown arguments:", str(cmd_args
)
555 print GetCoalitionInfo(coal
, verbose
)
557 # EndMacro: showcoalitioninfo
559 # Macro: showallcoalitions
561 @lldb_command('showallcoalitions')
562 def ShowAllCoalitions(cmd_args
=None):
563 """ Print a summary listing of all the coalitions
566 print GetCoalitionSummary
.header
567 for c
in kern
.coalitions
:
568 print GetCoalitionSummary(c
)
570 # EndMacro: showallcoalitions
572 # Macro: showallthreadgroups
574 @lldb_type_summary(['struct thread_group *', 'thread_group *'])
575 @header("{0: <20s} {1: <5s} {2: <16s} {3: <5s} {4: <8s} {5: <20s}".format("thread_group", "id", "name", "refc", "flags", "recommendation"))
576 def GetThreadGroupSummary(tg
):
577 if unsigned(tg
) == 0:
578 return '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'.format(0, -1, "", -1, "", -1)
580 format_string
= '{0: <#020x} {1: <5d} {2: <16s} {3: <5d} {4: <8s} {5: <20d}'
582 if (tg
.tg_flags
& 0x1):
584 if (tg
.tg_flags
& 0x2):
586 out_string
+= format_string
.format(tg
, tg
.tg_id
, tg
.tg_name
, tg
.tg_refcount
, tg_flags
, tg
.tg_recommendation
)
589 @lldb_command('showallthreadgroups')
590 def ShowAllThreadGroups(cmd_args
=None):
591 """ Print a summary listing of all thread groups
594 print GetThreadGroupSummary
.header
595 for tg
in kern
.thread_groups
:
596 print GetThreadGroupSummary(tg
)
598 # EndMacro: showallthreadgroups
600 # Macro: showtaskcoalitions
602 @lldb_command('showtaskcoalitions', 'F:')
603 def ShowTaskCoalitions(cmd_args
=None, cmd_options
={}):
607 if "-F" in cmd_options
:
608 task_list
= FindTasksByName(cmd_options
["-F"])
610 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
613 raise ArgumentError("No arguments passed")
615 if len(task_list
) > 0:
616 print GetCoalitionSummary
.header
617 for task
in task_list
:
618 print GetCoalitionSummary(task
.coalition
[0])
619 print GetCoalitionSummary(task
.coalition
[1])
621 # EndMacro: showtaskcoalitions
623 @lldb_type_summary(['proc', 'proc *'])
624 @header("{0: >6s} {1: <18s} {2: >11s} {3: ^10s} {4: <32s}".format("pid", "process", "io_policy", "wq_state", "command"))
625 def GetProcSummary(proc
):
626 """ Summarize the process data.
628 proc : value - value representaitng a proc * in kernel
630 str - string summary of the process.
633 format_string
= "{0: >6d} {1: <#018x} {2: >11s} {3: >2d} {4: >2d} {5: >2d} {6: <32s}"
634 pval
= proc
.GetSBValue()
635 #code.interact(local=locals())
636 if str(pval
.GetType()) != str(gettype('proc *')) :
637 return "Unknown type " + str(pval
.GetType()) + " " + str(hex(proc
))
639 out_string
+= "Process " + hex(proc
) + " is not valid."
641 pid
= int(proc
.p_pid
)
642 proc_addr
= int(hex(proc
), 16)
644 if int(proc
.p_lflag
) & 0x400000 :
645 proc_rage_str
= "RAGE"
647 task
= Cast(proc
.task
, 'task *')
651 if int(task
.effective_policy
.tep_darwinbg
) != 0:
653 if int(task
.effective_policy
.tep_lowpri_cpu
) != 0:
656 if int(task
.effective_policy
.tep_io_tier
) != 0:
658 if int(task
.effective_policy
.tep_io_passive
) != 0:
660 if int(task
.effective_policy
.tep_terminated
) != 0:
663 if int(task
.effective_policy
.tep_latency_qos
) != 0:
665 if int(task
.effective_policy
.tep_sup_active
) != 0:
670 work_queue
= Cast(proc
.p_wqptr
, 'workqueue *')
671 if proc
.p_wqptr
!= 0 :
672 wq_num_threads
= int(work_queue
.wq_nthreads
)
673 wq_idle_threads
= int(work_queue
.wq_thidlecount
)
674 wq_req_threads
= int(work_queue
.wq_reqcount
)
683 process_name
= GetProcName(proc
)
684 if process_name
== 'xpcproxy':
685 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
686 thread_name
= GetThreadName(thread
)
688 process_name
+= ' (' + thread_name
+ ')'
690 out_string
+= format_string
.format(pid
, proc_addr
, " ".join([proc_rage_str
, io_policy_str
]), wq_num_threads
, wq_idle_threads
, wq_req_threads
, process_name
)
693 @lldb_type_summary(['tty_dev_t', 'tty_dev_t *'])
694 @header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","master", "slave", "open", "free", "name", "revoke"))
695 def GetTTYDevSummary(tty_dev
):
696 """ Summarizes the important fields in tty_dev_t structure.
697 params: tty_dev: value - value object representing a tty_dev_t in kernel
698 returns: str - summary of the tty_dev
701 format_string
= "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"
702 open_fn
= kern
.Symbolicate(int(hex(tty_dev
.open), 16))
703 free_fn
= kern
.Symbolicate(int(hex(tty_dev
.free
), 16))
704 name_fn
= kern
.Symbolicate(int(hex(tty_dev
.name
), 16))
705 revoke_fn
= kern
.Symbolicate(int(hex(tty_dev
.revoke
), 16))
706 out_string
+= format_string
.format(tty_dev
, tty_dev
.master
, tty_dev
.slave
, open_fn
, free_fn
, name_fn
, revoke_fn
)
711 @lldb_command('showtask', 'F:')
712 def ShowTask(cmd_args
=None, cmd_options
={}):
713 """ Routine to print a summary listing of given task
714 Usage: showtask <address of task>
715 or : showtask -F <name of task>
718 if "-F" in cmd_options
:
719 task_list
= FindTasksByName(cmd_options
['-F'])
722 raise ArgumentError("Invalid arguments passed.")
724 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
726 raise ("Unknown arguments: %r" % cmd_args
)
727 task_list
.append(tval
)
729 for tval
in task_list
:
730 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
731 pval
= Cast(tval
.bsd_info
, 'proc *')
732 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
738 @lldb_command('showpid')
739 def ShowPid(cmd_args
=None):
740 """ Routine to print a summary listing of task corresponding to given pid
741 Usage: showpid <pid value>
744 raise ArgumentError("No arguments passed")
745 pidval
= ArgumentStringToInt(cmd_args
[0])
747 pval
= Cast(t
.bsd_info
, 'proc *')
748 if pval
and pval
.p_pid
== pidval
:
749 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
750 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
757 @lldb_command('showproc')
758 def ShowProc(cmd_args
=None):
759 """ Routine to print a summary listing of task corresponding to given proc
760 Usage: showproc <address of proc>
763 raise ArgumentError("No arguments passed")
764 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
766 print "unknown arguments:", str(cmd_args
)
768 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
769 tval
= Cast(pval
.task
, 'task *')
770 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
774 # Macro: showprocinfo
776 @lldb_command('showprocinfo')
777 def ShowProcInfo(cmd_args
=None):
778 """ Routine to display name, pid, parent & task for the given proc address
779 It also shows the Cred, Flags and state of the process
780 Usage: showprocinfo <address of proc>
783 raise ArgumentError("No arguments passed")
784 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
786 print "unknown arguments:", str(cmd_args
)
788 print GetProcInfo(pval
)
790 # EndMacro: showprocinfo
792 #Macro: showprocfiles
794 @lldb_command('showprocfiles')
795 def ShowProcFiles(cmd_args
=None):
796 """ Given a proc_t pointer, display the list of open file descriptors for the referenced process.
797 Usage: showprocfiles <proc_t>
800 print ShowProcFiles
.__doc
__
802 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t')
803 proc_filedesc
= proc
.p_fd
804 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
805 proc_ofiles
= proc_filedesc
.fd_ofiles
806 if unsigned(proc_ofiles
) == 0:
807 print 'No open files for proc {0: <s}'.format(cmd_args
[0])
809 print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')
810 print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")
813 while count
<= proc_lastfile
:
814 if unsigned(proc_ofiles
[count
]) != 0:
816 proc_fd_flags
= proc_ofiles
[count
].fp_flags
817 proc_fd_fglob
= proc_ofiles
[count
].fp_glob
818 out_str
+= "{0: <5d} ".format(count
)
819 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
))
820 out_str
+= "0x{0:0>8x} ".format(unsigned(proc_fd_flags
))
821 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
822 if proc_fd_ftype
in xnudefines
.filetype_strings
:
823 out_str
+= "{0: <8s} ".format(xnudefines
.filetype_strings
[proc_fd_ftype
])
825 out_str
+= "?: {0: <5d} ".format(proc_fd_ftype
)
826 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
.fg_data
))
827 if proc_fd_ftype
== 1:
828 fd_name
= Cast(proc_fd_fglob
.fg_data
, 'struct vnode *').v_name
829 out_str
+= "{0: <64s}".format(fd_name
)
834 #EndMacro: showprocfiles
838 @lldb_command('showtty')
839 def ShowTTY(cmd_args
=None):
840 """ Display information about a struct tty
841 Usage: showtty <tty struct>
844 print ShowTTY
.__doc
__
847 tty
= kern
.GetValueFromAddress(cmd_args
[0], 'struct tty *')
848 print "TTY structure at: {0: <s}".format(cmd_args
[0])
849 print "Last input to raw queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_rawq
.c_cs
), tty
.t_rawq
.c_cs
)
850 print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_canq
.c_cs
), tty
.t_canq
.c_cs
)
851 print "Last output data: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_outq
.c_cs
), tty
.t_outq
.c_cs
)
853 ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'],
854 ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'],
855 ['', 'TS_BUSY (Draining output)'],
856 ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'],
857 ['', 'TS_FLUSH (Outq has been flushed during DMA)'],
858 ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'],
859 ['', 'TS_TBLOCK (Further input blocked)'],
860 ['', 'TS_TIMEOUT (Wait for output char processing)'],
861 ['', 'TS_TTSTOP (Output paused)'],
862 ['', 'TS_WOPEN (Open in progress)'],
863 ['', 'TS_XCLUDE (Tty requires exclusivity)'],
864 ['', 'TS_BKSL (State for lowercase \\ work)'],
865 ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'],
866 ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'],
867 ['', 'TS_LNCH (Next character is literal)'],
868 ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'],
869 ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'],
870 ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'],
871 ['', 'TS_SNOOP (Device is being snooped on)'],
872 ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'],
873 ['', 'TS_ZOMBIE (Connection lost)'],
874 ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'],
875 ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'],
876 ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)']
880 tty_state
= unsigned(tty
.t_state
)
883 if tty_state
& mask
!= 0:
884 if len(tty_state_info
[index
][1]) > 0:
885 print '\t' + tty_state_info
[index
][1]
887 if len(tty_state_info
[index
][0]) > 0:
888 print '\t' + tty_state_info
[index
][0]
891 print "Flags: 0x{0:0>8x}".format(unsigned(tty
.t_flags
))
892 print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty
.t_pgrp
))
893 print "Enclosing session: 0x{0:0>16x}".format(unsigned(tty
.t_session
))
895 print "\tInput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_iflag
))
896 print "\tOutput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_oflag
))
897 print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_cflag
))
898 print "\tLocal Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_lflag
))
899 print "\tInput Speed: {0: <8d}".format(tty
.t_termios
.c_ispeed
)
900 print "\tOutput Speed: {0: <8d}".format(tty
.t_termios
.c_ospeed
)
901 print "High Watermark: {0: <d} bytes".format(tty
.t_hiwat
)
902 print "Low Watermark : {0: <d} bytes".format(tty
.t_lowat
)
906 #Macro showallttydevs
908 @lldb_command('showallttydevs')
909 def ShowAllTTYDevs(cmd_args
=[], cmd_options
={}):
910 """ Show a list of ttydevs registered in the system.
914 tty_dev_head
= kern
.globals.tty_dev_head
915 tty_dev
= tty_dev_head
916 print GetTTYDevSummary
.header
917 while unsigned(tty_dev
) != 0:
918 print GetTTYDevSummary(tty_dev
)
919 tty_dev
= tty_dev
.next
922 #EndMacro: showallttydevs
924 #Macro: dumpthread_terminate_queue
926 @lldb_command('dumpthread_terminate_queue')
927 def DumpThreadTerminateQueue(cmd_args
=None):
928 """ Displays the contents of the specified call_entry queue.
929 Usage: dumpthread_terminate_queue
933 print GetThreadSummary
.header
934 for th
in IterateMPSCQueue(addressof(kern
.globals.thread_terminate_queue
.mpd_queue
), 'struct thread', 'mpsc_links'):
935 print GetThreadSummary(th
)
937 print "{0: <d} entries!".format(count
)
939 #EndMacro: dumpthread_terminate_queue
941 #Macro: dumpcrashed_thread_queue
943 @lldb_command('dumpcrashed_thread_queue')
944 def DumpCrashedThreadsQueue(cmd_args
=None):
945 """ Displays the contents of the specified call_entry queue.
946 Usage: dumpcrashed_thread_queue
950 print GetThreadSummary
.header
951 for th
in IterateQueue(addressof(kern
.globals.crashed_threads_queue
), 'struct thread *', 'q_link'):
952 print GetThreadSummary(th
)
954 print "{0: <d} entries!".format(count
)
956 #EndMacro: dumpcrashed_thread_queue
958 #Macro: dumpcallqueue
960 @lldb_command('dumpcallqueue')
961 def DumpCallQueue(cmd_args
=None):
962 """ Displays the contents of the specified call_entry queue.
963 Usage: dumpcallqueue <queue_head_t *>
966 raise ArgumentError("Invalid arguments")
968 print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
969 callhead
= kern
.GetValueFromAddress(cmd_args
[0], 'queue_head_t *')
971 for callentry
in IterateQueue(callhead
, 'struct call_entry *', 'q_link'):
972 print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format(
973 unsigned(callentry
), unsigned(callentry
.param0
), unsigned(callentry
.param1
),
974 unsigned(callentry
.deadline
), unsigned(callentry
.func
))
976 print "{0: <d} entries!".format(count
)
978 #EndMacro: dumpcallqueue
980 @lldb_command('showalltasklogicalwrites')
981 def ShowAllTaskIOStats(cmd_args
=None):
982 """ Commad to print I/O stats for all tasks
984 print "{0: <20s} {1: <20s} {2: <20s} {3: <20s} {4: <20s} {5: <20s} {6: <20s} {7: <20s} {8: <20s} {9: <32}".format("task", "Immediate Writes", "Deferred Writes", "Invalidated Writes", "Metadata Writes", "Immediate Writes to External", "Deferred Writes to External", "Invalidated Writes to External", "Metadata Writes to External", "name")
986 pval
= Cast(t
.bsd_info
, 'proc *')
987 print "{0: <#18x} {1: >20d} {2: >20d} {3: >20d} {4: >20d} {5: <20s} {6: <20s} {7: <20s} {8: <20s} {9: <20s}".format(t
,
988 t
.task_writes_counters_internal
.task_immediate_writes
,
989 t
.task_writes_counters_internal
.task_deferred_writes
,
990 t
.task_writes_counters_internal
.task_invalidated_writes
,
991 t
.task_writes_counters_internal
.task_metadata_writes
,
992 t
.task_writes_counters_external
.task_immediate_writes
,
993 t
.task_writes_counters_external
.task_deferred_writes
,
994 t
.task_writes_counters_external
.task_invalidated_writes
,
995 t
.task_writes_counters_external
.task_metadata_writes
,
999 @lldb_command('showalltasks','C', fancy
=True)
1000 def ShowAllTasks(cmd_args
=None, cmd_options
={}, O
=None):
1001 """ Routine to print a summary listing of all the tasks
1002 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1003 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1004 io_policy -> RAGE - rapid aging of vnodes requested
1005 NORM - normal I/O explicitly requested (this is the default)
1006 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1007 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1008 Usage: (lldb) showalltasks -C : describe the corpse structure
1013 if '-C' in cmd_options
:
1015 extra_hdr
+= " " + GetKCDataSummary
.header
1017 with O
.table(GetTaskSummary
.header
+ extra_hdr
+ " " + GetProcSummary
.header
):
1018 for t
in kern
.tasks
:
1019 pval
= Cast(t
.bsd_info
, 'proc *')
1020 print GetTaskSummary(t
, showcorpse
) + " " + GetProcSummary(pval
)
1024 @lldb_command('taskforpmap')
1025 def TaskForPmap(cmd_args
=None):
1026 """ Find the task whose pmap corresponds to <pmap>.
1027 Syntax: (lldb) taskforpmap <pmap>
1028 Multiple -v's can be specified for increased verbosity
1030 if cmd_args
== None or len(cmd_args
) < 1:
1031 raise ArgumentError("Too few arguments to taskforpmap.")
1032 pmap
= kern
.GetValueFromAddress(cmd_args
[0], 'pmap_t')
1033 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1034 for tasklist
in [kern
.tasks
, kern
.terminated_tasks
]:
1036 if kern
.GetValueFromAddress(unsigned(t
.map.pmap
), 'pmap_t') == pmap
:
1037 pval
= Cast(t
.bsd_info
, 'proc *')
1038 out_str
= GetTaskSummary(t
) + " " + GetProcSummary(pval
)
1041 @lldb_command('showterminatedtasks')
1042 def ShowTerminatedTasks(cmd_args
=None):
1043 """ Routine to print a summary listing of all the terminated tasks
1044 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1045 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1046 io_policy -> RAGE - rapid aging of vnodes requested
1047 NORM - normal I/O explicitly requested (this is the default)
1048 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1049 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1050 syntax: (lldb)showallterminatedtasks
1053 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1054 for t
in kern
.terminated_tasks
:
1055 pval
= Cast(t
.bsd_info
, 'proc *')
1056 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1059 # Macro: showtaskstacks
1061 def ShowTaskStacks(task
):
1062 """ Print a task with summary and stack information for each of its threads
1065 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1066 pval
= Cast(task
.bsd_info
, 'proc *')
1067 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1068 for th
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1069 print " " + GetThreadSummary
.header
1070 print " " + GetThreadSummary(th
)
1071 print GetThreadBackTrace(th
, prefix
=" ") + "\n"
1073 def FindTasksByName(searchstr
, ignore_case
=True):
1074 """ Search the list of tasks by name.
1076 searchstr: str - a regex like string to search for task
1077 ignore_case: bool - If False then exact matching will be enforced
1079 [] - array of task object. Empty if not found any
1083 re_options
= re
.IGNORECASE
1084 search_regex
= re
.compile(searchstr
, re_options
)
1086 for t
in kern
.tasks
:
1087 pval
= Cast(t
.bsd_info
, "proc *")
1088 process_name
= "{:s}".format(GetProcName(pval
))
1089 if search_regex
.search(process_name
):
1093 @lldb_command('showtaskstacks', 'F:')
1094 def ShowTaskStacksCmdHelper(cmd_args
=None, cmd_options
={}):
1095 """ Routine to print out the stack for each thread in a task
1096 Usage: showtaskstacks <0xaddress of task>
1097 or: showtaskstacks -F launchd
1100 if "-F" in cmd_options
:
1101 find_task_str
= cmd_options
["-F"]
1102 task_list
= FindTasksByName(find_task_str
)
1103 for tval
in task_list
:
1104 ShowTaskStacks(tval
)
1108 raise ArgumentError("No arguments passed")
1110 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1112 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
1114 ShowTaskStacks(tval
)
1117 # EndMacro: showtaskstacks
1119 def CheckTaskProcRefs(task
, proc
):
1120 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1121 if int(thread
.uthread
) == 0:
1123 uthread
= Cast(thread
.uthread
, 'uthread *')
1124 refcount
= int(uthread
.uu_proc_refcount
)
1125 uu_ref_index
= int(uthread
.uu_pindex
)
1128 for ref
in range(0, uu_ref_index
):
1129 if unsigned(uthread
.uu_proc_ps
[ref
]) == unsigned(proc
):
1130 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1131 pval
= Cast(task
.bsd_info
, 'proc *')
1132 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1133 print "\t" + GetThreadSummary
.header
1134 print "\t" + GetThreadSummary(thread
) + "\n"
1136 for frame
in range (0, 10):
1137 trace_addr
= unsigned(uthread
.uu_proc_pcs
[ref
][frame
])
1138 symbol_arr
= kern
.SymbolicateFromAddress(unsigned(trace_addr
))
1140 symbol_str
= str(symbol_arr
[0].addr
)
1143 print '{0: <#x} {1: <s}'.format(trace_addr
, symbol_str
)
1146 @lldb_command('showprocrefs')
1147 def ShowProcRefs(cmd_args
= None):
1148 """ Display information on threads/BTs that could be holding a reference on the specified proc
1149 NOTE: We can't say affirmatively if any of these references are still held since
1150 there's no way to pair references with drop-refs in the current infrastructure.
1151 Usage: showprocrefs <proc>
1153 if cmd_args
== None or len(cmd_args
) < 1:
1154 raise ArgumentError("No arguments passed")
1156 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
1158 for t
in kern
.tasks
:
1159 CheckTaskProcRefs(t
, proc
)
1160 for t
in kern
.terminated_tasks
:
1161 CheckTaskProcRefs(t
, proc
)
1165 @lldb_command('showallthreads')
1166 def ShowAllThreads(cmd_args
= None):
1167 """ Display info about all threads in the system
1169 for t
in kern
.tasks
:
1170 ShowTaskThreads([str(int(t
))])
1173 for t
in kern
.terminated_tasks
:
1174 print "Terminated: \n"
1175 ShowTaskThreads([str(int(t
))])
1180 @lldb_command('showtaskthreads', "F:")
1181 def ShowTaskThreads(cmd_args
= None, cmd_options
={}):
1182 """ Display thread information for a given task
1183 Usage: showtaskthreads <0xaddress of task>
1184 or: showtaskthreads -F <name>
1187 if "-F" in cmd_options
:
1188 task_list
= FindTasksByName(cmd_options
["-F"])
1190 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1193 raise ArgumentError("No arguments passed")
1195 for task
in task_list
:
1196 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1197 pval
= Cast(task
.bsd_info
, 'proc *')
1198 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1199 print "\t" + GetThreadSummary
.header
1200 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1201 print "\t" + GetThreadSummary(thval
)
1204 @lldb_command('showact')
1205 def ShowAct(cmd_args
=None):
1206 """ Routine to print out the state of a specific thread.
1207 usage: showact <activation>
1210 raise ArgumentError("No arguments passed")
1211 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1212 print GetThreadSummary
.header
1213 print GetThreadSummary(threadval
)
1215 @lldb_command('showactstack')
1216 def ShowActStack(cmd_args
=None):
1217 """ Routine to print out the stack of a specific thread.
1218 usage: showactstack <activation>
1221 raise ArgumentError("No arguments passed")
1222 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1223 print GetThreadSummary
.header
1224 print GetThreadSummary(threadval
)
1225 print GetThreadBackTrace(threadval
, prefix
="\t")
1228 @lldb_command('switchtoact')
1229 def SwitchToAct(cmd_args
=None):
1230 """ Switch to different context specified by activation
1231 This command allows gdb to examine the execution context and call
1232 stack for the specified activation. For example, to view the backtrace
1233 for an activation issue "switchtoact <address>", followed by "bt".
1234 Before resuming execution, issue a "resetctx" command, to
1235 return to the original execution context.
1237 if cmd_args
is None or len(cmd_args
) < 1:
1238 raise ArgumentError("No arguments passed")
1239 thval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1240 lldbthread
= GetLLDBThreadForKernelThread(thval
)
1241 print GetThreadSummary
.header
1242 print GetThreadSummary(thval
)
1243 LazyTarget
.GetProcess().selected_thread
= lldbthread
1244 if not LazyTarget
.GetProcess().SetSelectedThread(lldbthread
):
1245 print "Failed to switch thread."
1248 @lldb_command('switchtoregs')
1249 def SwitchToRegs(cmd_args
=None):
1250 """ Routine to switch to a register state.
1251 Usage: (lldb) switchtoregs <struct arm_saved_state[64] *>
1252 This command creates a fake thread in lldb with the saved register state.
1253 Note: This command ONLY works for ARM based kernel setup.
1256 if cmd_args
== None or len(cmd_args
) < 1:
1257 raise ArgumentError("No arguments passed")
1259 lldb_process
= LazyTarget
.GetProcess()
1261 saved_state
= ArgumentStringToInt(cmd_args
[0])
1262 # any change to this logic requires change in operating_system.py as well
1263 fake_thread_id
= 0xdead0000 |
(saved_state
& ~
0xffff0000)
1264 fake_thread_id
= fake_thread_id
& 0xdeadffff
1265 lldb_process
.CreateOSPluginThread(0xdeadbeef, saved_state
)
1266 lldbthread
= lldb_process
.GetThreadByID(int(fake_thread_id
))
1268 if not lldbthread
.IsValid():
1269 print "Failed to create thread"
1272 lldb_process
.selected_thread
= lldbthread
1273 if not lldb_process
.SetSelectedThread(lldbthread
):
1274 print "Failed to switch thread"
1275 print "Switched to Fake thread created from register state at 0x%x" % saved_state
1279 # Macro: showallstacks
1280 @lldb_command('showallstacks')
1281 def ShowAllStacks(cmd_args
=None):
1282 """Routine to print out the stack for each thread in the system.
1284 for t
in kern
.tasks
:
1290 # EndMacro: showallstacks
1292 # Macro: showcurrentstacks
1293 @lldb_command('showcurrentstacks')
1294 def ShowCurrentStacks(cmd_args
=None):
1295 """ Routine to print out the thread running on each cpu (incl. its stack)
1297 processor_list
= kern
.GetGlobalVariable('processor_list')
1298 current_processor
= processor_list
1299 while unsigned(current_processor
) > 0:
1300 print "\n" + GetProcessorSummary(current_processor
)
1301 active_thread
= current_processor
.active_thread
1302 if unsigned(active_thread
) != 0 :
1303 task_val
= active_thread
.task
1304 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1305 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1306 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1307 print "\t" + GetThreadSummary
.header
1308 print "\t" + GetThreadSummary(active_thread
)
1309 print "\tBacktrace:"
1310 print GetThreadBackTrace(active_thread
, prefix
="\t")
1311 current_processor
= current_processor
.processor_list
1313 # EndMacro: showcurrentstacks
1315 @lldb_command('showcurrentthreads')
1316 def ShowCurrentThreads(cmd_args
=None):
1317 """ Display info about threads running on each cpu """
1318 processor_list
= kern
.GetGlobalVariable('processor_list')
1319 current_processor
= processor_list
1320 while unsigned(current_processor
) > 0:
1321 print GetProcessorSummary(current_processor
)
1322 active_thread
= current_processor
.active_thread
1323 if unsigned(active_thread
) != 0 :
1324 task_val
= active_thread
.task
1325 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1326 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1327 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1328 print "\t" + GetThreadSummary
.header
1329 print "\t" + GetThreadSummary(active_thread
)
1330 current_processor
= current_processor
.processor_list
1333 def GetFullBackTrace(frame_addr
, verbosity
= vHUMAN
, prefix
= ""):
1334 """ Get backtrace across interrupt context.
1335 params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7)
1336 prefix - str - prefix for each line of output.
1341 frame_ptr
= frame_addr
1342 previous_frame_ptr
= 0
1343 # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
1344 mh_execute_addr
= int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
1345 while frame_ptr
and frame_ptr
!= previous_frame_ptr
and bt_count
< 128:
1346 if (not kern
.arch
.startswith('arm') and frame_ptr
< mh_execute_addr
) or (kern
.arch
.startswith('arm') and frame_ptr
> mh_execute_addr
):
1348 pc_val
= kern
.GetValueFromAddress(frame_ptr
+ kern
.ptrsize
,'uintptr_t *')
1349 pc_val
= unsigned(dereference(pc_val
))
1350 out_string
+= prefix
+ GetSourceInformationForAddress(pc_val
) + "\n"
1352 previous_frame_ptr
= frame_ptr
1353 frame_val
= kern
.GetValueFromAddress((frame_ptr
), 'uintptr_t *')
1354 if unsigned(frame_val
) == 0:
1356 frame_ptr
= unsigned(dereference(frame_val
))
1360 @lldb_command('fullbt')
1361 def FullBackTrace(cmd_args
=[]):
1362 """ Show full backtrace across the interrupt boundary.
1363 Syntax: fullbt <frame ptr>
1364 Example: fullbt `$rbp`
1366 if len(cmd_args
) < 1:
1367 print FullBackTrace
.__doc
__
1369 print GetFullBackTrace(ArgumentStringToInt(cmd_args
[0]), prefix
="\t")
1371 @lldb_command('fullbtall')
1372 def FullBackTraceAll(cmd_args
=[]):
1373 """ Show full backtrace across the interrupt boundary for threads running on all processors.
1377 for processor
in IterateLinkedList(kern
.globals.processor_list
, 'processor_list') :
1378 print "\n" + GetProcessorSummary(processor
)
1379 active_thread
= processor
.active_thread
1380 if unsigned(active_thread
) != 0 :
1381 task_val
= active_thread
.task
1382 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1383 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1384 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1385 print "\t" + GetThreadSummary
.header
1386 print "\t" + GetThreadSummary(active_thread
)
1387 print "\tBacktrace:"
1389 ThreadVal
= GetLLDBThreadForKernelThread(active_thread
)
1391 FramePtr
= ThreadVal
.frames
[0].GetFP()
1393 print GetFullBackTrace(unsigned(FramePtr
), prefix
="\t")
1396 @lldb_command('symbolicate')
1397 def SymbolicateAddress(cmd_args
=[]):
1398 """ Symbolicate an address for symbol information from loaded symbols
1399 Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr"
1401 if len(cmd_args
) < 1:
1402 print "Invalid address.\nSyntax: symbolicate <address>"
1404 print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args
[0]))
1407 @lldb_command('showinitchild')
1408 def ShowInitChild(cmd_args
=None):
1409 """ Routine to print out all processes in the system
1410 which are children of init process
1412 headp
= kern
.globals.initproc
.p_children
1413 for pp
in IterateListEntry(headp
, 'struct proc *', 'p_sibling'):
1414 print GetProcInfo(pp
)
1417 @lldb_command('showproctree')
1418 def ShowProcTree(cmd_args
=None):
1419 """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes.
1420 If no argument is given, showproctree will print all the processes in the system.
1421 If pid is specified, showproctree prints all the descendants of the indicated process
1425 search_pid
= ArgumentStringToInt(cmd_args
[0])
1428 print "pid specified must be a positive number"
1429 print ShowProcTree
.__doc
__
1432 hdr_format
= "{0: <6s} {1: <14s} {2: <9s}\n"
1433 out_string
= hdr_format
.format("PID", "PROCESS", "POINTER")
1434 out_string
+= hdr_format
.format('='*3, '='*7, '='*7)
1435 proc
= GetProcForPid(search_pid
)
1436 out_string
+= "{0: <6d} {1: <32s} [ {2: #019x} ]\n".format(proc
.p_ppid
, GetProcName(proc
.p_pptr
), unsigned(proc
.p_pptr
))
1437 out_string
+= "|--{0: <6d} {1: <32s} [ {2: #019x} ]\n".format(proc
.p_pid
, GetProcName(proc
), unsigned(proc
))
1439 ShowProcTreeRecurse(proc
, "| ")
1443 def ShowProcTreeRecurse(proc
, prefix
=""):
1444 """ Prints descendants of a given proc in hierarchial tree form
1446 proc : core.value representing a struct proc * in the kernel
1448 str : String containing info about a given proc and its descendants in tree form
1450 if proc
.p_childrencnt
> 0:
1451 head_ptr
= proc
.p_children
.lh_first
1453 for p
in IterateListEntry(proc
.p_children
, 'struct proc *', 'p_sibling'):
1454 print prefix
+ "|--{0: <6d} {1: <32s} [ {2: #019x} ]\n".format(p
.p_pid
, GetProcName(p
), unsigned(p
))
1455 ShowProcTreeRecurse(p
, prefix
+ "| ")
1457 @lldb_command('showthreadfortid')
1458 def ShowThreadForTid(cmd_args
=None):
1459 """ The thread structure contains a unique thread_id value for each thread.
1460 This command is used to retrieve the address of the thread structure(thread_t)
1461 corresponding to a given thread_id.
1464 print "Please provide thread_t whose tid you'd like to look up"
1465 print ShowThreadForTid
.__doc
__
1467 search_tid
= ArgumentStringToInt(cmd_args
[0])
1468 for taskp
in kern
.tasks
:
1469 for actp
in IterateQueue(taskp
.threads
, 'struct thread *', 'task_threads'):
1470 if search_tid
== int(actp
.thread_id
):
1471 print "Found {0: #019x}".format(actp
)
1472 print GetThreadSummary
.header
1473 print GetThreadSummary(actp
)
1475 print "Not a valid thread_id"
1477 def GetProcessorSummary(processor
):
1478 """ Internal function to print summary of processor
1479 params: processor - value representing struct processor *
1480 return: str - representing the details of given processor
1483 processor_state_str
= "INVALID"
1484 processor_state
= int(processor
.state
)
1486 processor_states
= {
1490 # 3 (formerly INACTIVE)
1496 if processor_state
in processor_states
:
1497 processor_state_str
= "{0: <11s} ".format(processor_states
[processor_state
])
1499 processor_recommended_str
= ""
1500 if int(processor
.is_recommended
) == 0:
1501 processor_recommended_str
= " (not recommended)"
1504 preemption_disable
= 0
1505 preemption_disable_str
= ""
1507 if kern
.arch
== 'x86_64':
1508 cpu_data
= kern
.globals.cpu_data_ptr
[processor
.cpu_id
]
1509 if (cpu_data
!= 0) :
1510 ast
= cpu_data
.cpu_pending_ast
1511 preemption_disable
= cpu_data
.cpu_preemption_level
1512 # On arm64, it's kern.globals.CpuDataEntries[processor.cpu_id].cpu_data_vaddr
1513 # but LLDB can't find CpuDataEntries...
1515 ast_str
= GetASTSummary(ast
)
1517 if (preemption_disable
!= 0) :
1518 preemption_disable_str
= "Preemption Disabled"
1520 out_str
= "Processor {: <#018x} cpu_id {:>#4x} AST: {:<6s} State {:<s}{:<s} {:<s}\n".format(
1521 processor
, int(processor
.cpu_id
), ast_str
, processor_state_str
, processor_recommended_str
,
1522 preemption_disable_str
)
1525 def GetLedgerEntry(ledger_template
, ledger
, i
):
1526 """ Internal function to get internals of a ledger entry (*not* a ledger itself)
1527 params: ledger_template - value representing struct ledger_template_t for the task or thread
1528 ledger - value representing struct ledger_entry *
1529 return: entry - entry dictionary
1531 ledger_limit_infinity
= (uint64_t(0x1).value
<< 63) - 1
1532 lf_refill_scheduled
= 0x0400
1533 lf_tracking_max
= 0x4000
1535 now
= unsigned(kern
.globals.sched_tick
) / 20
1540 entry
["key"] = str(ledger_template
.lt_entries
[i
].et_key
)
1541 entry
["credit"] = unsigned(ledger
.le_credit
)
1542 entry
["debit"] = unsigned(ledger
.le_debit
)
1543 entry
["balance"] = entry
["credit"] - entry
["debit"]
1544 if (ledger
.le_flags
& lf_tracking_max
):
1545 entry
["interval_max"] = unsigned(ledger
._le
._le
_max
.le_interval_max
)
1546 entry
["lifetime_max"] = unsigned(ledger
._le
._le
_max
.le_lifetime_max
)
1548 if (unsigned(ledger
.le_limit
) != ledger_limit_infinity
):
1549 entry
["limit"] = unsigned(ledger
.le_limit
)
1551 if (ledger
.le_flags
& lf_refill_scheduled
):
1552 entry
["refill_period"] = unsigned (ledger
._le
.le_refill
.le_refill_period
)
1554 if (unsigned(ledger
.le_warn_percent
) < 65535):
1555 entry
["warn_percent"] = unsigned (ledger
.le_warn_percent
* 100 / 65536)
1556 entry
["flags"] = int(ledger
.le_flags
)
1560 def FormatLedgerEntrySummary(entry
, i
, show_footprint_interval_max
=False):
1561 """ internal function to format a ledger entry into a string
1562 params: entry - A python dictionary containing the ledger entry
1563 return: str - formatted output information of ledger entries
1566 out_str
+= "{: >32s} {:<2d}:".format(entry
["key"], i
)
1567 out_str
+= "{: >15d} ".format(entry
["balance"])
1569 if (show_footprint_interval_max
):
1570 if entry
.has_key("interval_max"):
1571 out_str
+= "{:12d} ".format(entry
["interval_max"])
1575 if entry
.has_key("lifetime_max"):
1576 out_str
+= "{:14d} ".format(entry
["lifetime_max"])
1580 out_str
+= "{:12d} {:12d} ".format(entry
["credit"], entry
["debit"])
1581 if entry
.has_key("limit"):
1582 out_str
+= "{:12d} ".format(unsigned(entry
["limit"]))
1586 if entry
.has_key("refill_period"):
1587 out_str
+= "{:15d} ".format(entry
["refill_period"])
1588 out_str
+= "{:9d} ".format((entry
["limit"] * 100) / entry
["refill_period"])
1593 if entry
.has_key("warn_percent"):
1594 out_str
+= "{:9d} ".format(entry
["warn_percent"])
1598 if entry
.has_key("limit"):
1599 if entry
["balance"] > entry
["limit"]:
1606 out_str
+= "{:#8x}\n".format(entry
["flags"])
1609 def GetLedgerEntrySummary(ledger_template
, ledger
, i
, show_footprint_interval_max
=False):
1610 """ internal function to get internals of a ledger entry (*not* a ledger itself)
1611 params: ledger_template - value representing struct ledger_template_t for the task or thread
1612 ledger - value representing struct ledger_entry *
1613 return: str - formatted output information of ledger entries
1615 entry
= GetLedgerEntry(ledger_template
, ledger
, i
)
1616 return FormatLedgerEntrySummary(entry
, i
)
1619 def GetThreadLedgers(thread_val
):
1620 """ Internal function to get a summary of ledger entries for the given thread
1621 params: thread_val - value representing struct thread *
1622 return: thread - python dictionary containing threads's ledger entries. This can
1623 be printed directly with FormatThreadLedgerSummmary or outputted as json.
1626 thread
["address"] = unsigned(thread_val
)
1627 ledgerp
= thread_val
.t_threadledger
1628 thread
["entries"] = []
1631 while i
!= ledgerp
.l_template
.lt_cnt
:
1632 thread
["entries"].append(GetLedgerEntry(kern
.globals.thread_ledger_template
,
1633 ledgerp
.l_entries
[i
], i
))
1637 def FormatThreadLedgerSummary(thread
):
1638 """ Internal function to print a thread's ledger entries
1639 params: thread - python dictionary containing thread's ledger entries
1640 return: str - formatted output information for ledger entries of the input thread
1642 out_str
= " [{:#08x}]\n".format(thread
["address"])
1643 entries
= thread
["entries"]
1644 for i
, entry
in enumerate(entries
):
1645 out_str
+= FormatLedgerEntrySummary(entry
, i
)
1648 def GetTaskLedgers(task_val
):
1649 """ Internal function to get summary of ledger entries from the task and its threads
1650 params: task_val - value representing struct task *
1651 return: task - python dictionary containing tasks's ledger entries. This can
1652 be printed directly with FormatTaskLedgerSummary or outputted as json.
1654 task_ledgerp
= task_val
.ledger
1658 task
["address"] = unsigned(task_val
)
1660 pval
= Cast(task_val
.bsd_info
, 'proc *')
1662 task
["name"] = GetProcName(pval
)
1663 task
["pid"] = int(pval
.p_pid
)
1665 task
["entries"] = []
1666 while i
!= task_ledgerp
.l_template
.lt_cnt
:
1667 task
["entries"].append(GetLedgerEntry(kern
.globals.task_ledger_template
, task_ledgerp
.l_entries
[i
], i
))
1671 task
["threads"] = []
1672 for thval
in IterateQueue(task_val
.threads
, 'thread *', 'task_threads'):
1673 task
["threads"].append(GetThreadLedgers(thval
))
1677 @header("{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >14s} {5: >12s} {6: >12s} {7: >12s} {8: <15s} {9: <8s} {10: <9s} {11: <6s} {12: >6s}".format(
1678 "task [thread]", "entry", "#", "balance", "lifetime_max", "credit",
1679 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags"))
1680 def FormatTaskLedgerSummary(task
, show_footprint_interval_max
=False):
1681 """ Internal function to get summary of ledger entries from the task and its threads
1682 params: task_val - value representing struct task *
1683 return: str - formatted output information for ledger entries of the input task
1686 out_str
+= "{: #08x} ".format(task
["address"])
1687 if task
.has_key("name"):
1688 out_str
+= "{: <5s}:\n".format(task
["name"])
1690 out_str
+= "Invalid process\n"
1692 for i
, entry
in enumerate(task
["entries"]):
1693 out_str
+= FormatLedgerEntrySummary(entry
, i
, show_footprint_interval_max
)
1695 for thread
in task
["threads"]:
1696 out_str
+= FormatThreadLedgerSummary(thread
)
1700 # Macro: showtaskledgers
1702 @lldb_command('showtaskledgers', 'JF:I')
1703 def ShowTaskLedgers(cmd_args
=None, cmd_options
={}):
1704 """ Routine to print a summary of ledger entries for the task and all of its threads
1705 or : showtaskledgers [ -I ] [-J] [ -F ] <task>
1707 -I: show footprint interval max (DEV/DEBUG only)
1708 -F: specify task via name instead of address
1713 if "-F" in cmd_options
:
1714 task_list
= FindTasksByName(cmd_options
["-F"])
1715 for tval
in task_list
:
1716 print FormatTaskLedgerSummary
.header
1717 ledgers
= GetTaskLedgers(tval
)
1718 print FormatTaskLedgerSummary(ledgers
)
1720 if "-J" in cmd_options
:
1724 raise ArgumentError("No arguments passed.")
1725 show_footprint_interval_max
= False
1726 if "-I" in cmd_options
:
1727 show_footprint_interval_max
= True
1728 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1730 raise ArgumentError("unknown arguments: %r" %cmd
_args
)
1731 ledgers
= GetTaskLedgers(tval
)
1733 print json
.dumps(ledgers
)
1735 if (show_footprint_interval_max
):
1736 print "{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >12s} {5: >14s} {6: >12s} {7: >12s} {8: >12s} {9: <15s} {10: <8s} {11: <9s} {12: <6s} {13: >6s}".format(
1737 "task [thread]", "entry", "#", "balance", "intrvl_max", "lifetime_max", "credit",
1738 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags")
1740 print FormatTaskLedgerSummary
.header
1741 print FormatTaskLedgerSummary(ledgers
, show_footprint_interval_max
)
1743 # EndMacro: showtaskledgers
1745 # Macro: showalltaskledgers
1747 @lldb_command('showalltaskledgers', "J")
1748 def ShowAllTaskLedgers(cmd_args
=None, cmd_options
={}):
1749 """ Routine to print a summary of ledger entries for all tasks and respective threads
1750 Usage: showalltaskledgers [-J]
1754 if "-J" in cmd_options
:
1757 for t
in kern
.tasks
:
1758 task_val
= unsigned(t
)
1760 ShowTaskLedgers([task_val
], cmd_options
=cmd_options
)
1762 tasks
.append(GetTaskLedgers(t
))
1764 print json
.dumps(tasks
)
1766 # EndMacro: showalltaskledgers
1768 # Macro: showprocuuidpolicytable
1770 @lldb_type_summary(['proc_uuid_policy_entry'])
1771 @header("{0: <36s} {1: <10s}".format("uuid", "flags"))
1772 def GetProcUUIDPolicyEntrySummary(entry
):
1773 """ Summarizes the important fields in proc_uuid_policy_entry structure.
1774 params: entry: value - value object representing an entry
1775 returns: str - summary of the entry
1779 data
.append(int(entry
.uuid
[i
]))
1780 flags
= unsigned(entry
.flags
)
1781 out_string
= "{a[0]:02X}{a[1]:02X}{a[2]:02X}{a[3]:02X}-{a[4]:02X}{a[5]:02X}-{a[6]:02X}{a[7]:02X}-{a[8]:02X}{a[9]:02X}-{a[10]:02X}{a[11]:02X}{a[12]:02X}{a[13]:02X}{a[14]:02X}{a[15]:02X} 0x{b:0>8x}".format(a
=data
, b
=flags
)
1784 @lldb_command('showprocuuidpolicytable')
1785 def ShowProcUUIDPolicyTable(cmd_args
=None):
1786 """ Routine to print the proc UUID policy table
1787 Usage: showprocuuidpolicytable
1789 hashslots
= unsigned(kern
.globals.proc_uuid_policy_hash_mask
)
1790 print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary
.header
1791 for i
in range(0, hashslots
+1):
1792 headp
= addressof(kern
.globals.proc_uuid_policy_hashtbl
[i
])
1794 for entry
in IterateListEntry(headp
, 'struct proc_uuid_policy_entry *', 'entries'):
1795 print "{0: >2d}.{1: <5d} ".format(i
, entrynum
) + GetProcUUIDPolicyEntrySummary(entry
)
1799 # EndMacro: showprocuuidpolicytable
1801 @lldb_command('showalltaskpolicy')
1802 def ShowAllTaskPolicy(cmd_args
=None):
1804 Routine to print a summary listing of all the tasks
1805 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1806 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1807 io_policy -> RAGE - rapid aging of vnodes requested
1808 NORM - normal I/O explicitly requested (this is the default)
1809 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1810 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1813 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1814 for t
in kern
.tasks
:
1815 pval
= Cast(t
.bsd_info
, 'proc *')
1816 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1817 requested_strings
= [
1818 ["int_darwinbg", "DBG-int"],
1819 ["ext_darwinbg", "DBG-ext"],
1820 ["int_iotier", "iotier-int"],
1821 ["ext_iotier", "iotier-ext"],
1822 ["int_iopassive", "passive-int"],
1823 ["ext_iopassive", "passive-ext"],
1824 ["bg_iotier", "bg-iotier"],
1825 ["terminated", "terminated"],
1826 ["th_pidbind_bg", "bg-pidbind"],
1827 ["t_apptype", "apptype"],
1828 ["t_boosted", "boosted"],
1830 ["t_tal_enabled", "tal-enabled"],
1831 ["t_base_latency_qos", "latency-base"],
1832 ["t_over_latency_qos", "latency-override"],
1833 ["t_base_through_qos", "throughput-base"],
1834 ["t_over_through_qos", "throughput-override"]
1838 for value
in requested_strings
:
1839 if t
.requested_policy
.__getattr
__(value
[0]) :
1840 requested
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1844 suppression_strings
= [
1845 ["t_sup_active", "active"],
1846 ["t_sup_lowpri_cpu", "lowpri-cpu"],
1847 ["t_sup_timer", "timer-throttling"],
1848 ["t_sup_disk", "disk-throttling"],
1849 ["t_sup_cpu_limit", "cpu-limits"],
1850 ["t_sup_suspend", "suspend"],
1851 ["t_sup_bg_sockets", "bg-sockets"]
1855 for value
in suppression_strings
:
1856 if t
.requested_policy
.__getattr
__(value
[0]) :
1857 suppression
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1861 effective_strings
= [
1862 ["darwinbg", "background"],
1863 ["lowpri_cpu", "lowpri-cpu"],
1864 ["io_tier", "iotier"],
1865 ["io_passive", "passive"],
1866 ["all_sockets_bg", "bg-allsockets"],
1867 ["new_sockets_bg", "bg-newsockets"],
1868 ["bg_iotier", "bg-iotier"],
1869 ["terminated", "terminated"],
1870 ["t_gpu_deny", "gpu-deny"],
1871 ["t_tal_engaged", "tal-engaged"],
1872 ["t_suspended", "suspended"],
1873 ["t_watchers_bg", "bg-watchers"],
1874 ["t_latency_qos", "latency-qos"],
1875 ["t_through_qos", "throughput-qos"],
1876 ["t_sup_active", "suppression-active"],
1881 for value
in effective_strings
:
1882 if t
.effective_policy
.__getattr
__(value
[0]) :
1883 effective
+=value
[1] + ": " + str(t
.effective_policy
.__getattr
__(value
[0])) + " "
1887 print "requested: " + requested
1888 print "suppression: " + suppression
1889 print "effective: " + effective
1892 @lldb_type_summary(['wait_queue', 'wait_queue_t'])
1893 @header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask"))
1894 def GetWaitQSummary(waitq
):
1895 """ Summarizes the important fields in task structure.
1896 params: task: value - value object representing a task in kernel
1897 returns: str - summary of the task
1900 format_string
= '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
1904 if (waitq
.wq_fifo
== 1) :
1909 if (waitq
.wq_prepost
== 1) :
1912 if (waitq
.wq_type
== 0x3) :
1914 elif (waitq
.wq_type
== 0x2) :
1919 out_string
+= format_string
.format(waitq
, unsigned(waitq
.wq_interlock
.lock_data
), policy
, 0, 0, unsigned(waitq
.wq_eventmask
))
1921 out_string
+= "\n" + GetThreadSummary
.header
1923 for thread
in IterateQueue(waitq
.wq_queue
, "thread_t", "links"):
1924 out_string
+= "\n" + GetThreadSummary(thread
)
1929 @lldb_command('showallsuspendedtasks', '')
1930 def ShowSuspendedTasks(cmd_args
=[], options
={}):
1931 """ Show a list of suspended tasks with their process name summary.
1933 print GetTaskSummary
.header
+ ' ' + GetProcSummary
.header
1934 for t
in kern
.tasks
:
1935 if t
.suspend_count
> 0:
1936 print GetTaskSummary(t
) + ' ' + GetProcSummary(Cast(t
.bsd_info
, 'proc *'))
1940 @lldb_command('showallpte')
1941 def ShowAllPte(cmd_args
=None):
1942 """ Prints out the physical address of the pte for all tasks
1944 head_taskp
= addressof(kern
.globals.tasks
)
1945 taskp
= Cast(head_taskp
.next
, 'task *')
1946 while taskp
!= head_taskp
:
1947 procp
= Cast(taskp
.bsd_info
, 'proc *')
1948 out_str
= "task = {:#x} pte = {:#x}\t".format(taskp
, taskp
.map.pmap
.ttep
)
1950 out_str
+= "{:s}\n".format(GetProcName(procp
))
1954 taskp
= Cast(taskp
.tasks
.next
, 'struct task *')
1956 # EndMacro: showallpte
1958 # Macro: showallrefcounts
1959 @lldb_command('showallrefcounts')
1960 @header("{0: <20s} {1: ^10s}".format("task", "ref_count"))
1961 def ShowAllRefCounts(cmd_args
=None):
1962 """ Prints the ref_count of all tasks
1965 head_taskp
= addressof(kern
.globals.tasks
)
1966 taskp
= Cast(head_taskp
.next
, 'task *')
1967 print ShowAllRefCounts
.header
1968 while taskp
!= head_taskp
:
1969 out_str
+= "{: <#20x}".format(taskp
)
1970 out_str
+= "{: ^10d}\n".format(taskp
.ref_count
)
1971 taskp
= Cast(taskp
.tasks
.next
, 'task *')
1973 # EndMacro: showallrefcounts
1975 # Macro: showallrunnablethreads
1976 @lldb_command('showallrunnablethreads')
1977 def ShowAllRunnableThreads(cmd_args
=None):
1978 """ Prints the sched usage information for all threads of each task
1981 for taskp
in kern
.tasks
:
1982 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1983 if int(actp
.state
& 0x4):
1984 ShowActStack([unsigned(actp
)])
1986 # EndMacro: showallrunnablethreads
1988 # Macro: showallschedusage
1989 @lldb_command('showallschedusage')
1990 @header("{0:<20s} {1:^10s} {2:^10s} {3:^15s}".format("Thread", "Priority", "State", "sched_usage"))
1991 def ShowAllSchedUsage(cmd_args
=None):
1992 """ Prints the sched usage information for all threads of each task
1995 for taskp
in kern
.tasks
:
1996 ShowTask([unsigned(taskp
)])
1997 print ShowAllSchedUsage
.header
1998 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1999 out_str
= "{: <#20x}".format(actp
)
2000 out_str
+= "{: ^10s}".format(str(int(actp
.sched_pri
)))
2001 state
= int(actp
.state
)
2002 thread_state_chars
= {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'}
2004 state_str
+= thread_state_chars
[int(state
& 0x1)]
2005 state_str
+= thread_state_chars
[int(state
& 0x2)]
2006 state_str
+= thread_state_chars
[int(state
& 0x4)]
2007 state_str
+= thread_state_chars
[int(state
& 0x8)]
2008 state_str
+= thread_state_chars
[int(state
& 0x10)]
2009 state_str
+= thread_state_chars
[int(state
& 0x20)]
2010 state_str
+= thread_state_chars
[int(state
& 0x40)]
2011 state_str
+= thread_state_chars
[int(state
& 0x80)]
2012 out_str
+= "{: ^10s}".format(state_str
)
2013 out_str
+= "{: >15d}".format(actp
.sched_usage
)
2014 print out_str
+ "\n"
2017 # EndMacro: showallschedusage
2019 #Macro: showprocfilessummary
2020 @lldb_command('showprocfilessummary')
2021 @header("{0: <20s} {1: <20s} {2: >10s}".format("Process", "Name", "Number of Open Files"))
2022 def ShowProcFilesSummary(cmd_args
=None):
2023 """ Display the summary of open file descriptors for all processes in task list
2024 Usage: showprocfilessummary
2026 print ShowProcFilesSummary
.header
2027 for proc
in kern
.procs
:
2028 proc_filedesc
= proc
.p_fd
2029 proc_ofiles
= proc_filedesc
.fd_ofiles
2030 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
2033 if proc_filedesc
.fd_nfiles
!= 0:
2034 while count
<= proc_lastfile
:
2035 if unsigned(proc_ofiles
[count
]) != 0:
2036 proc_file_count
+= 1
2038 print "{0: <#020x} {1: <32s} {2: >10d}".format(proc
, GetProcName(proc
), proc_file_count
)
2040 #EndMacro: showprocfilessummary
2042 @lldb_command('workinguserstacks')
2043 def WorkingUserStacks(cmd_args
=None):
2044 """ Print out the user stack for each thread in a task, followed by the user libraries.
2045 Syntax: (lldb) workinguserstacks <task_t>
2048 print "Insufficient arguments" + ShowTaskUserStacks
.__doc
__
2050 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
2051 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
2052 pval
= Cast(task
.bsd_info
, 'proc *')
2053 print GetTaskSummary(task
) + " " + GetProcSummary(pval
) + "\n \n"
2054 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
2055 print "For thread 0x{0:x}".format(thval
)
2057 ShowThreadUserStack([hex(thval
)])
2058 except Exception as exc_err
:
2059 print "Failed to show user stack for thread 0x{0:x}".format(thval
)
2063 print "Enable debugging ('(lldb) xnudebug debug') to see detailed trace."
2064 WorkingUserLibraries([hex(task
)])
2067 @static_var("exec_load_path", 0)
2068 @lldb_command("workingkuserlibraries")
2069 def WorkingUserLibraries(cmd_args
=None):
2070 """ Show binary images known by dyld in target task
2071 For a given user task, inspect the dyld shared library state and print information about all Mach-O images.
2072 Syntax: (lldb)workinguserlibraries <task_t>
2075 print "Insufficient arguments"
2076 print ShowTaskUserLibraries
.__doc
__
2079 print "{0: <18s} {1: <12s} {2: <36s} {3: <50s}".format('address','type','uuid','path')
2080 out_format
= "0x{0:0>16x} {1: <12s} {2: <36s} {3: <50s}"
2081 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t')
2082 is_task_64
= int(task
.t_flags
) & 0x1
2083 dyld_all_image_infos_address
= unsigned(task
.all_image_info_addr
)
2085 if dyld_all_image_infos_address
== 0:
2086 print "No dyld shared library information available for task"
2088 vers_info_data
= GetUserDataAsString(task
, dyld_all_image_infos_address
, 112)
2089 version
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
2090 cur_data_offset
+= 4
2092 print "Unknown dyld all_image_infos version number %d" % version
2093 image_info_count
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
2094 WorkingUserLibraries
.exec_load_path
= 0
2096 image_info_size
= 24
2097 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 8, "uint64_t")
2098 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 8*4, "uint64_t")
2099 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 8*13, "uint64_t")
2101 image_info_size
= 12
2102 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 4*2, "uint32_t")
2103 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 4*5, "uint32_t")
2104 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 4*14, "uint32_t")
2105 # Account for ASLR slide before dyld can fix the structure
2106 dyld_load_address
= dyld_load_address
+ (dyld_all_image_infos_address
- dyld_all_image_infos_address_from_struct
)
2109 while i
< image_info_count
:
2110 image_info_address
= image_info_array_address
+ i
* image_info_size
2111 img_data
= GetUserDataAsString(task
, image_info_address
, image_info_size
)
2113 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint64_t")
2114 image_info_path
= _ExtractDataFromString(img_data
, 8, "uint64_t")
2116 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint32_t")
2117 image_info_path
= _ExtractDataFromString(img_data
, 4, "uint32_t")
2118 PrintImageInfo(task
, image_info_addr
, image_info_path
)
2121 # load_path might get set when the main executable is processed.
2122 if WorkingUserLibraries
.exec_load_path
!= 0:
2123 PrintImageInfo(task
, dyld_load_address
, WorkingUserLibraries
.exec_load_path
)
2126 # Macro: showstackaftertask
2127 @lldb_command('showstackaftertask','F:')
2128 def Showstackaftertask(cmd_args
=None,cmd_options
={}):
2129 """ Routine to print the thread stacks for all tasks succeeding a given task
2130 Usage: showstackaftertask <0xaddress of task>
2131 or: showstackaftertask -F <taskname>
2133 if "-F" in cmd_options
:
2134 # Find the task pointer corresponding to its task name
2135 find_task_str
= cmd_options
["-F"]
2136 task_list
= FindTasksByName(find_task_str
)
2138 # Iterate through the list of tasks and print all task stacks thereafter
2139 for tval
in task_list
:
2140 ListTaskStacks(tval
)
2144 raise ArgumentError("Insufficient arguments")
2145 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
2147 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
2149 ListTaskStacks(tval
)
2153 # EndMacro: showstackaftertask
2155 def ListTaskStacks(task
):
2156 """ Search for a given task and print the list of all task stacks thereafter.
2158 # Initialize local variable task_flag to mark when a given task is found.
2161 for t
in kern
.tasks
:
2162 if (task_flag
== 1):
2168 # Macro: showstackafterthread
2169 @lldb_command('showstackafterthread')
2170 def Showstackafterthread(cmd_args
= None):
2171 """ Routine to print the stacks of all threads succeeding a given thread.
2172 Usage: Showstackafterthread <0xaddress of thread>
2174 # local variable thread_flag is used to mark when a given thread is found.
2177 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
2179 raise ArgumentError("No arguments passed")
2180 # Iterate through list of all tasks to look up a given thread
2181 for t
in kern
.tasks
:
2183 pval
= Cast(t
.bsd_info
, 'proc *')
2184 print GetTaskSummary
.header
+ " "+ GetProcSummary
.header
2185 print GetTaskSummary(t
) + " "+ GetProcSummary(pval
)
2187 # Look up for a given thread from the the list of threads of a given task
2188 for thval
in IterateQueue(t
.threads
, 'thread *', 'task_threads'):
2189 if (thread_flag
==1):
2191 print " " + GetThreadSummary
.header
2192 print " " + GetThreadSummary(thval
)
2193 print GetThreadBackTrace(thval
, prefix
="\t")+"\n"
2196 if(thval
==threadval
):
2197 pval
= Cast(t
.bsd_info
, 'proc *')
2198 process_name
= "{:s}".format(GetProcName(pval
))
2200 print " *** Continuing to dump the thread stacks from the process *** :" + " " + process_name