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 *
13 def GetProcNameForTask(task
):
14 """ returns a string name of the process. if proc is not valid "unknown" is returned
16 task: value object represeting a task in the kernel.
18 str : A string name of the process linked to the task
20 if not task
or not unsigned(task
.bsd_info
):
22 p
= Cast(task
.bsd_info
, 'proc *')
25 def GetProcPIDForTask(task
):
26 """ returns a int pid of the process. if the proc is not valid, val[5] from audit_token is returned.
28 task: value object representing a task in the kernel
30 int : pid of the process or -1 if not found
32 if task
and unsigned(task
.bsd_info
):
33 p
= Cast(task
.bsd_info
, 'proc *')
34 return unsigned(p
.p_pid
)
37 return unsigned(task
.audit_token
.val
[5])
41 def GetProcInfo(proc
):
42 """ returns a string name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields.
44 proc : value object representing a proc in the kernel
46 str : A string describing various information for process.
49 out_string
+= ("Process {p: <#020x}\n\tname {p.p_comm: <20s}\n\tpid:{p.p_pid: <6d} " +
50 "task:{p.task: <#020x} p_stat:{p.p_stat: <6d} parent pid: {p.p_ppid: <6d}\n"
55 out_string
+= "Cred: euid {:d} ruid {:d} svuid {:d}\n".format(ucred
.cr_posix
.cr_uid
,
56 ucred
.cr_posix
.cr_ruid
,
57 ucred
.cr_posix
.cr_svuid
)
59 flags
= int(proc
.p_flag
)
60 out_string
+= "Flags: {0: <#020x}\n".format(flags
)
65 out_string
+= "\t" + xnudefines
.proc_flag_explain_strings
[i
] + "\n"
66 elif num
== 0x4: #special case for 32bit flag
67 out_string
+= "\t" + xnudefines
.proc_flag_explain_strings
[0] + "\n"
70 out_string
+= "State: "
71 state_val
= proc
.p_stat
72 if state_val
< 1 or state_val
> len(xnudefines
.proc_state_strings
) :
73 out_string
+= "(Unknown)"
75 out_string
+= xnudefines
.proc_state_strings
[int(state_val
)]
79 def GetProcNameForPid(pid
):
80 """ Finds the name of the process corresponding to a given pid
82 pid : int, pid you want to find the procname for
84 str : Name of the process corresponding to the pid, "Unknown" if not found
87 if int(p
.p_pid
) == int(pid
):
91 def GetProcForPid(search_pid
):
92 """ Finds the value object representing a proc in the kernel based on its pid
94 search_pid : int, pid whose proc structure you want to find
96 value : The value object representing the proc, if a proc corresponding
97 to the given pid is found. Returns None otherwise
100 return kern
.globals.initproc
102 headp
= kern
.globals.allproc
103 for proc
in IterateListEntry(headp
, 'struct proc *', 'p_list'):
104 if proc
.p_pid
== search_pid
:
108 @lldb_command('allproc')
109 def AllProc(cmd_args
=None):
110 """ Walk through the allproc structure and print procinfo for each process structure.
112 cmd_args - [] : array of strings passed from lldb command prompt
114 for proc
in kern
.procs
:
115 print GetProcInfo(proc
)
118 @lldb_command('zombproc')
119 def ZombProc(cmd_args
=None):
120 """ Routine to print out all procs in the zombie list
122 cmd_args - [] : array of strings passed from lldb command prompt
124 if len(kern
.zombprocs
) != 0:
125 print "\nZombie Processes:"
126 for proc
in kern
.zombprocs
:
127 print GetProcInfo(proc
) + "\n\n"
129 @lldb_command('zombtasks')
130 def ZombTasks(cmd_args
=None):
131 """ Routine to print out all tasks in the zombie list
135 if len(kern
.zombprocs
) != 0:
136 header
= "\nZombie Tasks:\n"
137 header
+= GetTaskSummary
.header
+ " " + GetProcSummary
.header
138 for proc
in kern
.zombprocs
:
140 t
= Cast(proc
.task
, 'task *')
141 out_str
+= GetTaskSummary(t
) +" "+ GetProcSummary(proc
) + "\n"
146 @lldb_command('zombstacks')
147 def ZombStacks(cmd_args
=None):
148 """ Routine to print out all stacks of tasks that are exiting
151 for proc
in kern
.zombprocs
:
154 print "\nZombie Stacks:"
156 t
= Cast(proc
.task
, 'task *')
160 def GetASTSummary(ast
):
161 """ Summarizes an AST field
176 T - AST_TELEMETRY_USER
177 T - AST_TELEMETRY_KERNEL
178 T - AST_TELEMETRY_WINDOWED
183 thread_state_chars
= {0x0:'', 0x1:'P', 0x2:'Q', 0x4:'U', 0x8:'H', 0x10:'Y', 0x20:'A',
184 0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M', 0x400:'C', 0x800:'C',
185 0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S'}
188 while mask
<= 0x10000:
189 state_str
+= thread_state_chars
[int(state
& mask
)]
195 @lldb_type_summary(['kcdata_descriptor *', 'kcdata_descriptor_t'])
196 @header("{0: <20s} {1: <20s} {2: <20s} {3: <10s} {4: <5s}".format("kcdata_descriptor", "begin_addr", "cur_pos", "size", "flags"))
197 def GetKCDataSummary(kcdata
):
198 """ Summarizes kcdata_descriptor structure
199 params: kcdata: value - value object representing kcdata_descriptor
200 returns: str - summary of the kcdata object
202 format_string
= "{0: <#020x} {1: <#020x} {2: <#020x} {3: <10d} {4: <#05x}"
203 return format_string
.format(kcdata
, kcdata
.kcd_addr_begin
, kcdata
.kcd_addr_end
, kcdata
.kcd_length
, kcdata
.kcd_flags
)
206 @lldb_type_summary(['task', 'task_t'])
207 @header("{0: <20s} {1: <20s} {2: <20s} {3: >5s} {4: <5s}".format("task","vm_map", "ipc_space", "#acts", "flags"))
208 def GetTaskSummary(task
, showcorpse
=False):
209 """ Summarizes the important fields in task structure.
210 params: task: value - value object representing a task in kernel
211 returns: str - summary of the task
214 format_string
= '{0: <#020x} {1: <#020x} {2: <#020x} {3: >5d} {4: <5s}'
215 thread_count
= int(task
.thread_count
)
217 if hasattr(task
, "suppression_generation") and (int(task
.suppression_generation
) & 0x1) == 0x1:
219 if hasattr(task
, "suspend_count") and int(task
.suspend_count
) > 0:
221 if hasattr(task
, 'task_imp_base') and unsigned(task
.task_imp_base
):
222 tib
= task
.task_imp_base
223 if int(tib
.iit_receiver
) == 1:
225 if int(tib
.iit_donor
) == 1:
227 if int(tib
.iit_assertcnt
) > 0:
230 # check if corpse flag is set
231 if unsigned(task
.t_flags
) & 0x20:
233 if unsigned(task
.t_flags
) & 0x40:
236 out_string
+= format_string
.format(task
, task
.map, task
.itk_space
, thread_count
, task_flags
)
237 if showcorpse
is True and unsigned(task
.corpse_info
) != 0:
238 out_string
+= " " + GetKCDataSummary(task
.corpse_info
)
241 def GetThreadName(thread
):
242 """ Get the name of a thread, if possible. Returns the empty string
245 if int(thread
.uthread
) != 0:
246 uthread
= Cast(thread
.uthread
, 'uthread *')
247 if int(uthread
.pth_name
) != 0 :
248 th_name_strval
= Cast(uthread
.pth_name
, 'char *')
249 if len(str(th_name_strval
)) > 0 :
250 return str(th_name_strval
)
254 @lldb_type_summary(['thread *', 'thread_t'])
255 @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'))
256 def GetThreadSummary(thread
):
257 """ Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct.
258 params: thread: value - value objecte representing a thread in kernel
259 returns: str - summary of a thread
267 A - Terminated and on termination queue
278 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}"
279 thread_ptr_str
= str("{0: <#020x}".format(thread
))
280 if int(thread
.static_param
) :
281 thread_ptr_str
+="[WQ]"
282 thread_id
= hex(thread
.thread_id
)
283 processor
= hex(thread
.last_processor
)
284 base_priority
= str(int(thread
.base_pri
))
285 sched_priority
= str(int(thread
.sched_pri
))
287 mode
= str(thread
.sched_mode
)
288 if "TIMESHARE" in mode
:
289 sched_mode
+="timeshare"
290 elif "FIXED" in mode
:
292 elif "REALTIME" in mode
:
293 sched_mode
+="realtime"
295 if (unsigned(thread
.bound_processor
) != 0):
299 if (unsigned(thread
.sched_flags
) & 0x0004):
303 thread_name
= GetThreadName(thread
)
304 if int(thread
.uthread
) != 0:
305 uthread
= Cast(thread
.uthread
, 'uthread *')
307 #check for io_policy flags
308 if int(uthread
.uu_flag
) & 0x400:
309 io_policy_str
+='RAGE '
311 #now flags for task_policy
315 if int(thread
.effective_policy
.thep_darwinbg
) != 0:
317 if int(thread
.effective_policy
.thep_io_tier
) != 0:
319 if int(thread
.effective_policy
.thep_io_passive
) != 0:
321 if int(thread
.effective_policy
.thep_terminated
) != 0:
324 state
= int(thread
.state
)
325 thread_state_chars
= {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
329 state_str
+= thread_state_chars
[int(state
& mask
)]
332 if int(thread
.inspection
):
335 ast
= int(thread
.ast
) |
int(thread
.reason
)
336 ast_str
= GetASTSummary(ast
)
338 #wait queue information
342 if ( state
& 0x1 ) != 0:
343 #we need to look at the waitqueue as well
344 wait_queue_str
= str("{0: <#020x}".format(int(hex(thread
.waitq
), 16)))
345 wait_event_str
= str("{0: <#020x}".format(int(hex(thread
.wait_event
), 16)))
346 wait_event_str_sym
= kern
.Symbolicate(int(hex(thread
.wait_event
), 16))
347 if len(wait_event_str_sym
) > 0:
348 wait_event_str
= wait_event_str
.strip() + " <" + wait_event_str_sym
+ ">"
349 if int(thread
.uthread
) != 0 :
350 uthread
= Cast(thread
.uthread
, 'uthread *')
351 if int(uthread
.uu_wmesg
) != 0:
352 wait_message
= str(Cast(uthread
.uu_wmesg
, 'char *'))
354 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
)
358 def GetTaskRoleString(role
):
360 0 : "TASK_UNSPECIFIED",
361 1 : "TASK_FOREGROUND_APPLICATION",
362 2 : "TASK_BACKGROUND_APPLICATION",
363 3 : "TASK_CONTROL_APPLICATION",
364 4 : "TASK_GRAPHICS_SERVER",
365 5 : "TASK_THROTTLE_APPLICATION",
366 6 : "TASK_NONUI_APPLICATION",
367 7 : "TASK_DEFAULT_APPLICATION",
369 return role_strs
[int(role
)]
371 def GetCoalitionFlagString(coal
):
373 if (coal
.privileged
):
374 flags
.append('privileged')
375 if (coal
.termrequested
):
376 flags
.append('termrequested')
377 if (coal
.terminated
):
378 flags
.append('terminated')
380 flags
.append('reaped')
382 flags
.append('notified')
383 return "|".join(flags
)
385 def GetCoalitionTasks(queue
, coal_type
, thread_details
=False):
387 0x0 : "SFI_CLASS_UNSPECIFIED",
388 0x1 : "SFI_CLASS_DARWIN_BG",
389 0x2 : "SFI_CLASS_APP_NAP",
390 0x3 : "SFI_CLASS_MANAGED_FOCAL",
391 0x4 : "SFI_CLASS_MANAGED_NONFOCAL",
392 0x5 : "SFI_CLASS_DEFAULT_FOCAL",
393 0x6 : "SFI_CLASS_DEFAULT_NONFOCAL",
394 0x7 : "SFI_CLASS_KERNEL",
395 0x8 : "SFI_CLASS_OPTED_OUT",
396 0x9 : "SFI_CLASS_UTILITY",
397 0xA : "SFI_CLASS_LEGACY_FOCAL",
398 0xB : "SFI_CLASS_LEGACY_NONFOCAL",
399 0xC : "SFI_CLASS_USER_INITIATED_FOCAL",
400 0xD : "SFI_CLASS_USER_INITIATED_NONFOCAL",
401 0xE : "SFI_CLASS_USER_INTERACTIVE_FOCAL",
402 0xF : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL",
403 0x10 : "SFI_CLASS_MAINTENANCE",
406 field_name
= 'task_coalition'
407 for task
in IterateLinkageChain(queue
, 'task *', field_name
, coal_type
* sizeof('queue_chain_t')):
408 task_str
= "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task
),task
,GetProcNameForTask(task
),GetTaskRoleString(task
.effective_policy
.tep_role
))
410 for thread
in IterateQueue(task
.threads
, "thread_t", "task_threads"):
411 task_str
+= "\n\t\t\t|-> thread:" + hex(thread
) + ", " + sfi_strs
[int(thread
.sfi_class
)]
412 tasks
.append(task_str
)
415 def GetCoalitionTypeString(type):
416 """ Convert a coalition type field into a string
417 Currently supported types (from <mach/coalition.h>):
418 COALITION_TYPE_RESOURCE
419 COALITION_TYPE_JETSAM
421 if type == 0: # COALITION_TYPE_RESOURCE
427 def GetResourceCoalitionSummary(coal
, verbose
=False):
428 """ Summarize a resource coalition
430 out_string
= "Resource Coalition:\n\t Ledger:\n"
431 thread_details
= False
432 if config
['verbosity'] > vSCRIPT
:
433 thread_details
= True
434 ledgerp
= coal
.r
.ledger
435 if verbose
and unsigned(ledgerp
) != 0:
437 while i
!= ledgerp
.l_template
.lt_cnt
:
439 out_string
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, ledgerp
.l_entries
[i
], i
)
441 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
)
442 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
)
443 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
)
444 out_string
+= "\n\t Tasks:\n\t\t"
445 tasks
= GetCoalitionTasks(addressof(coal
.r
.tasks
), 0, thread_details
)
446 out_string
+= "\n\t\t".join(tasks
)
449 def GetJetsamCoalitionSummary(coal
, verbose
=False):
450 out_string
= "Jetsam Coalition:"
451 thread_details
= False
452 if config
['verbosity'] > vSCRIPT
:
453 thread_details
= True
454 if unsigned(coal
.j
.leader
) == 0:
455 out_string
+= "\n\t NO Leader!"
457 out_string
+= "\n\t Leader:\n\t\t"
458 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
.t_role
))
459 out_string
+= "\n\t Extensions:\n\t\t"
460 tasks
= GetCoalitionTasks(addressof(coal
.j
.extensions
), 1, thread_details
)
461 out_string
+= "\n\t\t".join(tasks
)
462 out_string
+= "\n\t XPC Services:\n\t\t"
463 tasks
= GetCoalitionTasks(addressof(coal
.j
.services
), 1, thread_details
)
464 out_string
+= "\n\t\t".join(tasks
)
465 out_string
+= "\n\t Other Tasks:\n\t\t"
466 tasks
= GetCoalitionTasks(addressof(coal
.j
.other
), 1, thread_details
)
467 out_string
+= "\n\t\t".join(tasks
)
470 @lldb_type_summary(['coalition_t', 'coalition *'])
471 @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"))
472 def GetCoalitionSummary(coal
):
473 if unsigned(coal
) == 0:
474 return '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'.format(0, "", -1, -1, -1, -1, -1, "")
476 format_string
= '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'
477 type_string
= GetCoalitionTypeString(coal
.type)
478 flag_string
= GetCoalitionFlagString(coal
)
479 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
)
482 def GetCoalitionInfo(coal
, verbose
=False):
483 """ returns a string describing a coalition, including details about the particular coalition type.
485 coal : value object representing a coalition in the kernel
487 str : A string describing the coalition.
489 if unsigned(coal
) == 0:
490 return "<null coalition>"
491 typestr
= GetCoalitionTypeString(coal
.type)
492 flagstr
= GetCoalitionFlagString(coal
)
494 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
)
495 if coal
.type == 0: # COALITION_TYPE_RESOURCE
496 out_string
+= GetResourceCoalitionSummary(coal
, verbose
)
497 elif coal
.type == 1: # COALITION_TYPE_JETSAM
498 out_string
+= GetJetsamCoalitionSummary(coal
, verbose
)
500 out_string
+= "Unknown Type"
504 # Macro: showcoalitioninfo
506 @lldb_command('showcoalitioninfo')
507 def ShowCoalitionInfo(cmd_args
=None, cmd_options
={}):
508 """ Display more detailed information about a coalition
509 Usage: showcoalitioninfo <address of coalition>
512 if config
['verbosity'] > vHUMAN
:
515 print "No arguments passed"
516 print ShowCoalitionInfo
.__doc
__
518 coal
= kern
.GetValueFromAddress(cmd_args
[0], 'coalition *')
520 print "unknown arguments:", str(cmd_args
)
522 print GetCoalitionInfo(coal
, verbose
)
524 # EndMacro: showcoalitioninfo
526 # Macro: showallcoalitions
528 @lldb_command('showallcoalitions')
529 def ShowAllCoalitions(cmd_args
=None):
530 """ Print a summary listing of all the coalitions
533 print GetCoalitionSummary
.header
534 for c
in kern
.coalitions
:
535 print GetCoalitionSummary(c
)
537 # EndMacro: showallcoalitions
539 # Macro: showtaskcoalitions
541 @lldb_command('showtaskcoalitions', 'F:')
542 def ShowTaskCoalitions(cmd_args
=None, cmd_options
={}):
546 if "-F" in cmd_options
:
547 task_list
= FindTasksByName(cmd_options
["-F"])
549 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
552 raise ArgumentError("No arguments passed")
554 if len(task_list
) > 0:
555 print GetCoalitionSummary
.header
556 for task
in task_list
:
557 print GetCoalitionSummary(task
.coalition
[0])
558 print GetCoalitionSummary(task
.coalition
[1])
560 # EndMacro: showtaskcoalitions
562 @lldb_type_summary(['proc', 'proc *'])
563 @header("{0: >6s} {1: ^20s} {2: >14s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command"))
564 def GetProcSummary(proc
):
565 """ Summarize the process data.
567 proc : value - value representaitng a proc * in kernel
569 str - string summary of the process.
572 format_string
= "{0: >6d} {1: >#020x} {2: >14s} {3: >2d} {4: >2d} {5: >2d} {6: <20s}"
573 pval
= proc
.GetSBValue()
574 #code.interact(local=locals())
575 if str(pval
.GetType()) != str(gettype('proc *')) :
576 return "Unknown type " + str(pval
.GetType()) + " " + str(hex(proc
))
578 out_string
+= "Process " + hex(proc
) + " is not valid."
580 pid
= int(proc
.p_pid
)
581 proc_addr
= int(hex(proc
), 16)
583 if int(proc
.p_lflag
) & 0x400000 :
584 proc_rage_str
= "RAGE"
586 task
= Cast(proc
.task
, 'task *')
590 if int(task
.effective_policy
.tep_darwinbg
) != 0:
592 if int(task
.effective_policy
.tep_lowpri_cpu
) != 0:
595 if int(task
.effective_policy
.tep_io_tier
) != 0:
597 if int(task
.effective_policy
.tep_io_passive
) != 0:
599 if int(task
.effective_policy
.tep_terminated
) != 0:
602 if int(task
.effective_policy
.tep_latency_qos
) != 0:
604 if int(task
.effective_policy
.tep_sup_active
) != 0:
609 work_queue
= Cast(proc
.p_wqptr
, 'workqueue *')
610 if proc
.p_wqptr
!= 0 :
611 wq_num_threads
= int(work_queue
.wq_nthreads
)
612 wq_idle_threads
= int(work_queue
.wq_thidlecount
)
613 wq_req_threads
= int(work_queue
.wq_reqcount
)
622 process_name
= str(proc
.p_comm
)
623 if process_name
== 'xpcproxy':
624 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
625 thread_name
= GetThreadName(thread
)
627 process_name
+= ' (' + thread_name
+ ')'
629 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
)
632 @lldb_type_summary(['tty_dev_t', 'tty_dev_t *'])
633 @header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","master", "slave", "open", "free", "name", "revoke"))
634 def GetTTYDevSummary(tty_dev
):
635 """ Summarizes the important fields in tty_dev_t structure.
636 params: tty_dev: value - value object representing a tty_dev_t in kernel
637 returns: str - summary of the tty_dev
640 format_string
= "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"
641 open_fn
= kern
.Symbolicate(int(hex(tty_dev
.open), 16))
642 free_fn
= kern
.Symbolicate(int(hex(tty_dev
.free
), 16))
643 name_fn
= kern
.Symbolicate(int(hex(tty_dev
.name
), 16))
644 revoke_fn
= kern
.Symbolicate(int(hex(tty_dev
.revoke
), 16))
645 out_string
+= format_string
.format(tty_dev
, tty_dev
.master
, tty_dev
.slave
, open_fn
, free_fn
, name_fn
, revoke_fn
)
648 @lldb_type_summary(['kqueue *'])
649 @header("{: <20s} {: <20s} {: <6s} {: <20s} {: <10s}".format('kqueue', 'process', '#events', 'wqs', 'state'))
650 def GetKQueueSummary(kq
):
651 """ summarizes kqueue information
652 returns: str - summary of kqueue
655 format_string
= "{o: <#020x} {o.kq_p: <#020x} {o.kq_count: <6d} {wqs: <#020x} {st_str: <10s}"
656 state
= int(kq
.kq_state
)
660 if int(state
& mask
):
661 state_str
+= ' ' + xnudefines
.kq_state_strings
[int(state
& mask
)]
663 out_string
+= format_string
.format(o
=kq
, wqs
=addressof(kq
.kq_wqs
), st_str
=state_str
)
664 out_string
+= "\n" + GetKnoteSummary
.header
665 for kn
in IterateTAILQ_HEAD(kq
.kq_head
, 'kn_tqe'):
666 out_string
+= "\n" + GetKnoteSummary(kn
)
669 @lldb_type_summary(['knote *'])
670 @header("{0: <20s} {1: <10s} {2: <10s} {3: <20s} {4: <20s} {5: <30s}".format('knote', 'ident', 'kev_flags', 'kn_kq', 'filtops', ' status'))
671 def GetKnoteSummary(kn
):
672 """ Summarizes a knote and related information
673 returns: str - summary of knote
676 format_string
= "{o: <#020x} {o.kn_kevent.ident: <#010X} {o.kn_kevent.flags: <#010X} {o.kn_kq: <#020X} {ops_str: <20s} {st_str: <30s}"
677 state
= unsigned(kn
.kn_status
)
678 fops_str
= kern
.Symbolicate(unsigned(kn
.kn_fop
))
683 status_desc
+= ' ' + xnudefines
.kn_state_strings
[int(state
& mask
)]
686 out_string
+= format_string
.format(o
=kn
, st_str
=status_desc
, ops_str
=fops_str
)
691 @lldb_command('showtask', 'F:')
692 def ShowTask(cmd_args
=None, cmd_options
={}):
693 """ Routine to print a summary listing of given task
694 Usage: showtask <address of task>
695 or : showtask -F <name of task>
698 if "-F" in cmd_options
:
699 task_list
= FindTasksByName(cmd_options
['-F'])
702 raise ArgumentError("Invalid arguments passed.")
704 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
706 raise ("Unknown arguments: %r" % cmd_args
)
707 task_list
.append(tval
)
709 for tval
in task_list
:
710 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
711 pval
= Cast(tval
.bsd_info
, 'proc *')
712 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
718 @lldb_command('showpid')
719 def ShowPid(cmd_args
=None):
720 """ Routine to print a summary listing of task corresponding to given pid
721 Usage: showpid <pid value>
724 print "No arguments passed"
725 print ShowPid
.__doc
__
727 pidval
= ArgumentStringToInt(cmd_args
[0])
729 pval
= Cast(t
.bsd_info
, 'proc *')
730 if pval
and pval
.p_pid
== pidval
:
731 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
732 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
739 @lldb_command('showproc')
740 def ShowProc(cmd_args
=None):
741 """ Routine to print a summary listing of task corresponding to given proc
742 Usage: showproc <address of proc>
745 print "No arguments passed"
746 print ShowProc
.__doc
__
748 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
750 print "unknown arguments:", str(cmd_args
)
752 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
753 tval
= Cast(pval
.task
, 'task *')
754 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
758 # Macro: showprocinfo
760 @lldb_command('showprocinfo')
761 def ShowProcInfo(cmd_args
=None):
762 """ Routine to display name, pid, parent & task for the given proc address
763 It also shows the Cred, Flags and state of the process
764 Usage: showprocinfo <address of proc>
767 print "No arguments passed"
768 print ShowProcInfo
.__doc
__
770 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
772 print "unknown arguments:", str(cmd_args
)
774 print GetProcInfo(pval
)
776 # EndMacro: showprocinfo
778 #Macro: showprocfiles
780 @lldb_command('showprocfiles')
781 def ShowProcFiles(cmd_args
=None):
782 """ Given a proc_t pointer, display the list of open file descriptors for the referenced process.
783 Usage: showprocfiles <proc_t>
786 print ShowProcFiles
.__doc
__
788 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t')
789 proc_filedesc
= proc
.p_fd
790 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
791 proc_ofiles
= proc_filedesc
.fd_ofiles
792 if unsigned(proc_ofiles
) == 0:
793 print 'No open files for proc {0: <s}'.format(cmd_args
[0])
795 print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')
796 print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")
810 while count
<= proc_lastfile
:
811 if unsigned(proc_ofiles
[count
]) != 0:
813 proc_fd_flags
= proc_ofiles
[count
].f_flags
814 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
815 out_str
+= "{0: <5d} ".format(count
)
816 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
))
817 out_str
+= "0x{0:0>8x} ".format(unsigned(proc_fd_flags
))
818 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
819 if proc_fd_ftype
in filetype_dict
:
820 out_str
+= "{0: <8s} ".format(filetype_dict
[proc_fd_ftype
])
822 out_str
+= "?: {0: <5d} ".format(proc_fd_ftype
)
823 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
.fg_data
))
824 if proc_fd_ftype
== 1:
825 fd_name
= Cast(proc_fd_fglob
.fg_data
, 'struct vnode *').v_name
826 out_str
+= "{0: <64s}".format(fd_name
)
831 #EndMacro: showprocfiles
834 def GetProcKqueues(proc
):
837 proc_filedesc
= proc
.p_fd
838 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
839 proc_ofiles
= proc_filedesc
.fd_ofiles
843 if unsigned(proc_ofiles
) == 0:
848 while count
<= proc_lastfile
:
849 if unsigned(proc_ofiles
[count
]) != 0:
850 proc_fd_flags
= proc_ofiles
[count
].f_flags
851 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
852 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
853 if proc_fd_ftype
== filetype_KQUEUE
:
854 q
= Cast(proc_fd_fglob
.fg_data
, 'struct kqueue *')
862 if unsigned(t
.bsd_info
) == 0:
864 pval
= Cast(t
.bsd_info
, 'proc *')
865 for kq
in GetProcKqueues(pval
):
868 #Macro: showallkqueues
869 @lldb_command('showallkqueues' ,'')
870 def ShowAllKqueues(cmd_args
=[], cmd_options
={}):
871 """ Display a summary of all the kqueues in the system """
872 for kq
in GetAllKqueues():
873 print GetKQueueSummary
.header
874 print GetKQueueSummary(kq
)
876 #EndMacro: showallkqueues
879 @lldb_command('showkqueue' ,'')
880 def ShowKQueue(cmd_args
=[], cmd_options
={}):
881 """ Given a struct kqueue pointer, display the summary of the kqueue
882 Usage: (lldb) showkqueue <struct kqueue *>
885 raise ArgumentError('Invalid arguments')
887 kq
= kern
.GetValueFromAddress(cmd_args
[0], 'struct kqueue *')
888 print GetKQueueSummary
.header
889 print GetKQueueSummary(kq
)
891 #EndMacro: showkqueue
895 @lldb_command('showtty')
896 def ShowTTY(cmd_args
=None):
897 """ Display information about a struct tty
898 Usage: showtty <tty struct>
901 print ShowTTY
.__doc
__
904 tty
= kern
.GetValueFromAddress(cmd_args
[0], 'struct tty *')
905 print "TTY structure at: {0: <s}".format(cmd_args
[0])
906 print "Last input to raw queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_rawq
.c_cs
), tty
.t_rawq
.c_cs
)
907 print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_canq
.c_cs
), tty
.t_canq
.c_cs
)
908 print "Last output data: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_outq
.c_cs
), tty
.t_outq
.c_cs
)
910 ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'],
911 ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'],
912 ['', 'TS_BUSY (Draining output)'],
913 ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'],
914 ['', 'TS_FLUSH (Outq has been flushed during DMA)'],
915 ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'],
916 ['', 'TS_TBLOCK (Further input blocked)'],
917 ['', 'TS_TIMEOUT (Wait for output char processing)'],
918 ['', 'TS_TTSTOP (Output paused)'],
919 ['', 'TS_WOPEN (Open in progress)'],
920 ['', 'TS_XCLUDE (Tty requires exclusivity)'],
921 ['', 'TS_BKSL (State for lowercase \\ work)'],
922 ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'],
923 ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'],
924 ['', 'TS_LNCH (Next character is literal)'],
925 ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'],
926 ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'],
927 ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'],
928 ['', 'TS_SNOOP (Device is being snooped on)'],
929 ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'],
930 ['', 'TS_ZOMBIE (Connection lost)'],
931 ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'],
932 ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'],
933 ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)']
937 tty_state
= unsigned(tty
.t_state
)
940 if tty_state
& mask
!= 0:
941 if len(tty_state_info
[index
][1]) > 0:
942 print '\t' + tty_state_info
[index
][1]
944 if len(tty_state_info
[index
][0]) > 0:
945 print '\t' + tty_state_info
[index
][0]
948 print "Flags: 0x{0:0>8x}".format(unsigned(tty
.t_flags
))
949 print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty
.t_pgrp
))
950 print "Enclosing session: 0x{0:0>16x}".format(unsigned(tty
.t_session
))
952 print "\tInput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_iflag
))
953 print "\tOutput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_oflag
))
954 print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_cflag
))
955 print "\tLocal Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_lflag
))
956 print "\tInput Speed: {0: <8d}".format(tty
.t_termios
.c_ispeed
)
957 print "\tOutput Speed: {0: <8d}".format(tty
.t_termios
.c_ospeed
)
958 print "High Watermark: {0: <d} bytes".format(tty
.t_hiwat
)
959 print "Low Watermark : {0: <d} bytes".format(tty
.t_lowat
)
963 #Macro showallttydevs
965 @lldb_command('showallttydevs')
966 def ShowAllTTYDevs(cmd_args
=[], cmd_options
={}):
967 """ Show a list of ttydevs registered in the system.
971 tty_dev_head
= kern
.globals.tty_dev_head
972 tty_dev
= tty_dev_head
973 print GetTTYDevSummary
.header
974 while unsigned(tty_dev
) != 0:
975 print GetTTYDevSummary(tty_dev
)
976 tty_dev
= tty_dev
.next
979 #EndMacro: showallttydevs
981 #Macro: dumpthread_terminate_queue
983 @lldb_command('dumpthread_terminate_queue')
984 def DumpThreadTerminateQueue(cmd_args
=None):
985 """ Displays the contents of the specified call_entry queue.
986 Usage: dumpthread_terminate_queue
990 print GetThreadSummary
.header
991 for th
in IterateQueue(addressof(kern
.globals.thread_terminate_queue
), 'struct thread *', 'q_link'):
992 print GetThreadSummary(th
)
994 print "{0: <d} entries!".format(count
)
996 #EndMacro: dumpthread_terminate_queue
998 #Macro: dumpcrashed_thread_queue
1000 @lldb_command('dumpcrashed_thread_queue')
1001 def DumpCrashedThreadsQueue(cmd_args
=None):
1002 """ Displays the contents of the specified call_entry queue.
1003 Usage: dumpcrashed_thread_queue
1007 print GetThreadSummary
.header
1008 for th
in IterateQueue(addressof(kern
.globals.crashed_threads_queue
), 'struct thread *', 'q_link'):
1009 print GetThreadSummary(th
)
1011 print "{0: <d} entries!".format(count
)
1013 #EndMacro: dumpcrashed_thread_queue
1015 #Macro: dumpcallqueue
1017 @lldb_command('dumpcallqueue')
1018 def DumpCallQueue(cmd_args
=None):
1019 """ Displays the contents of the specified call_entry queue.
1020 Usage: dumpcallqueue <queue_head_t *>
1023 raise ArgumentError("Invalid arguments")
1025 print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
1026 callhead
= kern
.GetValueFromAddress(cmd_args
[0], 'queue_head_t *')
1028 for callentry
in IterateQueue(callhead
, 'struct call_entry *', 'q_link'):
1029 print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format(
1030 unsigned(callentry
), unsigned(callentry
.param0
), unsigned(callentry
.param1
),
1031 unsigned(callentry
.deadline
), unsigned(callentry
.func
))
1033 print "{0: <d} entries!".format(count
)
1035 #EndMacro: dumpcallqueue
1037 @lldb_command('showalltasklogicalwrites')
1038 def ShowAllTaskIOStats(cmd_args
=None):
1039 """ Commad to print I/O stats for all tasks
1041 print "{0: <20s} {1: <20s} {2: <20s} {3: <20s} {4: <20s} {5: <20s}".format("task", "Immediate Writes", "Deferred Writes", "Invalidated Writes", "Metadata Writes", "name")
1042 for t
in kern
.tasks
:
1043 pval
= Cast(t
.bsd_info
, 'proc *')
1044 print "{0: <#18x} {1: >20d} {2: >20d} {3: >20d} {4: >20d} {5: <20s}".format(t
,
1045 t
.task_immediate_writes
,
1046 t
.task_deferred_writes
,
1047 t
.task_invalidated_writes
,
1048 t
.task_metadata_writes
,
1052 @lldb_command('showalltasks','C')
1053 def ShowAllTasks(cmd_args
=None, cmd_options
={}):
1054 """ Routine to print a summary listing of all the tasks
1055 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1056 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1057 io_policy -> RAGE - rapid aging of vnodes requested
1058 NORM - normal I/O explicitly requested (this is the default)
1059 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1060 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1061 Usage: (lldb) showalltasks -C : describe the corpse structure
1066 if '-C' in cmd_options
:
1068 extra_hdr
+= " " + GetKCDataSummary
.header
1070 print GetTaskSummary
.header
+ extra_hdr
+ " " + GetProcSummary
.header
1071 for t
in kern
.tasks
:
1072 pval
= Cast(t
.bsd_info
, 'proc *')
1073 out_str
= GetTaskSummary(t
, showcorpse
) + " " + GetProcSummary(pval
)
1077 @lldb_command('taskforpmap')
1078 def TaskForPmap(cmd_args
=None):
1079 """ Find the task whose pmap corresponds to <pmap>.
1080 Syntax: (lldb) taskforpmap <pmap>
1081 Multiple -v's can be specified for increased verbosity
1083 if cmd_args
== None or len(cmd_args
) < 1:
1084 raise ArgumentError("Too few arguments to taskforpmap.")
1085 pmap
= kern
.GetValueFromAddress(cmd_args
[0], 'pmap_t')
1086 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1087 for tasklist
in [kern
.tasks
, kern
.terminated_tasks
]:
1089 if t
.map.pmap
== pmap
:
1090 pval
= Cast(t
.bsd_info
, 'proc *')
1091 out_str
= GetTaskSummary(t
) + " " + GetProcSummary(pval
)
1094 @lldb_command('showterminatedtasks')
1095 def ShowTerminatedTasks(cmd_args
=None):
1096 """ Routine to print a summary listing of all the terminated tasks
1097 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1098 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1099 io_policy -> RAGE - rapid aging of vnodes requested
1100 NORM - normal I/O explicitly requested (this is the default)
1101 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1102 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1103 syntax: (lldb)showallterminatedtasks
1106 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1107 for t
in kern
.terminated_tasks
:
1108 pval
= Cast(t
.bsd_info
, 'proc *')
1109 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1112 # Macro: showtaskstacks
1114 def ShowTaskStacks(task
):
1115 """ Print a task with summary and stack information for each of its threads
1118 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1119 pval
= Cast(task
.bsd_info
, 'proc *')
1120 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1121 for th
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1122 print " " + GetThreadSummary
.header
1123 print " " + GetThreadSummary(th
)
1124 print GetThreadBackTrace(th
, prefix
=" ") + "\n"
1126 def FindTasksByName(searchstr
, ignore_case
=True):
1127 """ Search the list of tasks by name.
1129 searchstr: str - a regex like string to search for task
1130 ignore_case: bool - If False then exact matching will be enforced
1132 [] - array of task object. Empty if not found any
1136 re_options
= re
.IGNORECASE
1137 search_regex
= re
.compile(searchstr
, re_options
)
1139 for t
in kern
.tasks
:
1140 pval
= Cast(t
.bsd_info
, "proc *")
1141 process_name
= "{:s}".format(pval
.p_comm
)
1142 if search_regex
.search(process_name
):
1146 @lldb_command('showtaskstacks', 'F:')
1147 def ShowTaskStacksCmdHelper(cmd_args
=None, cmd_options
={}):
1148 """ Routine to print out the stack for each thread in a task
1149 Usage: showtaskstacks <0xaddress of task>
1150 or: showtaskstacks -F launchd
1153 if "-F" in cmd_options
:
1154 find_task_str
= cmd_options
["-F"]
1155 task_list
= FindTasksByName(find_task_str
)
1156 for tval
in task_list
:
1157 ShowTaskStacks(tval
)
1161 raise ArgumentError("No arguments passed")
1163 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1165 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
1167 ShowTaskStacks(tval
)
1170 # EndMacro: showtaskstacks
1172 def CheckTaskProcRefs(task
, proc
):
1173 for thread
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1174 if int(thread
.uthread
) == 0:
1176 uthread
= Cast(thread
.uthread
, 'uthread *')
1177 refcount
= int(uthread
.uu_proc_refcount
)
1178 uu_ref_index
= int(uthread
.uu_pindex
)
1181 for ref
in range(0, uu_ref_index
):
1182 if unsigned(uthread
.uu_proc_ps
[ref
]) == unsigned(proc
):
1183 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1184 pval
= Cast(task
.bsd_info
, 'proc *')
1185 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1186 print "\t" + GetThreadSummary
.header
1187 print "\t" + GetThreadSummary(thread
) + "\n"
1189 for frame
in range (0, 10):
1190 trace_addr
= unsigned(uthread
.uu_proc_pcs
[ref
][frame
])
1191 symbol_arr
= kern
.SymbolicateFromAddress(unsigned(trace_addr
))
1193 symbol_str
= str(symbol_arr
[0].addr
)
1196 print '{0: <#x} {1: <s}'.format(trace_addr
, symbol_str
)
1199 @lldb_command('showprocrefs')
1200 def ShowProcRefs(cmd_args
= None):
1201 """ Display information on threads/BTs that could be holding a reference on the specified proc
1202 NOTE: We can't say affirmatively if any of these references are still held since
1203 there's no way to pair references with drop-refs in the current infrastructure.
1204 Usage: showprocrefs <proc>
1206 if cmd_args
== None or len(cmd_args
) < 1:
1207 raise ArgumentError("No arguments passed")
1209 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
1211 for t
in kern
.tasks
:
1212 CheckTaskProcRefs(t
, proc
)
1213 for t
in kern
.terminated_tasks
:
1214 CheckTaskProcRefs(t
, proc
)
1218 @lldb_command('showallthreads')
1219 def ShowAllThreads(cmd_args
= None):
1220 """ Display info about all threads in the system
1222 for t
in kern
.tasks
:
1223 ShowTaskThreads([str(int(t
))])
1226 for t
in kern
.terminated_tasks
:
1227 print "Terminated: \n"
1228 ShowTaskThreads([str(int(t
))])
1233 @lldb_command('showtaskthreads', "F:")
1234 def ShowTaskThreads(cmd_args
= None, cmd_options
={}):
1235 """ Display thread information for a given task
1236 Usage: showtaskthreads <0xaddress of task>
1237 or: showtaskthreads -F <name>
1240 if "-F" in cmd_options
:
1241 task_list
= FindTasksByName(cmd_options
["-F"])
1243 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1246 raise ArgumentError("No arguments passed")
1248 for task
in task_list
:
1249 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1250 pval
= Cast(task
.bsd_info
, 'proc *')
1251 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1252 print "\t" + GetThreadSummary
.header
1253 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1254 print "\t" + GetThreadSummary(thval
)
1257 @lldb_command('showact')
1258 def ShowAct(cmd_args
=None):
1259 """ Routine to print out the state of a specific thread.
1260 usage: showact <activation>
1262 if cmd_args
== None or len(cmd_args
) < 1:
1263 print "No arguments passed"
1264 print ShowAct
.__doc
__
1266 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1267 print GetThreadSummary
.header
1268 print GetThreadSummary(threadval
)
1270 @lldb_command('showactstack')
1271 def ShowActStack(cmd_args
=None):
1272 """ Routine to print out the stack of a specific thread.
1273 usage: showactstack <activation>
1275 if cmd_args
== None or len(cmd_args
) < 1:
1276 print "No arguments passed"
1277 print ShowAct
.__doc
__.strip()
1279 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1280 print GetThreadSummary
.header
1281 print GetThreadSummary(threadval
)
1282 print GetThreadBackTrace(threadval
, prefix
="\t")
1285 @lldb_command('switchtoact')
1286 def SwitchToAct(cmd_args
=None):
1287 """ Switch to different context specified by activation
1288 This command allows gdb to examine the execution context and call
1289 stack for the specified activation. For example, to view the backtrace
1290 for an activation issue "switchtoact <address>", followed by "bt".
1291 Before resuming execution, issue a "resetctx" command, to
1292 return to the original execution context.
1294 if cmd_args
== None or len(cmd_args
) < 1:
1295 print "No arguments passed"
1296 print SwitchToAct
.__doc
__.strip()
1298 thval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1299 lldbthread
= GetLLDBThreadForKernelThread(thval
)
1300 print GetThreadSummary
.header
1301 print GetThreadSummary(thval
)
1302 LazyTarget
.GetProcess().selected_thread
= lldbthread
1303 if not LazyTarget
.GetProcess().SetSelectedThread(lldbthread
):
1304 print "Failed to switch thread."
1307 @lldb_command('switchtoregs')
1308 def SwitchToRegs(cmd_args
=None):
1309 """ Routine to switch to a register state.
1310 Usage: (lldb) switchtoregs <struct arm_saved_state[64] *>
1311 This command creates a fake thread in lldb with the saved register state.
1312 Note: This command ONLY works for ARM based kernel setup.
1315 if cmd_args
== None or len(cmd_args
) < 1:
1316 raise ArgumentError("No arguments passed")
1318 lldb_process
= LazyTarget
.GetProcess()
1320 saved_state
= ArgumentStringToInt(cmd_args
[0])
1321 # any change to this logic requires change in operating_system.py as well
1322 fake_thread_id
= 0xdead0000 |
(saved_state
& ~
0xffff0000)
1323 fake_thread_id
= fake_thread_id
& 0xdeadffff
1324 lldb_process
.CreateOSPluginThread(0xdeadbeef, saved_state
)
1325 lldbthread
= lldb_process
.GetThreadByID(int(fake_thread_id
))
1327 if not lldbthread
.IsValid():
1328 print "Failed to create thread"
1331 lldb_process
.selected_thread
= lldbthread
1332 if not lldb_process
.SetSelectedThread(lldbthread
):
1333 print "Failed to switch thread"
1334 print "Switched to Fake thread created from register state at 0x%x" % saved_state
1338 # Macro: showallstacks
1339 @lldb_command('showallstacks')
1340 def ShowAllStacks(cmd_args
=None):
1341 """Routine to print out the stack for each thread in the system.
1343 for t
in kern
.tasks
:
1349 # EndMacro: showallstacks
1351 # Macro: showcurrentstacks
1352 @lldb_command('showcurrentstacks')
1353 def ShowCurrentStacks(cmd_args
=None):
1354 """ Routine to print out the thread running on each cpu (incl. its stack)
1356 processor_list
= kern
.GetGlobalVariable('processor_list')
1357 current_processor
= processor_list
1358 while unsigned(current_processor
) > 0:
1359 print "\n" + GetProcessorSummary(current_processor
)
1360 active_thread
= current_processor
.active_thread
1361 if unsigned(active_thread
) != 0 :
1362 task_val
= active_thread
.task
1363 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1364 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1365 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1366 print "\t" + GetThreadSummary
.header
1367 print "\t" + GetThreadSummary(active_thread
)
1368 print "\tBacktrace:"
1369 print GetThreadBackTrace(active_thread
, prefix
="\t")
1370 current_processor
= current_processor
.processor_list
1372 # EndMacro: showcurrentstacks
1374 @lldb_command('showcurrentthreads')
1375 def ShowCurrentThreads(cmd_args
=None):
1376 """ Display info about threads running on each cpu """
1377 processor_list
= kern
.GetGlobalVariable('processor_list')
1378 current_processor
= processor_list
1379 while unsigned(current_processor
) > 0:
1380 print GetProcessorSummary(current_processor
)
1381 active_thread
= current_processor
.active_thread
1382 if unsigned(active_thread
) != 0 :
1383 task_val
= active_thread
.task
1384 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1385 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1386 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1387 print "\t" + GetThreadSummary
.header
1388 print "\t" + GetThreadSummary(active_thread
)
1389 current_processor
= current_processor
.processor_list
1392 def GetFullBackTrace(frame_addr
, verbosity
= vHUMAN
, prefix
= ""):
1393 """ Get backtrace across interrupt context.
1394 params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7)
1395 prefix - str - prefix for each line of output.
1400 frame_ptr
= frame_addr
1401 previous_frame_ptr
= 0
1402 # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
1403 mh_execute_addr
= int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
1404 while frame_ptr
and frame_ptr
!= previous_frame_ptr
and bt_count
< 128:
1405 if (kern
.arch
not in ('arm', 'arm64') and frame_ptr
< mh_execute_addr
) or (kern
.arch
in ('arm', 'arm64') and frame_ptr
> mh_execute_addr
):
1407 pc_val
= kern
.GetValueFromAddress(frame_ptr
+ kern
.ptrsize
,'uintptr_t *')
1408 pc_val
= unsigned(dereference(pc_val
))
1409 out_string
+= prefix
+ GetSourceInformationForAddress(pc_val
) + "\n"
1411 previous_frame_ptr
= frame_ptr
1412 frame_val
= kern
.GetValueFromAddress((frame_ptr
), 'uintptr_t *')
1413 if unsigned(frame_val
) == 0:
1415 frame_ptr
= unsigned(dereference(frame_val
))
1419 @lldb_command('fullbt')
1420 def FullBackTrace(cmd_args
=[]):
1421 """ Show full backtrace across the interrupt boundary.
1422 Syntax: fullbt <frame ptr>
1423 Example: fullbt `$rbp`
1425 if len(cmd_args
) < 1:
1426 print FullBackTrace
.__doc
__
1428 print GetFullBackTrace(ArgumentStringToInt(cmd_args
[0]), prefix
="\t")
1430 @lldb_command('fullbtall')
1431 def FullBackTraceAll(cmd_args
=[]):
1432 """ Show full backtrace across the interrupt boundary for threads running on all processors.
1436 for processor
in IterateLinkedList(kern
.globals.processor_list
, 'processor_list') :
1437 print "\n" + GetProcessorSummary(processor
)
1438 active_thread
= processor
.active_thread
1439 if unsigned(active_thread
) != 0 :
1440 task_val
= active_thread
.task
1441 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1442 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1443 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1444 print "\t" + GetThreadSummary
.header
1445 print "\t" + GetThreadSummary(active_thread
)
1446 print "\tBacktrace:"
1448 ThreadVal
= GetLLDBThreadForKernelThread(active_thread
)
1450 FramePtr
= ThreadVal
.frames
[0].GetFP()
1452 print GetFullBackTrace(unsigned(FramePtr
), prefix
="\t")
1455 @lldb_command('symbolicate')
1456 def SymbolicateAddress(cmd_args
=[]):
1457 """ Symbolicate an address for symbol information from loaded symbols
1458 Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr"
1460 if len(cmd_args
) < 1:
1461 print "Invalid address.\nSyntax: symbolicate <address>"
1463 print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args
[0]))
1466 @lldb_command('showinitchild')
1467 def ShowInitChild(cmd_args
=None):
1468 """ Routine to print out all processes in the system
1469 which are children of init process
1471 headp
= kern
.globals.initproc
.p_children
1472 for pp
in IterateListEntry(headp
, 'struct proc *', 'p_sibling'):
1473 print GetProcInfo(pp
)
1476 @lldb_command('showproctree')
1477 def ShowProcTree(cmd_args
=None):
1478 """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes.
1479 If no argument is given, showproctree will print all the processes in the system.
1480 If pid is specified, showproctree prints all the descendants of the indicated process
1484 search_pid
= ArgumentStringToInt(cmd_args
[0])
1487 print "pid specified must be a positive number"
1488 print ShowProcTree
.__doc
__
1491 hdr_format
= "{0: <6s} {1: <14s} {2: <9s}\n"
1492 out_string
= hdr_format
.format("PID", "PROCESS", "POINTER")
1493 out_string
+= hdr_format
.format('='*3, '='*7, '='*7)
1494 proc
= GetProcForPid(search_pid
)
1495 out_string
+= "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc
.p_ppid
, proc
.p_pptr
.p_comm
, unsigned(proc
.p_pptr
))
1496 out_string
+= "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc
.p_pid
, proc
.p_comm
, unsigned(proc
))
1498 ShowProcTreeRecurse(proc
, "| ")
1502 def ShowProcTreeRecurse(proc
, prefix
=""):
1503 """ Prints descendants of a given proc in hierarchial tree form
1505 proc : core.value representing a struct proc * in the kernel
1507 str : String containing info about a given proc and its descendants in tree form
1509 if proc
.p_childrencnt
> 0:
1510 head_ptr
= proc
.p_children
.lh_first
1512 for p
in IterateListEntry(proc
.p_children
, 'struct proc *', 'p_sibling'):
1513 print prefix
+ "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p
.p_pid
, p
.p_comm
, unsigned(p
))
1514 ShowProcTreeRecurse(p
, prefix
+ "| ")
1516 @lldb_command('showthreadfortid')
1517 def ShowThreadForTid(cmd_args
=None):
1518 """ The thread structure contains a unique thread_id value for each thread.
1519 This command is used to retrieve the address of the thread structure(thread_t)
1520 corresponding to a given thread_id.
1523 print "Please provide thread_t whose tid you'd like to look up"
1524 print ShowThreadForTid
.__doc
__
1526 search_tid
= ArgumentStringToInt(cmd_args
[0])
1527 for taskp
in kern
.tasks
:
1528 for actp
in IterateQueue(taskp
.threads
, 'struct thread *', 'task_threads'):
1529 if search_tid
== int(actp
.thread_id
):
1530 print "Found {0: #019x}".format(actp
)
1531 print GetThreadSummary
.header
1532 print GetThreadSummary(actp
)
1534 print "Not a valid thread_id"
1536 def GetProcessorSummary(processor
):
1537 """ Internal function to print summary of processor
1538 params: processor - value representing struct processor *
1539 return: str - representing the details of given processor
1542 processor_state_str
= "INVALID"
1543 processor_state
= int(processor
.state
)
1545 processor_states
= {
1549 # 3 (formerly INACTIVE)
1555 if processor_state
in processor_states
:
1556 processor_state_str
= "{0: <11s} ".format(processor_states
[processor_state
])
1558 processor_recommended_str
= ""
1559 if int(processor
.is_recommended
) == 0:
1560 processor_recommended_str
= " (not recommended)"
1563 preemption_disable
= 0
1564 preemption_disable_str
= ""
1566 if kern
.arch
== 'x86_64':
1567 cpu_data
= kern
.globals.cpu_data_ptr
[processor
.cpu_id
]
1568 if (cpu_data
!= 0) :
1569 ast
= cpu_data
.cpu_pending_ast
1570 preemption_disable
= cpu_data
.cpu_preemption_level
1571 # On arm64, it's kern.globals.CpuDataEntries[processor.cpu_id].cpu_data_vaddr
1572 # but LLDB can't find CpuDataEntries...
1574 ast_str
= GetASTSummary(ast
)
1576 if (preemption_disable
!= 0) :
1577 preemption_disable_str
= "Preemption Disabled"
1579 out_str
= "Processor {: <#018x} cpu_id {:>#4x} AST: {:<6s} State {:<s}{:<s} {:<s}\n".format(
1580 processor
, int(processor
.cpu_id
), ast_str
, processor_state_str
, processor_recommended_str
,
1581 preemption_disable_str
)
1584 def GetLedgerEntrySummary(ledger_template
, ledger
, i
):
1585 """ Internal function to get internals of a ledger entry (*not* a ledger itself)
1586 params: ledger_template - value representing struct ledger_template_t for the task or thread
1587 ledger - value representing struct ledger_entry *
1588 return: str - formatted output information of ledger entries
1590 ledger_limit_infinity
= (uint64_t(0x1).value
<< 63) - 1
1591 lf_refill_scheduled
= 0x0400
1592 lf_tracking_max
= 0x4000
1595 now
= unsigned(kern
.globals.sched_tick
) / 20
1598 out_str
+= "{: >32s} {:<2d}:".format(ledger_template
.lt_entries
[i
].et_key
, i
)
1599 out_str
+= "{: >15d} ".format(unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
))
1600 if (ledger
.le_flags
& lf_tracking_max
):
1601 out_str
+= "{:9d} {:5d} ".format(ledger
._le
.le_peaks
[0].le_max
, now
- unsigned(ledger
._le
.le_peaks
[0].le_time
))
1602 out_str
+= "{:9d} {:4d} ".format(ledger
._le
.le_peaks
[1].le_max
, now
- unsigned(ledger
._le
.le_peaks
[1].le_time
))
1604 out_str
+= " - - - - "
1606 out_str
+= "{:12d} {:12d} ".format(unsigned(ledger
.le_credit
), unsigned(ledger
.le_debit
))
1607 if (unsigned(ledger
.le_limit
) != ledger_limit_infinity
):
1608 out_str
+= "{:12d} ".format(unsigned(ledger
.le_limit
))
1612 if (ledger
.le_flags
& lf_refill_scheduled
):
1613 out_str
+= "{:15d} ".format(ledger
._le
.le_refill
.le_refill_period
)
1617 if (ledger
.le_flags
& lf_refill_scheduled
):
1618 out_str
+= "{:9d} ".format((unsigned(ledger
.le_limit
) * 100) / ledger
._le
.le_refill
.le_refill_period
)
1622 if (unsigned(ledger
.le_warn_level
) != ledger_limit_infinity
):
1623 out_str
+= "{:9d} ".format((unsigned(ledger
.le_warn_level
) * 100) / unsigned(ledger
.le_limit
))
1627 if ((unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
)) > unsigned(ledger
.le_limit
)):
1632 out_str
+= "{:#8x}\n".format(ledger
.le_flags
)
1635 def GetThreadLedgerSummary(thread_val
):
1636 """ Internal function to get a summary of ledger entries for the given thread
1637 params: thread - value representing struct thread *
1638 return: str - formatted output information for ledger entries of the input thread
1640 out_str
= " [{:#08x}]\n".format(thread_val
)
1641 ledgerp
= thread_val
.t_threadledger
1644 while i
!= ledgerp
.l_template
.lt_cnt
:
1645 out_str
+= GetLedgerEntrySummary(kern
.globals.thread_ledger_template
,
1646 ledgerp
.l_entries
[i
], i
)
1650 @header("{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >9s} {5: >6s} {6: >8s} {7: <10s} {8: <9s} \
1651 {9: <12s} {10: <7s} {11: <15s} {12: <8s} {13: <9s} {14: <6s} {15: >6s}".format(
1652 "task [thread]", "entry", "#", "balance", "peakA", "(age)", "peakB", "(age)", "credit",
1653 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags"))
1654 def GetTaskLedgers(task_val
):
1655 """ Internal function to get summary of ledger entries from the task and its threads
1656 params: task_val - value representing struct task *
1657 return: str - formatted output information for ledger entries of the input task
1660 task_ledgerp
= task_val
.ledger
1662 out_str
+= "{: #08x} ".format(task_val
)
1663 pval
= Cast(task_val
.bsd_info
, 'proc *')
1665 out_str
+= "{: <5s}:\n".format(pval
.p_comm
)
1667 out_str
+= "Invalid process:\n"
1668 while i
!= task_ledgerp
.l_template
.lt_cnt
:
1669 out_str
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, task_ledgerp
.l_entries
[i
], i
)
1673 for thval
in IterateQueue(task_val
.threads
, 'thread *', 'task_threads'):
1674 out_str
+= GetThreadLedgerSummary(thval
)
1678 # Macro: showtaskledgers
1680 @lldb_command('showtaskledgers', 'F:')
1681 def ShowTaskLedgers(cmd_args
=None, cmd_options
={}):
1682 """ Routine to print a summary of ledger entries for the task and all of its threads
1683 Usage: showtaskledgers <address of task>
1684 or : showtaskledgers -F <name of task>
1686 if "-F" in cmd_options
:
1687 task_list
= FindTasksByName(cmd_options
["-F"])
1688 for tval
in task_list
:
1689 print GetTaskLedgers
.header
1690 print GetTaskLedgers(tval
)
1694 raise ArgumentError("No arguments passed.")
1695 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1697 raise ArgumentError("unknown arguments: %r" %cmd
_args
)
1698 print GetTaskLedgers
.header
1699 print GetTaskLedgers(tval
)
1701 # EndMacro: showtaskledgers
1703 # Macro: showalltaskledgers
1705 @lldb_command('showalltaskledgers')
1706 def ShowAllTaskLedgers(cmd_args
=None):
1707 """ Routine to print a summary of ledger entries for all tasks and respective threads
1708 Usage: showalltaskledgers
1710 for t
in kern
.tasks
:
1711 task_val
= unsigned(t
)
1712 ShowTaskLedgers([task_val
])
1714 # EndMacro: showalltaskledgers
1716 # Macro: showprocuuidpolicytable
1718 @lldb_type_summary(['proc_uuid_policy_entry'])
1719 @header("{0: <36s} {1: <10s}".format("uuid", "flags"))
1720 def GetProcUUIDPolicyEntrySummary(entry
):
1721 """ Summarizes the important fields in proc_uuid_policy_entry structure.
1722 params: entry: value - value object representing an entry
1723 returns: str - summary of the entry
1727 data
.append(int(entry
.uuid
[i
]))
1728 flags
= unsigned(entry
.flags
)
1729 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
)
1732 @lldb_command('showprocuuidpolicytable')
1733 def ShowProcUUIDPolicyTable(cmd_args
=None):
1734 """ Routine to print the proc UUID policy table
1735 Usage: showprocuuidpolicytable
1737 hashslots
= unsigned(kern
.globals.proc_uuid_policy_hash_mask
)
1738 print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary
.header
1739 for i
in range(0, hashslots
+1):
1740 headp
= addressof(kern
.globals.proc_uuid_policy_hashtbl
[i
])
1742 for entry
in IterateListEntry(headp
, 'struct proc_uuid_policy_entry *', 'entries'):
1743 print "{0: >2d}.{1: <5d} ".format(i
, entrynum
) + GetProcUUIDPolicyEntrySummary(entry
)
1747 # EndMacro: showprocuuidpolicytable
1749 @lldb_command('showalltaskpolicy')
1750 def ShowAllTaskPolicy(cmd_args
=None):
1752 Routine to print a summary listing of all the tasks
1753 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1754 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1755 io_policy -> RAGE - rapid aging of vnodes requested
1756 NORM - normal I/O explicitly requested (this is the default)
1757 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1758 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1761 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1762 for t
in kern
.tasks
:
1763 pval
= Cast(t
.bsd_info
, 'proc *')
1764 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1765 requested_strings
= [
1766 ["int_darwinbg", "DBG-int"],
1767 ["ext_darwinbg", "DBG-ext"],
1768 ["int_iotier", "iotier-int"],
1769 ["ext_iotier", "iotier-ext"],
1770 ["int_iopassive", "passive-int"],
1771 ["ext_iopassive", "passive-ext"],
1772 ["bg_iotier", "bg-iotier"],
1773 ["terminated", "terminated"],
1774 ["th_pidbind_bg", "bg-pidbind"],
1775 ["t_apptype", "apptype"],
1776 ["t_boosted", "boosted"],
1778 ["t_tal_enabled", "tal-enabled"],
1779 ["t_base_latency_qos", "latency-base"],
1780 ["t_over_latency_qos", "latency-override"],
1781 ["t_base_through_qos", "throughput-base"],
1782 ["t_over_through_qos", "throughput-override"]
1786 for value
in requested_strings
:
1787 if t
.requested_policy
.__getattr
__(value
[0]) :
1788 requested
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1792 suppression_strings
= [
1793 ["t_sup_active", "active"],
1794 ["t_sup_lowpri_cpu", "lowpri-cpu"],
1795 ["t_sup_timer", "timer-throttling"],
1796 ["t_sup_disk", "disk-throttling"],
1797 ["t_sup_cpu_limit", "cpu-limits"],
1798 ["t_sup_suspend", "suspend"],
1799 ["t_sup_bg_sockets", "bg-sockets"]
1803 for value
in suppression_strings
:
1804 if t
.requested_policy
.__getattr
__(value
[0]) :
1805 suppression
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1809 effective_strings
= [
1810 ["darwinbg", "background"],
1811 ["lowpri_cpu", "lowpri-cpu"],
1812 ["io_tier", "iotier"],
1813 ["io_passive", "passive"],
1814 ["all_sockets_bg", "bg-allsockets"],
1815 ["new_sockets_bg", "bg-newsockets"],
1816 ["bg_iotier", "bg-iotier"],
1817 ["terminated", "terminated"],
1818 ["t_gpu_deny", "gpu-deny"],
1819 ["t_tal_engaged", "tal-engaged"],
1820 ["t_suspended", "suspended"],
1821 ["t_watchers_bg", "bg-watchers"],
1822 ["t_latency_qos", "latency-qos"],
1823 ["t_through_qos", "throughput-qos"],
1824 ["t_sup_active", "suppression-active"],
1829 for value
in effective_strings
:
1830 if t
.effective_policy
.__getattr
__(value
[0]) :
1831 effective
+=value
[1] + ": " + str(t
.effective_policy
.__getattr
__(value
[0])) + " "
1835 print "requested: " + requested
1836 print "suppression: " + suppression
1837 print "effective: " + effective
1840 @lldb_type_summary(['wait_queue', 'wait_queue_t'])
1841 @header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask"))
1842 def GetWaitQSummary(waitq
):
1843 """ Summarizes the important fields in task structure.
1844 params: task: value - value object representing a task in kernel
1845 returns: str - summary of the task
1848 format_string
= '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
1852 if (waitq
.wq_fifo
== 1) :
1857 if (waitq
.wq_prepost
== 1) :
1860 if (waitq
.wq_type
== 0x3) :
1862 elif (waitq
.wq_type
== 0x2) :
1867 out_string
+= format_string
.format(waitq
, unsigned(waitq
.wq_interlock
.lock_data
), policy
, 0, 0, unsigned(waitq
.wq_eventmask
))
1869 out_string
+= "\n" + GetThreadSummary
.header
1871 for thread
in IterateQueue(waitq
.wq_queue
, "thread_t", "links"):
1872 out_string
+= "\n" + GetThreadSummary(thread
)
1877 @lldb_command('showallsuspendedtasks', '')
1878 def ShowSuspendedTasks(cmd_args
=[], options
={}):
1879 """ Show a list of suspended tasks with their process name summary.
1881 print GetTaskSummary
.header
+ ' ' + GetProcSummary
.header
1882 for t
in kern
.tasks
:
1883 if t
.suspend_count
> 0:
1884 print GetTaskSummary(t
) + ' ' + GetProcSummary(Cast(t
.bsd_info
, 'proc *'))
1888 @lldb_command('showallpte')
1889 def ShowAllPte(cmd_args
=None):
1890 """ Prints out the physical address of the pte for all tasks
1892 head_taskp
= addressof(kern
.globals.tasks
)
1893 taskp
= Cast(head_taskp
.next
, 'task *')
1894 while taskp
!= head_taskp
:
1895 procp
= Cast(taskp
.bsd_info
, 'proc *')
1896 out_str
= "task = {:#x} pte = {:#x}\t".format(taskp
, taskp
.map.pmap
.ttep
)
1898 out_str
+= "{:s}\n".format(procp
.p_comm
)
1902 taskp
= Cast(taskp
.tasks
.next
, 'struct task *')
1904 # EndMacro: showallpte
1906 # Macro: showallrefcounts
1907 @lldb_command('showallrefcounts')
1908 @header("{0: <20s} {1: ^10s}".format("task", "ref_count"))
1909 def ShowAllRefCounts(cmd_args
=None):
1910 """ Prints the ref_count of all tasks
1913 head_taskp
= addressof(kern
.globals.tasks
)
1914 taskp
= Cast(head_taskp
.next
, 'task *')
1915 print ShowAllRefCounts
.header
1916 while taskp
!= head_taskp
:
1917 out_str
+= "{: <#20x}".format(taskp
)
1918 out_str
+= "{: ^10d}\n".format(taskp
.ref_count
)
1919 taskp
= Cast(taskp
.tasks
.next
, 'task *')
1921 # EndMacro: showallrefcounts
1923 # Macro: showallrunnablethreads
1924 @lldb_command('showallrunnablethreads')
1925 def ShowAllRunnableThreads(cmd_args
=None):
1926 """ Prints the sched usage information for all threads of each task
1929 for taskp
in kern
.tasks
:
1930 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1931 if int(actp
.state
& 0x4):
1932 ShowActStack([unsigned(actp
)])
1934 # EndMacro: showallrunnablethreads
1936 # Macro: showallschedusage
1937 @lldb_command('showallschedusage')
1938 @header("{0:<20s} {1:^10s} {2:^10s} {3:^15s}".format("Thread", "Priority", "State", "sched_usage"))
1939 def ShowAllSchedUsage(cmd_args
=None):
1940 """ Prints the sched usage information for all threads of each task
1943 for taskp
in kern
.tasks
:
1944 ShowTask([unsigned(taskp
)])
1945 print ShowAllSchedUsage
.header
1946 for actp
in IterateQueue(taskp
.threads
, 'thread *', 'task_threads'):
1947 out_str
= "{: <#20x}".format(actp
)
1948 out_str
+= "{: ^10s}".format(str(int(actp
.sched_pri
)))
1949 state
= int(actp
.state
)
1950 thread_state_chars
= {0:'', 1:'W', 2:'S', 4:'R', 8:'U', 16:'H', 32:'A', 64:'P', 128:'I'}
1952 state_str
+= thread_state_chars
[int(state
& 0x1)]
1953 state_str
+= thread_state_chars
[int(state
& 0x2)]
1954 state_str
+= thread_state_chars
[int(state
& 0x4)]
1955 state_str
+= thread_state_chars
[int(state
& 0x8)]
1956 state_str
+= thread_state_chars
[int(state
& 0x10)]
1957 state_str
+= thread_state_chars
[int(state
& 0x20)]
1958 state_str
+= thread_state_chars
[int(state
& 0x40)]
1959 state_str
+= thread_state_chars
[int(state
& 0x80)]
1960 out_str
+= "{: ^10s}".format(state_str
)
1961 out_str
+= "{: >15d}".format(actp
.sched_usage
)
1962 print out_str
+ "\n"
1965 # EndMacro: showallschedusage
1967 #Macro: showprocfilessummary
1968 @lldb_command('showprocfilessummary')
1969 @header("{0: <20s} {1: <20s} {2: >10s}".format("Process", "Name", "Number of Open Files"))
1970 def ShowProcFilesSummary(cmd_args
=None):
1971 """ Display the summary of open file descriptors for all processes in task list
1972 Usage: showprocfilessummary
1974 print ShowProcFilesSummary
.header
1975 for proc
in kern
.procs
:
1976 proc_filedesc
= proc
.p_fd
1977 proc_ofiles
= proc_filedesc
.fd_ofiles
1978 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
1981 if proc_filedesc
.fd_nfiles
!= 0:
1982 while count
<= proc_lastfile
:
1983 if unsigned(proc_ofiles
[count
]) != 0:
1984 proc_file_count
+= 1
1986 print "{0: <#020x} {1: <20s} {2: >10d}".format(proc
, proc
.p_comm
, proc_file_count
)
1988 #EndMacro: showprocfilessummary
1990 @lldb_command('workinguserstacks')
1991 def WorkingUserStacks(cmd_args
=None):
1992 """ Print out the user stack for each thread in a task, followed by the user libraries.
1993 Syntax: (lldb) workinguserstacks <task_t>
1996 print "Insufficient arguments" + ShowTaskUserStacks
.__doc
__
1998 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1999 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
2000 pval
= Cast(task
.bsd_info
, 'proc *')
2001 print GetTaskSummary(task
) + " " + GetProcSummary(pval
) + "\n \n"
2002 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
2003 print "For thread 0x{0:x}".format(thval
)
2005 ShowThreadUserStack([hex(thval
)])
2006 except Exception as exc_err
:
2007 print "Failed to show user stack for thread 0x{0:x}".format(thval
)
2011 print "Enable debugging ('(lldb) xnudebug debug') to see detailed trace."
2012 WorkingUserLibraries([hex(task
)])
2015 @static_var("exec_load_path", 0)
2016 @lldb_command("workingkuserlibraries")
2017 def WorkingUserLibraries(cmd_args
=None):
2018 """ Show binary images known by dyld in target task
2019 For a given user task, inspect the dyld shared library state and print information about all Mach-O images.
2020 Syntax: (lldb)workinguserlibraries <task_t>
2023 print "Insufficient arguments"
2024 print ShowTaskUserLibraries
.__doc
__
2027 print "{0: <18s} {1: <12s} {2: <36s} {3: <50s}".format('address','type','uuid','path')
2028 out_format
= "0x{0:0>16x} {1: <12s} {2: <36s} {3: <50s}"
2029 task
= kern
.GetValueFromAddress(cmd_args
[0], 'task_t')
2030 is_task_64
= int(task
.t_flags
) & 0x1
2031 dyld_all_image_infos_address
= unsigned(task
.all_image_info_addr
)
2033 if dyld_all_image_infos_address
== 0:
2034 print "No dyld shared library information available for task"
2036 vers_info_data
= GetUserDataAsString(task
, dyld_all_image_infos_address
, 112)
2037 version
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
2038 cur_data_offset
+= 4
2040 print "Unknown dyld all_image_infos version number %d" % version
2041 image_info_count
= _ExtractDataFromString(vers_info_data
, cur_data_offset
, "uint32_t")
2042 WorkingUserLibraries
.exec_load_path
= 0
2044 image_info_size
= 24
2045 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 8, "uint64_t")
2046 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 8*4, "uint64_t")
2047 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 8*13, "uint64_t")
2049 image_info_size
= 12
2050 image_info_array_address
= _ExtractDataFromString(vers_info_data
, 4*2, "uint32_t")
2051 dyld_load_address
= _ExtractDataFromString(vers_info_data
, 4*5, "uint32_t")
2052 dyld_all_image_infos_address_from_struct
= _ExtractDataFromString(vers_info_data
, 4*14, "uint32_t")
2053 # Account for ASLR slide before dyld can fix the structure
2054 dyld_load_address
= dyld_load_address
+ (dyld_all_image_infos_address
- dyld_all_image_infos_address_from_struct
)
2057 while i
< image_info_count
:
2058 image_info_address
= image_info_array_address
+ i
* image_info_size
2059 img_data
= GetUserDataAsString(task
, image_info_address
, image_info_size
)
2061 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint64_t")
2062 image_info_path
= _ExtractDataFromString(img_data
, 8, "uint64_t")
2064 image_info_addr
= _ExtractDataFromString(img_data
, 0, "uint32_t")
2065 image_info_path
= _ExtractDataFromString(img_data
, 4, "uint32_t")
2066 PrintImageInfo(task
, image_info_addr
, image_info_path
)
2069 # load_path might get set when the main executable is processed.
2070 if WorkingUserLibraries
.exec_load_path
!= 0:
2071 PrintImageInfo(task
, dyld_load_address
, WorkingUserLibraries
.exec_load_path
)
2074 # Macro: showstackaftertask
2075 @lldb_command('showstackaftertask','F:')
2076 def Showstackaftertask(cmd_args
=None,cmd_options
={}):
2077 """ Routine to print the thread stacks for all tasks succeeding a given task
2078 Usage: showstackaftertask <0xaddress of task>
2079 or: showstackaftertask -F <taskname>
2081 if "-F" in cmd_options
:
2082 # Find the task pointer corresponding to its task name
2083 find_task_str
= cmd_options
["-F"]
2084 task_list
= FindTasksByName(find_task_str
)
2086 # Iterate through the list of tasks and print all task stacks thereafter
2087 for tval
in task_list
:
2088 ListTaskStacks(tval
)
2092 raise ArgumentError("Insufficient arguments")
2093 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
2095 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
2097 ListTaskStacks(tval
)
2101 # EndMacro: showstackaftertask
2103 def ListTaskStacks(task
):
2104 """ Search for a given task and print the list of all task stacks thereafter.
2106 # Initialize local variable task_flag to mark when a given task is found.
2109 for t
in kern
.tasks
:
2110 if (task_flag
== 1):
2116 # Macro: showstackafterthread
2117 @lldb_command('showstackafterthread')
2118 def Showstackafterthread(cmd_args
= None):
2119 """ Routine to print the stacks of all threads succeeding a given thread.
2120 Usage: Showstackafterthread <0xaddress of thread>
2122 # local variable thread_flag is used to mark when a given thread is found.
2125 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
2127 raise ArgumentError("No arguments passed")
2128 # Iterate through list of all tasks to look up a given thread
2129 for t
in kern
.tasks
:
2131 pval
= Cast(t
.bsd_info
, 'proc *')
2132 print GetTaskSummary
.header
+ " "+ GetProcSummary
.header
2133 print GetTaskSummary(t
) + " "+ GetProcSummary(pval
)
2135 # Look up for a given thread from the the list of threads of a given task
2136 for thval
in IterateQueue(t
.threads
, 'thread *', 'task_threads'):
2137 if (thread_flag
==1):
2139 print " " + GetThreadSummary
.header
2140 print " " + GetThreadSummary(thval
)
2141 print GetThreadBackTrace(thval
, prefix
="\t")+"\n"
2144 if(thval
==threadval
):
2145 pval
= Cast(t
.bsd_info
, 'proc *')
2146 process_name
= "{:s}".format(pval
.p_comm
)
2148 print " *** Continuing to dump the thread stacks from the process *** :" + " " + process_name
2154 def FindVMEntriesForVnode(task
, vn
):
2155 """ returns an array of vme that have the vnode set to defined vnode
2156 each entry in array is of format (vme, start_addr, end_address, protection)
2161 pager_ops_addr
= unsigned(addressof(kern
.globals.vnode_pager_ops
))
2162 debuglog("pager_ops_addr %s" % hex(pager_ops_addr
))
2164 if unsigned(pmap
) == 0:
2166 vme_list_head
= vmmap
.hdr
.links
2167 vme_ptr_type
= gettype('vm_map_entry *')
2168 for vme
in IterateQueue(vme_list_head
, vme_ptr_type
, 'links'):
2170 if unsigned(vme
.is_sub_map
) == 0 and unsigned(vme
.object.vm_object
) != 0:
2171 obj
= vme
.object.vm_object
2180 vn_pager
= Cast(obj
.pager
, 'vnode_pager *')
2181 if unsigned(vn_pager
.pager_ops
) == pager_ops_addr
and unsigned(vn_pager
.vnode_handle
) == unsigned(vn
):
2182 retval
.append((vme
, unsigned(vme
.links
.start
), unsigned(vme
.links
.end
), unsigned(vme
.protection
)))
2186 @lldb_command('showtaskloadinfo')
2187 def ShowTaskLoadInfo(cmd_args
=None, cmd_options
={}):
2188 """ Print the load address and uuid for the process
2189 Usage: (lldb)showtaskloadinfo <task_t>
2192 raise ArgumentError("Insufficient arguments")
2193 t
= kern
.GetValueFromAddress(cmd_args
[0], 'struct task *')
2194 print_format
= "0x{0:x} - 0x{1:x} {2: <50s} (??? - ???) <{3: <36s}> {4: <50s}"
2195 p
= Cast(t
.bsd_info
, 'struct proc *')
2197 uuid_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}".format(a
=uuid
)
2198 filepath
= GetVnodePath(p
.p_textvp
)
2199 libname
= filepath
.split('/')[-1]
2200 #print "uuid: %s file: %s" % (uuid_out_string, filepath)
2201 mappings
= FindVMEntriesForVnode(t
, p
.p_textvp
)
2208 #print "Load address: %s" % hex(m[1])
2209 print print_format
.format(load_addr
, end_addr
, libname
, uuid_out_string
, filepath
)