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 @lldb_type_summary(['thread *', 'thread_t'])
242 @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'))
243 def GetThreadSummary(thread
):
244 """ Summarize the thread structure. It decodes the wait state and waitevents from the data in the struct.
245 params: thread: value - value objecte representing a thread in kernel
246 returns: str - summary of a thread
254 A - Terminated and on termination queue
266 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}"
267 thread_ptr_str
= str("{0: <#020x}".format(thread
))
268 if int(thread
.static_param
) :
269 thread_ptr_str
+="[WQ]"
270 thread_id
= hex(thread
.thread_id
)
272 processor
= hex(thread
.last_processor
)
273 base_priority
= str(int(thread
.base_pri
))
274 sched_priority
= str(int(thread
.sched_pri
))
276 mode
= str(thread
.sched_mode
)
277 if "TIMESHARE" in mode
:
278 sched_mode
+="timeshare"
279 elif "FIXED" in mode
:
281 elif "REALTIME" in mode
:
282 sched_mode
+="realtime"
284 if (unsigned(thread
.bound_processor
) != 0):
288 if (unsigned(thread
.sched_flags
) & 0x0004):
292 if int(thread
.uthread
) != 0:
293 uthread
= Cast(thread
.uthread
, 'uthread *')
294 #check for thread name
295 if int(uthread
.pth_name
) != 0 :
296 th_name_strval
= Cast(uthread
.pth_name
, 'char *')
297 if len(str(th_name_strval
)) > 0 :
298 thread_name
= str(th_name_strval
)
300 #check for io_policy flags
301 if int(uthread
.uu_flag
) & 0x400:
302 io_policy_str
+='RAGE '
304 #now flags for task_policy
308 if int(thread
.effective_policy
.darwinbg
) != 0:
310 if int(thread
.effective_policy
.lowpri_cpu
) != 0:
313 if int(thread
.effective_policy
.io_tier
) != 0:
315 if int(thread
.effective_policy
.io_passive
) != 0:
317 if int(thread
.effective_policy
.terminated
) != 0:
320 state
= int(thread
.state
)
321 thread_state_chars
= {0x0:'', 0x1:'W', 0x2:'S', 0x4:'R', 0x8:'U', 0x10:'H', 0x20:'A', 0x40:'P', 0x80:'I'}
325 state_str
+= thread_state_chars
[int(state
& mask
)]
328 if int(thread
.inspection
):
331 ast
= int(thread
.ast
) |
int(thread
.reason
)
332 ast_str
= GetASTSummary(ast
)
334 #wait queue information
338 if ( state
& 0x1 ) != 0:
339 #we need to look at the waitqueue as well
340 wait_queue_str
= str("{0: <#020x}".format(int(hex(thread
.waitq
), 16)))
341 wait_event_str
= str("{0: <#020x}".format(int(hex(thread
.wait_event
), 16)))
342 wait_event_str_sym
= kern
.Symbolicate(int(hex(thread
.wait_event
), 16))
343 if len(wait_event_str_sym
) > 0:
344 wait_event_str
= wait_event_str
.strip() + " <" + wait_event_str_sym
+ ">"
345 if int(thread
.uthread
) != 0 :
346 uthread
= Cast(thread
.uthread
, 'uthread *')
347 if int(uthread
.uu_wmesg
) != 0:
348 wait_message
= str(Cast(uthread
.uu_wmesg
, 'char *'))
350 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
)
354 def GetTaskRoleString(role
):
356 0 : "TASK_UNSPECIFIED",
357 1 : "TASK_FOREGROUND_APPLICATION",
358 2 : "TASK_BACKGROUND_APPLICATION",
359 3 : "TASK_CONTROL_APPLICATION",
360 4 : "TASK_GRAPHICS_SERVER",
361 5 : "TASK_THROTTLE_APPLICATION",
362 6 : "TASK_NONUI_APPLICATION",
363 7 : "TASK_DEFAULT_APPLICATION",
365 return role_strs
[int(role
)]
367 def GetCoalitionFlagString(coal
):
369 if (coal
.privileged
):
370 flags
.append('privileged')
371 if (coal
.termrequested
):
372 flags
.append('termrequested')
373 if (coal
.terminated
):
374 flags
.append('terminated')
376 flags
.append('reaped')
378 flags
.append('notified')
379 return "|".join(flags
)
381 def GetCoalitionTasks(queue
, coal_type
, thread_details
=False):
383 0x0 : "SFI_CLASS_UNSPECIFIED",
384 0x1 : "SFI_CLASS_DARWIN_BG",
385 0x2 : "SFI_CLASS_APP_NAP",
386 0x3 : "SFI_CLASS_MANAGED_FOCAL",
387 0x4 : "SFI_CLASS_MANAGED_NONFOCAL",
388 0x5 : "SFI_CLASS_DEFAULT_FOCAL",
389 0x6 : "SFI_CLASS_DEFAULT_NONFOCAL",
390 0x7 : "SFI_CLASS_KERNEL",
391 0x8 : "SFI_CLASS_OPTED_OUT",
392 0x9 : "SFI_CLASS_UTILITY",
393 0xA : "SFI_CLASS_LEGACY_FOCAL",
394 0xB : "SFI_CLASS_LEGACY_NONFOCAL",
395 0xC : "SFI_CLASS_USER_INITIATED_FOCAL",
396 0xD : "SFI_CLASS_USER_INITIATED_NONFOCAL",
397 0xE : "SFI_CLASS_USER_INTERACTIVE_FOCAL",
398 0xF : "SFI_CLASS_USER_INTERACTIVE_NONFOCAL",
399 0x10 : "SFI_CLASS_MAINTENANCE",
402 field_name
= 'task_coalition'
403 for task
in IterateLinkageChain(queue
, 'task *', field_name
, coal_type
* sizeof('queue_chain_t')):
404 task_str
= "({0: <d},{1: #x}, {2: <s}, {3: <s})".format(GetProcPIDForTask(task
),task
,GetProcNameForTask(task
),GetTaskRoleString(task
.effective_policy
.t_role
))
406 for thread
in IterateQueue(task
.threads
, "thread_t", "task_threads"):
407 task_str
+= "\n\t\t\t|-> thread:" + hex(thread
) + ", " + sfi_strs
[int(thread
.sfi_class
)]
408 tasks
.append(task_str
)
411 def GetCoalitionTypeString(type):
412 """ Convert a coalition type field into a string
413 Currently supported types (from <mach/coalition.h>):
414 COALITION_TYPE_RESOURCE
415 COALITION_TYPE_JETSAM
417 if type == 0: # COALITION_TYPE_RESOURCE
423 def GetResourceCoalitionSummary(coal
, verbose
=False):
424 """ Summarize a resource coalition
426 out_string
= "Resource Coalition:\n\t Ledger:\n"
427 thread_details
= False
428 if config
['verbosity'] > vSCRIPT
:
429 thread_details
= True
430 ledgerp
= coal
.r
.ledger
431 if verbose
and unsigned(ledgerp
) != 0:
433 while i
!= ledgerp
.l_template
.lt_cnt
:
435 out_string
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, ledgerp
.l_entries
[i
], i
)
437 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
)
438 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
)
439 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
)
440 out_string
+= "\n\t Tasks:\n\t\t"
441 tasks
= GetCoalitionTasks(addressof(coal
.r
.tasks
), 0, thread_details
)
442 out_string
+= "\n\t\t".join(tasks
)
445 def GetJetsamCoalitionSummary(coal
, verbose
=False):
446 out_string
= "Jetsam Coalition:"
447 thread_details
= False
448 if config
['verbosity'] > vSCRIPT
:
449 thread_details
= True
450 if unsigned(coal
.j
.leader
) == 0:
451 out_string
+= "\n\t NO Leader!"
453 out_string
+= "\n\t Leader:\n\t\t"
454 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
))
455 out_string
+= "\n\t Extensions:\n\t\t"
456 tasks
= GetCoalitionTasks(addressof(coal
.j
.extensions
), 1, thread_details
)
457 out_string
+= "\n\t\t".join(tasks
)
458 out_string
+= "\n\t XPC Services:\n\t\t"
459 tasks
= GetCoalitionTasks(addressof(coal
.j
.services
), 1, thread_details
)
460 out_string
+= "\n\t\t".join(tasks
)
461 out_string
+= "\n\t Other Tasks:\n\t\t"
462 tasks
= GetCoalitionTasks(addressof(coal
.j
.other
), 1, thread_details
)
463 out_string
+= "\n\t\t".join(tasks
)
466 @lldb_type_summary(['coalition_t', 'coalition *'])
467 @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"))
468 def GetCoalitionSummary(coal
):
469 if unsigned(coal
) == 0:
470 return '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'.format(0, "", -1, -1, -1, -1, -1, "")
472 format_string
= '{0: <#020x} {1: <15s} {2: <10d} {3: <10d} {4: <10d} {5: <12d} {6: <12d} {7: <s}'
473 type_string
= GetCoalitionTypeString(coal
.type)
474 flag_string
= GetCoalitionFlagString(coal
)
475 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
)
478 def GetCoalitionInfo(coal
, verbose
=False):
479 """ returns a string describing a coalition, including details about the particular coalition type.
481 coal : value object representing a coalition in the kernel
483 str : A string describing the coalition.
485 if unsigned(coal
) == 0:
486 return "<null coalition>"
487 typestr
= GetCoalitionTypeString(coal
.type)
488 flagstr
= GetCoalitionFlagString(coal
)
490 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
)
491 if coal
.type == 0: # COALITION_TYPE_RESOURCE
492 out_string
+= GetResourceCoalitionSummary(coal
, verbose
)
493 elif coal
.type == 1: # COALITION_TYPE_JETSAM
494 out_string
+= GetJetsamCoalitionSummary(coal
, verbose
)
496 out_string
+= "Unknown Type"
500 # Macro: showcoalitioninfo
502 @lldb_command('showcoalitioninfo')
503 def ShowCoalitionInfo(cmd_args
=None, cmd_options
={}):
504 """ Display more detailed information about a coalition
505 Usage: showcoalitioninfo <address of coalition>
508 if config
['verbosity'] > vHUMAN
:
511 print "No arguments passed"
512 print ShowCoalitionInfo
.__doc
__
514 coal
= kern
.GetValueFromAddress(cmd_args
[0], 'coalition *')
516 print "unknown arguments:", str(cmd_args
)
518 print GetCoalitionInfo(coal
, verbose
)
520 # EndMacro: showcoalitioninfo
522 # Macro: showallcoalitions
524 @lldb_command('showallcoalitions')
525 def ShowAllCoalitions(cmd_args
=None):
526 """ Print a summary listing of all the coalitions
529 print GetCoalitionSummary
.header
530 for c
in kern
.coalitions
:
531 print GetCoalitionSummary(c
)
533 # EndMacro: showallcoalitions
535 # Macro: showtaskcoalitions
537 @lldb_command('showtaskcoalitions', 'F:')
538 def ShowTaskCoalitions(cmd_args
=None, cmd_options
={}):
542 if "-F" in cmd_options
:
543 task_list
= FindTasksByName(cmd_options
["-F"])
545 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
548 raise ArgumentError("No arguments passed")
550 if len(task_list
) > 0:
551 print GetCoalitionSummary
.header
552 for task
in task_list
:
553 print GetCoalitionSummary(task
.coalition
[0])
554 print GetCoalitionSummary(task
.coalition
[1])
556 # EndMacro: showtaskcoalitions
558 @lldb_type_summary(['proc', 'proc *'])
559 @header("{0: >6s} {1: ^20s} {2: >14s} {3: ^10s} {4: <20s}".format("pid", "process", "io_policy", "wq_state", "command"))
560 def GetProcSummary(proc
):
561 """ Summarize the process data.
563 proc : value - value representaitng a proc * in kernel
565 str - string summary of the process.
568 format_string
= "{0: >6d} {1: >#020x} {2: >14s} {3: >2d} {4: >2d} {5: >2d} {6: <20s}"
569 pval
= proc
.GetSBValue()
570 #code.interact(local=locals())
571 if str(pval
.GetType()) != str(gettype('proc *')) :
572 return "Unknown type " + str(pval
.GetType()) + " " + str(hex(proc
))
574 out_string
+= "Process " + hex(proc
) + " is not valid."
576 pid
= int(proc
.p_pid
)
577 proc_addr
= int(hex(proc
), 16)
579 if int(proc
.p_lflag
) & 0x400000 :
580 proc_rage_str
= "RAGE"
582 task
= Cast(proc
.task
, 'task *')
586 if int(task
.effective_policy
.darwinbg
) != 0:
588 if int(task
.effective_policy
.lowpri_cpu
) != 0:
591 if int(task
.effective_policy
.io_tier
) != 0:
593 if int(task
.effective_policy
.io_passive
) != 0:
595 if int(task
.effective_policy
.terminated
) != 0:
598 if int(task
.effective_policy
.t_suspended
) != 0:
600 if int(task
.effective_policy
.t_latency_qos
) != 0:
602 if int(task
.effective_policy
.t_sup_active
) != 0:
607 work_queue
= Cast(proc
.p_wqptr
, 'workqueue *')
608 if proc
.p_wqptr
!= 0 :
609 wq_num_threads
= int(work_queue
.wq_nthreads
)
610 wq_idle_threads
= int(work_queue
.wq_thidlecount
)
611 wq_req_threads
= int(work_queue
.wq_reqcount
)
620 process_name
= str(proc
.p_comm
)
621 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
)
624 @lldb_type_summary(['tty_dev_t', 'tty_dev_t *'])
625 @header("{0: <20s} {1: <10s} {2: <10s} {3: <15s} {4: <15s} {5: <15s} {6: <15s}".format("tty_dev","master", "slave", "open", "free", "name", "revoke"))
626 def GetTTYDevSummary(tty_dev
):
627 """ Summarizes the important fields in tty_dev_t structure.
628 params: tty_dev: value - value object representing a tty_dev_t in kernel
629 returns: str - summary of the tty_dev
632 format_string
= "{0: <#020x} {1: <#010x} {2: <#010x} {3: <15s} {4: <15s} {5: <15s} {6: <15s}"
633 open_fn
= kern
.Symbolicate(int(hex(tty_dev
.open), 16))
634 free_fn
= kern
.Symbolicate(int(hex(tty_dev
.free
), 16))
635 name_fn
= kern
.Symbolicate(int(hex(tty_dev
.name
), 16))
636 revoke_fn
= kern
.Symbolicate(int(hex(tty_dev
.revoke
), 16))
637 out_string
+= format_string
.format(tty_dev
, tty_dev
.master
, tty_dev
.slave
, open_fn
, free_fn
, name_fn
, revoke_fn
)
640 @lldb_type_summary(['kqueue *'])
641 @header("{: <20s} {: <20s} {: <6s} {: <20s} {: <10s}".format('kqueue', 'process', '#events', 'wqs', 'state'))
642 def GetKQueueSummary(kq
):
643 """ summarizes kqueue information
644 returns: str - summary of kqueue
647 format_string
= "{o: <#020x} {o.kq_p: <#020x} {o.kq_count: <6d} {o.kq_wqs: <#020x} {st_str: <10s}"
648 state
= int(kq
.kq_state
)
652 if int(state
& mask
):
653 state_str
+= ' ' + xnudefines
.kq_state_strings
[int(state
& mask
)]
655 out_string
+= format_string
.format(o
=kq
, st_str
=state_str
)
656 out_string
+= "\n" + GetKnoteSummary
.header
657 for kn
in IterateTAILQ_HEAD(kq
.kq_head
, 'kn_tqe'):
658 out_string
+= "\n" + GetKnoteSummary(kn
)
661 @lldb_type_summary(['knote *'])
662 @header("{0: <20s} {1: <10s} {2: <10s} {3: <20s} {4: <20s} {5: <30s}".format('knote', 'ident', 'kev_flags', 'kn_kq', 'filtops', ' status'))
663 def GetKnoteSummary(kn
):
664 """ Summarizes a knote and related information
665 returns: str - summary of knote
668 format_string
= "{o: <#020x} {o.kn_kevent.ident: <#010X} {o.kn_kevent.flags: <#010X} {o.kn_kq: <#020X} {ops_str: <20s} {st_str: <30s}"
669 state
= unsigned(kn
.kn_status
)
670 fops_str
= kern
.Symbolicate(unsigned(kn
.kn_fop
))
675 status_desc
+= ' ' + xnudefines
.kn_state_strings
[int(state
& mask
)]
678 out_string
+= format_string
.format(o
=kn
, st_str
=status_desc
, ops_str
=fops_str
)
683 @lldb_command('showtask', 'F:')
684 def ShowTask(cmd_args
=None, cmd_options
={}):
685 """ Routine to print a summary listing of given task
686 Usage: showtask <address of task>
687 or : showtask -F <name of task>
690 if "-F" in cmd_options
:
691 task_list
= FindTasksByName(cmd_options
['-F'])
694 raise ArgumentError("Invalid arguments passed.")
696 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
698 raise ("Unknown arguments: %r" % cmd_args
)
699 task_list
.append(tval
)
701 for tval
in task_list
:
702 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
703 pval
= Cast(tval
.bsd_info
, 'proc *')
704 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
710 @lldb_command('showpid')
711 def ShowPid(cmd_args
=None):
712 """ Routine to print a summary listing of task corresponding to given pid
713 Usage: showpid <pid value>
716 print "No arguments passed"
717 print ShowPid
.__doc
__
719 pidval
= ArgumentStringToInt(cmd_args
[0])
721 pval
= Cast(t
.bsd_info
, 'proc *')
722 if pval
and pval
.p_pid
== pidval
:
723 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
724 print GetTaskSummary(t
) + " " + GetProcSummary(pval
)
731 @lldb_command('showproc')
732 def ShowProc(cmd_args
=None):
733 """ Routine to print a summary listing of task corresponding to given proc
734 Usage: showproc <address of proc>
737 print "No arguments passed"
738 print ShowProc
.__doc
__
740 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
742 print "unknown arguments:", str(cmd_args
)
744 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
745 tval
= Cast(pval
.task
, 'task *')
746 print GetTaskSummary(tval
) +" "+ GetProcSummary(pval
)
750 # Macro: showprocinfo
752 @lldb_command('showprocinfo')
753 def ShowProcInfo(cmd_args
=None):
754 """ Routine to display name, pid, parent & task for the given proc address
755 It also shows the Cred, Flags and state of the process
756 Usage: showprocinfo <address of proc>
759 print "No arguments passed"
760 print ShowProcInfo
.__doc
__
762 pval
= kern
.GetValueFromAddress(cmd_args
[0], 'proc *')
764 print "unknown arguments:", str(cmd_args
)
766 print GetProcInfo(pval
)
768 # EndMacro: showprocinfo
770 #Macro: showprocfiles
772 @lldb_command('showprocfiles')
773 def ShowProcFiles(cmd_args
=None):
774 """ Given a proc_t pointer, display the list of open file descriptors for the referenced process.
775 Usage: showprocfiles <proc_t>
778 print ShowProcFiles
.__doc
__
780 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t')
781 proc_filedesc
= proc
.p_fd
782 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
783 proc_ofiles
= proc_filedesc
.fd_ofiles
784 if unsigned(proc_ofiles
) == 0:
785 print 'No open files for proc {0: <s}'.format(cmd_args
[0])
787 print "{0: <5s} {1: <18s} {2: <10s} {3: <8s} {4: <18s} {5: <64s}".format('FD', 'FILEGLOB', 'FG_FLAGS', 'FG_TYPE', 'FG_DATA','INFO')
788 print "{0:-<5s} {0:-<18s} {0:-<10s} {0:-<8s} {0:-<18s} {0:-<64s}".format("")
802 while count
<= proc_lastfile
:
803 if unsigned(proc_ofiles
[count
]) != 0:
805 proc_fd_flags
= proc_ofiles
[count
].f_flags
806 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
807 out_str
+= "{0: <5d} ".format(count
)
808 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
))
809 out_str
+= "0x{0:0>8x} ".format(unsigned(proc_fd_flags
))
810 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
811 if proc_fd_ftype
in filetype_dict
:
812 out_str
+= "{0: <8s} ".format(filetype_dict
[proc_fd_ftype
])
814 out_str
+= "?: {0: <5d} ".format(proc_fd_ftype
)
815 out_str
+= "{0: <#18x} ".format(unsigned(proc_fd_fglob
.fg_data
))
816 if proc_fd_ftype
== 1:
817 fd_name
= Cast(proc_fd_fglob
.fg_data
, 'struct vnode *').v_name
818 out_str
+= "{0: <64s}".format(fd_name
)
823 #EndMacro: showprocfiles
826 def GetProcKqueues(proc
):
829 proc_filedesc
= proc
.p_fd
830 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
831 proc_ofiles
= proc_filedesc
.fd_ofiles
835 if unsigned(proc_ofiles
) == 0:
840 while count
<= proc_lastfile
:
841 if unsigned(proc_ofiles
[count
]) != 0:
842 proc_fd_flags
= proc_ofiles
[count
].f_flags
843 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
844 proc_fd_ftype
= unsigned(proc_fd_fglob
.fg_ops
.fo_type
)
845 if proc_fd_ftype
== filetype_KQUEUE
:
846 q
= Cast(proc_fd_fglob
.fg_data
, 'struct kqueue *')
854 if unsigned(t
.bsd_info
) == 0:
856 pval
= Cast(t
.bsd_info
, 'proc *')
857 for kq
in GetProcKqueues(pval
):
860 #Macro: showallkqueues
861 @lldb_command('showallkqueues' ,'')
862 def ShowAllKqueues(cmd_args
=[], cmd_options
={}):
863 """ Display a summary of all the kqueues in the system """
864 for kq
in GetAllKqueues():
865 print GetKQueueSummary
.header
866 print GetKQueueSummary(kq
)
868 #EndMacro: showallkqueues
871 @lldb_command('showkqueue' ,'')
872 def ShowKQueue(cmd_args
=[], cmd_options
={}):
873 """ Given a struct kqueue pointer, display the summary of the kqueue
874 Usage: (lldb) showkqueue <struct kqueue *>
877 raise ArgumentError('Invalid arguments')
879 kq
= kern
.GetValueFromAddress(cmd_args
[0], 'struct kqueue *')
880 print GetKQueueSummary
.header
881 print GetKQueueSummary(kq
)
883 #EndMacro: showkqueue
887 @lldb_command('showtty')
888 def ShowTTY(cmd_args
=None):
889 """ Display information about a struct tty
890 Usage: showtty <tty struct>
893 print ShowTTY
.__doc
__
896 tty
= kern
.GetValueFromAddress(cmd_args
[0], 'struct tty *')
897 print "TTY structure at: {0: <s}".format(cmd_args
[0])
898 print "Last input to raw queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_rawq
.c_cs
), tty
.t_rawq
.c_cs
)
899 print "Last input to canonical queue: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_canq
.c_cs
), tty
.t_canq
.c_cs
)
900 print "Last output data: {0: <#18x} \"{1: <s}\"".format(unsigned(tty
.t_outq
.c_cs
), tty
.t_outq
.c_cs
)
902 ['', 'TS_SO_OLOWAT (Wake up when output <= low water)'],
903 ['- (synchronous I/O mode)', 'TS_ASYNC (async I/O mode)'],
904 ['', 'TS_BUSY (Draining output)'],
905 ['- (Carrier is NOT present)', 'TS_CARR_ON (Carrier is present)'],
906 ['', 'TS_FLUSH (Outq has been flushed during DMA)'],
907 ['- (Open has NOT completed)', 'TS_ISOPEN (Open has completed)'],
908 ['', 'TS_TBLOCK (Further input blocked)'],
909 ['', 'TS_TIMEOUT (Wait for output char processing)'],
910 ['', 'TS_TTSTOP (Output paused)'],
911 ['', 'TS_WOPEN (Open in progress)'],
912 ['', 'TS_XCLUDE (Tty requires exclusivity)'],
913 ['', 'TS_BKSL (State for lowercase \\ work)'],
914 ['', 'TS_CNTTB (Counting tab width, ignore FLUSHO)'],
915 ['', 'TS_ERASE (Within a \\.../ for PRTRUB)'],
916 ['', 'TS_LNCH (Next character is literal)'],
917 ['', 'TS_TYPEN (Retyping suspended input (PENDIN))'],
918 ['', 'TS_CAN_BYPASS_L_RINT (Device in "raw" mode)'],
919 ['- (Connection NOT open)', 'TS_CONNECTED (Connection open)'],
920 ['', 'TS_SNOOP (Device is being snooped on)'],
921 ['', 'TS_SO_OCOMPLETE (Wake up when output completes)'],
922 ['', 'TS_ZOMBIE (Connection lost)'],
923 ['', 'TS_CAR_OFLOW (For MDMBUF - handle in driver)'],
924 ['', 'TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)'],
925 ['', 'TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)']
929 tty_state
= unsigned(tty
.t_state
)
932 if tty_state
& mask
!= 0:
933 if len(tty_state_info
[index
][1]) > 0:
934 print '\t' + tty_state_info
[index
][1]
936 if len(tty_state_info
[index
][0]) > 0:
937 print '\t' + tty_state_info
[index
][0]
940 print "Flags: 0x{0:0>8x}".format(unsigned(tty
.t_flags
))
941 print "Foreground Process Group: 0x{0:0>16x}".format(unsigned(tty
.t_pgrp
))
942 print "Enclosing session: 0x{0:0>16x}".format(unsigned(tty
.t_session
))
944 print "\tInput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_iflag
))
945 print "\tOutput Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_oflag
))
946 print "\tControl Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_cflag
))
947 print "\tLocal Flags: 0x{0:0>8x}".format(unsigned(tty
.t_termios
.c_lflag
))
948 print "\tInput Speed: {0: <8d}".format(tty
.t_termios
.c_ispeed
)
949 print "\tOutput Speed: {0: <8d}".format(tty
.t_termios
.c_ospeed
)
950 print "High Watermark: {0: <d} bytes".format(tty
.t_hiwat
)
951 print "Low Watermark : {0: <d} bytes".format(tty
.t_lowat
)
955 #Macro showallttydevs
957 @lldb_command('showallttydevs')
958 def ShowAllTTYDevs(cmd_args
=[], cmd_options
={}):
959 """ Show a list of ttydevs registered in the system.
963 tty_dev_head
= kern
.globals.tty_dev_head
964 tty_dev
= tty_dev_head
965 print GetTTYDevSummary
.header
966 while unsigned(tty_dev
) != 0:
967 print GetTTYDevSummary(tty_dev
)
968 tty_dev
= tty_dev
.next
971 #EndMacro: showallttydevs
973 #Macro: dumpthread_terminate_queue
975 @lldb_command('dumpthread_terminate_queue')
976 def DumpThreadTerminateQueue(cmd_args
=None):
977 """ Displays the contents of the specified call_entry queue.
978 Usage: dumpthread_terminate_queue
982 print GetThreadSummary
.header
983 for th
in IterateQueue(addressof(kern
.globals.thread_terminate_queue
), 'struct thread *', 'q_link'):
984 print GetThreadSummary(th
)
986 print "{0: <d} entries!".format(count
)
988 #EndMacro: dumpthread_terminate_queue
990 #Macro: dumpcrashed_thread_queue
992 @lldb_command('dumpcrashed_thread_queue')
993 def DumpCrashedThreadsQueue(cmd_args
=None):
994 """ Displays the contents of the specified call_entry queue.
995 Usage: dumpcrashed_thread_queue
999 print GetThreadSummary
.header
1000 for th
in IterateQueue(addressof(kern
.globals.crashed_threads_queue
), 'struct thread *', 'q_link'):
1001 print GetThreadSummary(th
)
1003 print "{0: <d} entries!".format(count
)
1005 #EndMacro: dumpcrashed_thread_queue
1007 #Macro: dumpcallqueue
1009 @lldb_command('dumpcallqueue')
1010 def DumpCallQueue(cmd_args
=None):
1011 """ Displays the contents of the specified call_entry queue.
1012 Usage: dumpcallqueue <queue_head_t *>
1015 raise ArgumentError("Invalid arguments")
1017 print "{0: <18s} {1: <18s} {2: <18s} {3: <64s} {4: <18s}".format('CALL_ENTRY', 'PARAM0', 'PARAM1', 'DEADLINE', 'FUNC')
1018 callhead
= kern
.GetValueFromAddress(cmd_args
[0], 'queue_head_t *')
1020 for callentry
in IterateQueue(callhead
, 'struct call_entry *', 'q_link'):
1021 print "{0: <#18x} {1: <#18x} {2: <#18x} {3: <64d} {4: <#18x}".format(
1022 unsigned(callentry
), unsigned(callentry
.param0
), unsigned(callentry
.param1
),
1023 unsigned(callentry
.deadline
), unsigned(callentry
.func
))
1025 print "{0: <d} entries!".format(count
)
1027 #EndMacro: dumpcallqueue
1029 @lldb_command('showalltasks','C')
1030 def ShowAllTasks(cmd_args
=None, cmd_options
={}):
1031 """ Routine to print a summary listing of all the tasks
1032 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1033 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1034 io_policy -> RAGE - rapid aging of vnodes requested
1035 NORM - normal I/O explicitly requested (this is the default)
1036 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1037 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1038 Usage: (lldb) showalltasks -C : describe the corpse structure
1043 if '-C' in cmd_options
:
1045 extra_hdr
+= " " + GetKCDataSummary
.header
1047 print GetTaskSummary
.header
+ extra_hdr
+ " " + GetProcSummary
.header
1048 for t
in kern
.tasks
:
1049 pval
= Cast(t
.bsd_info
, 'proc *')
1050 out_str
= GetTaskSummary(t
, showcorpse
) + " " + GetProcSummary(pval
)
1054 @lldb_command('showterminatedtasks')
1055 def ShowTerminatedTasks(cmd_args
=None):
1056 """ Routine to print a summary listing of all the terminated tasks
1057 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1058 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1059 io_policy -> RAGE - rapid aging of vnodes requested
1060 NORM - normal I/O explicitly requested (this is the default)
1061 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1062 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1063 syntax: (lldb)showallterminatedtasks
1066 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1067 for t
in kern
.terminated_tasks
:
1068 pval
= Cast(t
.bsd_info
, 'proc *')
1069 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1072 # Macro: showtaskstacks
1074 def ShowTaskStacks(task
):
1075 """ Print a task with summary and stack information for each of its threads
1078 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1079 pval
= Cast(task
.bsd_info
, 'proc *')
1080 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1081 for th
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1082 print " " + GetThreadSummary
.header
1083 print " " + GetThreadSummary(th
)
1084 print GetThreadBackTrace(th
, prefix
=" ") + "\n"
1086 def FindTasksByName(searchstr
, ignore_case
=True):
1087 """ Search the list of tasks by name.
1089 searchstr: str - a regex like string to search for task
1090 ignore_case: bool - If False then exact matching will be enforced
1092 [] - array of task object. Empty if not found any
1096 re_options
= re
.IGNORECASE
1097 search_regex
= re
.compile(searchstr
, re_options
)
1099 for t
in kern
.tasks
:
1100 pval
= Cast(t
.bsd_info
, "proc *")
1101 process_name
= "{:s}".format(pval
.p_comm
)
1102 if search_regex
.search(process_name
):
1106 @lldb_command('showtaskstacks', 'F:')
1107 def ShowTaskStacksCmdHelper(cmd_args
=None, cmd_options
={}):
1108 """ Routine to print out the stack for each thread in a task
1109 Usage: showtaskstacks <0xaddress of task>
1110 or: showtaskstacks -F launchd
1113 if "-F" in cmd_options
:
1114 find_task_str
= cmd_options
["-F"]
1115 task_list
= FindTasksByName(find_task_str
)
1116 for tval
in task_list
:
1117 ShowTaskStacks(tval
)
1121 raise ArgumentError("No arguments passed")
1123 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1125 raise ArgumentError("unknown arguments: {:s}".format(str(cmd_args
)))
1127 ShowTaskStacks(tval
)
1130 # EndMacro: showtaskstacks
1132 @lldb_command('showallthreads')
1133 def ShowAllThreads(cmd_args
= None):
1134 """ Display info about all threads in the system
1136 for t
in kern
.tasks
:
1137 ShowTaskThreads([str(int(t
))])
1140 for t
in kern
.terminated_tasks
:
1141 print "Terminated: \n"
1142 ShowTaskThreads([str(int(t
))])
1147 @lldb_command('showtaskthreads', "F:")
1148 def ShowTaskThreads(cmd_args
= None, cmd_options
={}):
1149 """ Display thread information for a given task
1150 Usage: showtaskthreads <0xaddress of task>
1151 or: showtaskthreads -F <name>
1154 if "-F" in cmd_options
:
1155 task_list
= FindTasksByName(cmd_options
["-F"])
1157 t
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1160 raise ArgumentError("No arguments passed")
1162 for task
in task_list
:
1163 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1164 pval
= Cast(task
.bsd_info
, 'proc *')
1165 print GetTaskSummary(task
) + " " + GetProcSummary(pval
)
1166 print "\t" + GetThreadSummary
.header
1167 for thval
in IterateQueue(task
.threads
, 'thread *', 'task_threads'):
1168 print "\t" + GetThreadSummary(thval
)
1171 @lldb_command('showact')
1172 def ShowAct(cmd_args
=None):
1173 """ Routine to print out the state of a specific thread.
1174 usage: showact <activation>
1176 if cmd_args
== None or len(cmd_args
) < 1:
1177 print "No arguments passed"
1178 print ShowAct
.__doc
__
1180 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1181 print GetThreadSummary
.header
1182 print GetThreadSummary(threadval
)
1184 @lldb_command('showactstack')
1185 def ShowActStack(cmd_args
=None):
1186 """ Routine to print out the stack of a specific thread.
1187 usage: showactstack <activation>
1189 if cmd_args
== None or len(cmd_args
) < 1:
1190 print "No arguments passed"
1191 print ShowAct
.__doc
__.strip()
1193 threadval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1194 print GetThreadSummary
.header
1195 print GetThreadSummary(threadval
)
1196 print GetThreadBackTrace(threadval
, prefix
="\t")
1199 @lldb_command('switchtoact')
1200 def SwitchToAct(cmd_args
=None):
1201 """ Switch to different context specified by activation
1202 This command allows gdb to examine the execution context and call
1203 stack for the specified activation. For example, to view the backtrace
1204 for an activation issue "switchtoact <address>", followed by "bt".
1205 Before resuming execution, issue a "resetctx" command, to
1206 return to the original execution context.
1208 if cmd_args
== None or len(cmd_args
) < 1:
1209 print "No arguments passed"
1210 print SwitchToAct
.__doc
__.strip()
1212 thval
= kern
.GetValueFromAddress(cmd_args
[0], 'thread *')
1213 lldbthread
= GetLLDBThreadForKernelThread(thval
)
1214 print GetThreadSummary
.header
1215 print GetThreadSummary(thval
)
1216 LazyTarget
.GetProcess().selected_thread
= lldbthread
1217 if not LazyTarget
.GetProcess().SetSelectedThread(lldbthread
):
1218 print "Failed to switch thread."
1221 @lldb_command('switchtoregs')
1222 def SwitchToRegs(cmd_args
=None):
1223 """ Routine to switch to a register state.
1224 Usage: (lldb) switchtoregs <struct arm_saved_state[64] *>
1225 This command creates a fake thread in lldb with the saved register state.
1226 Note: This command ONLY works for ARM based kernel setup.
1229 if cmd_args
== None or len(cmd_args
) < 1:
1230 raise ArgumentError("No arguments passed")
1232 lldb_process
= LazyTarget
.GetProcess()
1234 saved_state
= ArgumentStringToInt(cmd_args
[0])
1235 # any change to this logic requires change in operating_system.py as well
1236 fake_thread_id
= 0xdead0000 |
(saved_state
& ~
0xffff0000)
1237 fake_thread_id
= fake_thread_id
& 0xdeadffff
1238 lldb_process
.CreateOSPluginThread(0xdeadbeef, saved_state
)
1239 lldbthread
= lldb_process
.GetThreadByID(fake_thread_id
)
1241 if not lldbthread
.IsValid():
1242 print "Failed to create thread"
1245 lldb_process
.selected_thread
= lldbthread
1246 if not lldb_process
.SetSelectedThread(lldbthread
):
1247 print "Failed to switch thread"
1248 print "Switched to Fake thread created from register state at 0x%x" % saved_state
1252 # Macro: showallstacks
1253 @lldb_command('showallstacks')
1254 def ShowAllStacks(cmd_args
=None):
1255 """Routine to print out the stack for each thread in the system.
1257 for t
in kern
.tasks
:
1263 # EndMacro: showallstacks
1265 # Macro: showcurrentstacks
1266 @lldb_command('showcurrentstacks')
1267 def ShowCurrentStacks(cmd_args
=None):
1268 """ Routine to print out the thread running on each cpu (incl. its stack)
1270 processor_list
= kern
.GetGlobalVariable('processor_list')
1271 current_processor
= processor_list
1272 while unsigned(current_processor
) > 0:
1273 print "\n" + GetProcessorSummary(current_processor
)
1274 active_thread
= current_processor
.active_thread
1275 if unsigned(active_thread
) != 0 :
1276 task_val
= active_thread
.task
1277 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1278 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1279 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1280 print "\t" + GetThreadSummary
.header
1281 print "\t" + GetThreadSummary(active_thread
)
1282 print "\tBacktrace:"
1283 print GetThreadBackTrace(active_thread
, prefix
="\t")
1284 current_processor
= current_processor
.processor_list
1286 # EndMacro: showcurrentstacks
1288 @lldb_command('showcurrentthreads')
1289 def ShowCurrentThreads(cmd_args
=None):
1290 """ Display info about threads running on each cpu """
1291 processor_list
= kern
.GetGlobalVariable('processor_list')
1292 current_processor
= processor_list
1293 while unsigned(current_processor
) > 0:
1294 print GetProcessorSummary(current_processor
)
1295 active_thread
= current_processor
.active_thread
1296 if unsigned(active_thread
) != 0 :
1297 task_val
= active_thread
.task
1298 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1299 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1300 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1301 print "\t" + GetThreadSummary
.header
1302 print "\t" + GetThreadSummary(active_thread
)
1303 current_processor
= current_processor
.processor_list
1306 def GetFullBackTrace(frame_addr
, verbosity
= vHUMAN
, prefix
= ""):
1307 """ Get backtrace across interrupt context.
1308 params: frame_addr - int - address in memory which is a frame pointer (ie. rbp, r7)
1309 prefix - str - prefix for each line of output.
1314 frame_ptr
= frame_addr
1315 previous_frame_ptr
= 0
1316 # <rdar://problem/12677290> lldb unable to find symbol for _mh_execute_header
1317 mh_execute_addr
= int(lldb_run_command('p/x (uintptr_t *)&_mh_execute_header').split('=')[-1].strip(), 16)
1318 while frame_ptr
and frame_ptr
!= previous_frame_ptr
and bt_count
< 128:
1319 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
):
1321 pc_val
= kern
.GetValueFromAddress(frame_ptr
+ kern
.ptrsize
,'uintptr_t *')
1322 pc_val
= unsigned(dereference(pc_val
))
1323 out_string
+= prefix
+ GetSourceInformationForAddress(pc_val
) + "\n"
1325 previous_frame_ptr
= frame_ptr
1326 frame_val
= kern
.GetValueFromAddress((frame_ptr
), 'uintptr_t *')
1327 if unsigned(frame_val
) == 0:
1329 frame_ptr
= unsigned(dereference(frame_val
))
1333 @lldb_command('fullbt')
1334 def FullBackTrace(cmd_args
=[]):
1335 """ Show full backtrace across the interrupt boundary.
1336 Syntax: fullbt <frame ptr>
1337 Example: fullbt `$rbp`
1339 if len(cmd_args
) < 1:
1340 print FullBackTrace
.__doc
__
1342 print GetFullBackTrace(ArgumentStringToInt(cmd_args
[0]), prefix
="\t")
1344 @lldb_command('fullbtall')
1345 def FullBackTraceAll(cmd_args
=[]):
1346 """ Show full backtrace across the interrupt boundary for threads running on all processors.
1350 for processor
in IterateLinkedList(kern
.globals.processor_list
, 'processor_list') :
1351 print "\n" + GetProcessorSummary(processor
)
1352 active_thread
= processor
.active_thread
1353 if unsigned(active_thread
) != 0 :
1354 task_val
= active_thread
.task
1355 proc_val
= Cast(task_val
.bsd_info
, 'proc *')
1356 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1357 print GetTaskSummary(task_val
) + " " + GetProcSummary(proc_val
)
1358 print "\t" + GetThreadSummary
.header
1359 print "\t" + GetThreadSummary(active_thread
)
1360 print "\tBacktrace:"
1362 ThreadVal
= GetLLDBThreadForKernelThread(active_thread
)
1364 FramePtr
= ThreadVal
.frames
[0].GetFP()
1366 print GetFullBackTrace(unsigned(FramePtr
), prefix
="\t")
1369 @lldb_command('symbolicate')
1370 def SymbolicateAddress(cmd_args
=[]):
1371 """ Symbolicate an address for symbol information from loaded symbols
1372 Example: "symbolicate 0xaddr" is equivalent to "output/a 0xaddr"
1374 if len(cmd_args
) < 1:
1375 print "Invalid address.\nSyntax: symbolicate <address>"
1377 print GetSourceInformationForAddress(ArgumentStringToInt(cmd_args
[0]))
1380 @lldb_command('showinitchild')
1381 def ShowInitChild(cmd_args
=None):
1382 """ Routine to print out all processes in the system
1383 which are children of init process
1385 headp
= kern
.globals.initproc
.p_children
1386 for pp
in IterateListEntry(headp
, 'struct proc *', 'p_sibling'):
1387 print GetProcInfo(pp
)
1390 @lldb_command('showproctree')
1391 def ShowProcTree(cmd_args
=None):
1392 """ Routine to print the processes in the system in a hierarchical tree form. This routine does not print zombie processes.
1393 If no argument is given, showproctree will print all the processes in the system.
1394 If pid is specified, showproctree prints all the descendants of the indicated process
1398 search_pid
= ArgumentStringToInt(cmd_args
[0])
1401 print "pid specified must be a positive number"
1402 print ShowProcTree
.__doc
__
1405 hdr_format
= "{0: <6s} {1: <14s} {2: <9s}\n"
1406 out_string
= hdr_format
.format("PID", "PROCESS", "POINTER")
1407 out_string
+= hdr_format
.format('='*3, '='*7, '='*7)
1408 proc
= GetProcForPid(search_pid
)
1409 out_string
+= "{0: <6d} {1: <14s} [ {2: #019x} ]\n".format(proc
.p_ppid
, proc
.p_pptr
.p_comm
, unsigned(proc
.p_pptr
))
1410 out_string
+= "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(proc
.p_pid
, proc
.p_comm
, unsigned(proc
))
1412 ShowProcTreeRecurse(proc
, "| ")
1416 def ShowProcTreeRecurse(proc
, prefix
=""):
1417 """ Prints descendants of a given proc in hierarchial tree form
1419 proc : core.value representing a struct proc * in the kernel
1421 str : String containing info about a given proc and its descendants in tree form
1423 if proc
.p_childrencnt
> 0:
1424 head_ptr
= proc
.p_children
.lh_first
1426 for p
in IterateListEntry(proc
.p_children
, 'struct proc *', 'p_sibling'):
1427 print prefix
+ "|--{0: <6d} {1: <16s} [ {2: #019x} ]\n".format(p
.p_pid
, p
.p_comm
, unsigned(p
))
1428 ShowProcTreeRecurse(p
, prefix
+ "| ")
1430 @lldb_command('showthreadfortid')
1431 def ShowThreadForTid(cmd_args
=None):
1432 """ The thread structure contains a unique thread_id value for each thread.
1433 This command is used to retrieve the address of the thread structure(thread_t)
1434 corresponding to a given thread_id.
1437 print "Please provide thread_t whose tid you'd like to look up"
1438 print ShowThreadForTid
.__doc
__
1440 search_tid
= ArgumentStringToInt(cmd_args
[0])
1441 for taskp
in kern
.tasks
:
1442 for actp
in IterateQueue(taskp
.threads
, 'struct thread *', 'task_threads'):
1443 if search_tid
== int(actp
.thread_id
):
1444 print "Found {0: #019x}".format(actp
)
1445 print GetThreadSummary
.header
1446 print GetThreadSummary(actp
)
1448 print "Not a valid thread_id"
1450 # Macro: showallprocessors
1452 def GetProcessorSummary(processor
):
1453 """ Internal function to print summary of processor
1454 params: processor - value representing struct processor *
1455 return: str - representing the details of given processor
1458 processor_state_str
= "INVALID"
1459 processor_state
= int(processor
.state
)
1461 processor_states
= {
1465 # 3 (formerly INACTIVE)
1471 if processor_state
in processor_states
:
1472 processor_state_str
= "{0: <11s} ".format(processor_states
[processor_state
])
1474 processor_recommended_str
= ""
1475 if int(processor
.is_recommended
) == 0:
1476 processor_recommended_str
= " (not recommended)"
1479 preemption_disable
= 0
1480 preemption_disable_str
= ""
1482 if kern
.arch
== 'x86_64':
1483 cpu_data
= kern
.globals.cpu_data_ptr
[processor
.cpu_id
]
1484 if (cpu_data
!= 0) :
1485 ast
= cpu_data
.cpu_pending_ast
1486 preemption_disable
= cpu_data
.cpu_preemption_level
1487 # On arm64, it's kern.globals.CpuDataEntries[processor.cpu_id].cpu_data_vaddr
1488 # but LLDB can't find CpuDataEntries...
1490 ast_str
= GetASTSummary(ast
)
1492 if (preemption_disable
!= 0) :
1493 preemption_disable_str
= "Preemption Disabled"
1495 out_str
= "Processor {: <#018x} cpu_id {:>#4x} AST: {:<6s} State {:<s}{:<s} {:<s}\n".format(
1496 processor
, int(processor
.cpu_id
), ast_str
, processor_state_str
, processor_recommended_str
,
1497 preemption_disable_str
)
1500 def GetGroupSetSummary(runq
, task_map
):
1501 """ Internal function to print summary of group run queue
1502 params: runq - value representing struct run_queue *
1503 return: str - representing the details of given run_queue
1505 out_str
= " runq: count {: <10d} highq: {: <10d} urgency {: <10d}\n".format(runq
.count
, runq
.highq
, runq
.urgency
)
1508 runq_queue_count
= sizeof(runq
.queues
)/sizeof(runq
.queues
[0])
1510 for runq_queue_i
in range(runq_queue_count
) :
1511 runq_queue_head
= addressof(runq
.queues
[runq_queue_i
])
1512 runq_queue_p
= runq_queue_head
.next
1514 if unsigned(runq_queue_p
) != unsigned(runq_queue_head
):
1515 runq_queue_this_count
= 0
1517 for entry
in IterateQueue(runq_queue_head
, "sched_entry_t", "links"):
1518 runq_queue_this_count
+= 1
1520 out_str
+= " Queue [{: <#012x}] Priority {: <3d} count {:d}\n".format(runq_queue_head
, runq_queue_i
, runq_queue_this_count
)
1521 for entry
in IterateQueue(runq_queue_head
, "sched_entry_t", "links"):
1522 group_addr
= unsigned(entry
) - (sizeof(dereference(entry
)) * unsigned(entry
.sched_pri
))
1523 group
= kern
.GetValueFromAddress(unsigned(group_addr
), 'sched_group_t')
1524 task
= task_map
.get(unsigned(group
), 0x0)
1526 print "Cannot find task for group: {: <#012x}".format(group
)
1527 out_str
+= "\tEntry [{: <#012x}] Priority {: <3d} Group {: <#012x} Task {: <#012x}\n".format(unsigned(entry
), entry
.sched_pri
, unsigned(group
), unsigned(task
))
1531 @lldb_command('showrunq')
1532 def ShowRunq(cmd_args
=None):
1533 """ Routine to print information of a runq
1534 Usage: showrunq <runq>
1537 runq
= kern
.GetValueFromAddress(cmd_args
[0], 'struct run_queue *')
1538 out_str
+= GetRunQSummary(runq
)
1541 def GetRunQSummary(runq
):
1542 """ Internal function to print summary of run_queue
1543 params: runq - value representing struct run_queue *
1544 return: str - representing the details of given run_queue
1546 out_str
= " runq: count {: <10d} highq: {: <10d} urgency {: <10d}\n".format(runq
.count
, runq
.highq
, runq
.urgency
)
1549 runq_queue_count
= sizeof(runq
.queues
)/sizeof(runq
.queues
[0])
1551 for runq_queue_i
in range(runq_queue_count
) :
1552 runq_queue_head
= addressof(runq
.queues
[runq_queue_i
])
1553 runq_queue_p
= runq_queue_head
.next
1555 if unsigned(runq_queue_p
) != unsigned(runq_queue_head
):
1556 runq_queue_this_count
= 0
1558 for thread
in IterateQueue(runq_queue_head
, "thread_t", "links"):
1559 runq_queue_this_count
+= 1
1561 out_str
+= " Queue [{: <#012x}] Priority {: <3d} count {:d}\n".format(runq_queue_head
, runq_queue_i
, runq_queue_this_count
)
1562 out_str
+= "\t" + GetThreadSummary
.header
+ "\n"
1563 for thread
in IterateQueue(runq_queue_head
, "thread_t", "links"):
1564 out_str
+= "\t" + GetThreadSummary(thread
) + "\n"
1565 if config
['verbosity'] > vHUMAN
:
1566 out_str
+= "\t" + GetThreadBackTrace(thread
, prefix
="\t\t") + "\n"
1570 def GetGrrrSummary(grrr_runq
):
1571 """ Internal function to print summary of grrr_run_queue
1572 params: grrr_runq - value representing struct grrr_run_queue *
1573 return: str - representing the details of given grrr_run_queue
1575 out_str
= " GRRR Info: Count {: <10d} Weight {: <10d} Current Group {: <#012x}\n".format(grrr_runq
.count
,
1576 grrr_runq
.weight
, grrr_runq
.current_group
)
1578 grrr_group_count
= sizeof(grrr_runq
.groups
)/sizeof(grrr_runq
.groups
[0])
1579 for grrr_group_i
in range(grrr_group_count
) :
1580 grrr_group
= addressof(grrr_runq
.groups
[grrr_group_i
])
1581 if grrr_group
.count
> 0:
1582 out_str
+= " Group {: <3d} [{: <#012x}] ".format(grrr_group
.index
, grrr_group
)
1583 out_str
+= "Count {:d} Weight {:d}\n".format(grrr_group
.count
, grrr_group
.weight
)
1584 grrr_group_client_head
= addressof(grrr_group
.clients
)
1585 out_str
+= GetThreadSummary
.header
1586 for thread
in IterateQueue(grrr_group_client_head
, "thread_t", "links"):
1587 out_str
+= "\t" + GetThreadSummary(thread
) + "\n"
1588 if config
['verbosity'] > vHUMAN
:
1589 out_str
+= "\t" + GetThreadBackTrace(thread
, prefix
="\t\t") + "\n"
1592 def ShowNextThread(processor
):
1594 if (processor
.next_thread
!= 0) :
1595 out_str
+= " " + "Next thread:\n"
1596 out_str
+= "\t" + GetThreadSummary
.header
+ "\n"
1597 out_str
+= "\t" + GetThreadSummary(processor
.next_thread
) + "\n"
1600 def ShowActiveThread(processor
):
1602 if (processor
.active_thread
!= 0) :
1603 out_str
+= "\t" + GetThreadSummary
.header
+ "\n"
1604 out_str
+= "\t" + GetThreadSummary(processor
.active_thread
) + "\n"
1607 @lldb_command('showallprocessors')
1608 def ShowAllProcessors(cmd_args
=None):
1609 """ Routine to print information of all psets and processors
1610 Usage: showallprocessors
1612 pset
= addressof(kern
.globals.pset0
)
1614 show_priority_runq
= 0
1615 show_priority_pset_runq
= 0
1616 show_group_pset_runq
= 0
1617 sched_string
= str(kern
.globals.sched_current_dispatch
.sched_name
)
1619 if sched_string
== "traditional":
1620 show_priority_runq
= 1
1621 elif sched_string
== "traditional_with_pset_runqueue":
1622 show_priority_pset_runq
= 1
1623 elif sched_string
== "grrr":
1625 elif sched_string
== "multiq":
1626 show_priority_runq
= 1
1627 show_group_pset_runq
= 1
1628 elif sched_string
== "dualq":
1629 show_priority_pset_runq
= 1
1630 show_priority_runq
= 1
1632 print "Unknown sched_string {:s}".format(sched_string
)
1636 out_str
+= "Scheduler: {:s} ({:s})\n".format(sched_string
,
1637 kern
.Symbolicate(unsigned(kern
.globals.sched_current_dispatch
)))
1639 out_str
+= "Runnable threads: {:d} Timeshare threads: {:d} Background threads: {:d}\n".format(
1640 kern
.globals.sched_run_count
, kern
.globals.sched_share_count
, kern
.globals.sched_background_count
)
1642 if show_group_pset_runq
:
1643 # Create a group->task mapping
1645 for task
in kern
.tasks
:
1646 task_map
[unsigned(task
.sched_group
)] = task
1647 for task
in kern
.terminated_tasks
:
1648 task_map
[unsigned(task
.sched_group
)] = task
1650 while unsigned(pset
) != 0:
1651 out_str
+= "Processor Set {: <#012x} Count {:d} (cpu_id {:<#x}-{:<#x})\n".format(pset
,
1652 pset
.cpu_set_count
, pset
.cpu_set_low
, pset
.cpu_set_hi
)
1654 if show_priority_pset_runq
:
1655 runq
= pset
.pset_runq
1656 out_str
+= GetRunQSummary(runq
)
1658 if show_group_pset_runq
:
1659 out_str
+= "Main Runq:\n"
1660 runq
= pset
.pset_runq
1661 out_str
+= GetGroupSetSummary(runq
, task_map
)
1662 out_str
+= "All Groups:\n"
1663 # TODO: Possibly output task header for each group
1664 for group
in IterateQueue(kern
.globals.sched_groups
, "sched_group_t", "sched_groups"):
1665 if (group
.runq
.count
!= 0) :
1666 task
= task_map
.get(unsigned(group
), "Unknown task!")
1667 out_str
+= "Group {: <#012x} Task {: <#012x}\n".format(unsigned(group
), unsigned(task
))
1668 out_str
+= GetRunQSummary(group
.runq
)
1670 out_str
+= " Active Processors:\n"
1671 for processor
in IterateQueue(pset
.active_queue
, "processor_t", "processor_queue"):
1673 out_str
+= GetProcessorSummary(processor
)
1674 out_str
+= ShowActiveThread(processor
)
1675 out_str
+= ShowNextThread(processor
)
1677 if show_priority_runq
:
1678 runq
= processor
.runq
1679 out_str
+= GetRunQSummary(runq
)
1681 grrr_runq
= processor
.grrr_runq
1682 out_str
+= GetGrrrSummary(grrr_runq
)
1684 out_str
+= " Idle Processors:\n"
1685 for processor
in IterateQueue(pset
.idle_queue
, "processor_t", "processor_queue"):
1686 out_str
+= " " + GetProcessorSummary(processor
)
1687 out_str
+= ShowActiveThread(processor
)
1688 out_str
+= ShowNextThread(processor
)
1690 if show_priority_runq
:
1691 out_str
+= GetRunQSummary(processor
.runq
)
1693 out_str
+= " Idle Secondary Processors:\n"
1694 for processor
in IterateQueue(pset
.idle_secondary_queue
, "processor_t", "processor_queue"):
1695 out_str
+= " " + GetProcessorSummary(processor
)
1696 out_str
+= ShowActiveThread(processor
)
1697 out_str
+= ShowNextThread(processor
)
1699 if show_priority_runq
:
1700 out_str
+= GetRunQSummary(processor
.runq
)
1702 pset
= pset
.pset_list
1704 out_str
+= "\nRealtime Queue ({:<#012x}) Count {:d}\n".format(addressof(kern
.globals.rt_runq
.queue
), kern
.globals.rt_runq
.count
)
1705 if kern
.globals.rt_runq
.count
!= 0:
1706 out_str
+= "\t" + GetThreadSummary
.header
+ "\n"
1707 for rt_runq_thread
in IterateQueue(kern
.globals.rt_runq
.queue
, "thread_t", "links"):
1708 out_str
+= "\t" + GetThreadSummary(rt_runq_thread
) + "\n"
1710 out_str
+= "\nTerminate Queue: ({:<#012x})\n".format(addressof(kern
.globals.thread_terminate_queue
))
1712 for thread
in IterateQueue(kern
.globals.thread_terminate_queue
, "thread_t", "links"):
1714 out_str
+= "\t" + GetThreadSummary
.header
+ "\n"
1716 out_str
+= "\t" + GetThreadSummary(thread
) + "\n"
1718 out_str
+= "\nCrashed Threads Queue: ({:<#012x})\n".format(addressof(kern
.globals.crashed_threads_queue
))
1720 for thread
in IterateQueue(kern
.globals.crashed_threads_queue
, "thread_t", "links"):
1722 out_str
+= "\t" + GetThreadSummary
.header
+ "\n"
1724 out_str
+= "\t" + GetThreadSummary(thread
) + "\n"
1731 # EndMacro: showallprocessors
1733 def GetLedgerEntrySummary(ledger_template
, ledger
, i
):
1734 """ Internal function to get internals of a ledger entry (*not* a ledger itself)
1735 params: ledger_template - value representing struct ledger_template_t for the task or thread
1736 ledger - value representing struct ledger_entry *
1737 return: str - formatted output information of ledger entries
1739 ledger_limit_infinity
= (uint64_t(0x1).value
<< 63) - 1
1740 lf_refill_scheduled
= 0x0400
1741 lf_tracking_max
= 0x4000
1744 now
= unsigned(kern
.globals.sched_tick
) / 20
1747 out_str
+= "{: >32s} {:<2d}:".format(ledger_template
.lt_entries
[i
].et_key
, i
)
1748 out_str
+= "{: >15d} ".format(unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
))
1749 if (ledger
.le_flags
& lf_tracking_max
):
1750 out_str
+= "{:9d} {:5d} ".format(ledger
._le
.le_peaks
[0].le_max
, now
- unsigned(ledger
._le
.le_peaks
[0].le_time
))
1751 out_str
+= "{:9d} {:4d} ".format(ledger
._le
.le_peaks
[1].le_max
, now
- unsigned(ledger
._le
.le_peaks
[1].le_time
))
1753 out_str
+= " - - - - "
1755 out_str
+= "{:12d} {:12d} ".format(unsigned(ledger
.le_credit
), unsigned(ledger
.le_debit
))
1756 if (unsigned(ledger
.le_limit
) != ledger_limit_infinity
):
1757 out_str
+= "{:12d} ".format(unsigned(ledger
.le_limit
))
1761 if (ledger
.le_flags
& lf_refill_scheduled
):
1762 out_str
+= "{:15d} ".format(ledger
._le
.le_refill
.le_refill_period
)
1766 if (ledger
.le_flags
& lf_refill_scheduled
):
1767 out_str
+= "{:9d} ".format((unsigned(ledger
.le_limit
) * 100) / ledger
._le
.le_refill
.le_refill_period
)
1771 if (unsigned(ledger
.le_warn_level
) != ledger_limit_infinity
):
1772 out_str
+= "{:9d} ".format((unsigned(ledger
.le_warn_level
) * 100) / unsigned(ledger
.le_limit
))
1776 if ((unsigned(ledger
.le_credit
) - unsigned(ledger
.le_debit
)) > unsigned(ledger
.le_limit
)):
1781 out_str
+= "{:#8x}\n".format(ledger
.le_flags
)
1784 def GetThreadLedgerSummary(thread_val
):
1785 """ Internal function to get a summary of ledger entries for the given thread
1786 params: thread - value representing struct thread *
1787 return: str - formatted output information for ledger entries of the input thread
1789 out_str
= " [{:#08x}]\n".format(thread_val
)
1790 ledgerp
= thread_val
.t_threadledger
1793 while i
!= ledgerp
.l_template
.lt_cnt
:
1794 out_str
+= GetLedgerEntrySummary(kern
.globals.thread_ledger_template
,
1795 ledgerp
.l_entries
[i
], i
)
1799 @header("{0: <15s} {1: >16s} {2: <2s} {3: >15s} {4: >9s} {5: >6s} {6: >8s} {7: <10s} {8: <9s} \
1800 {9: <12s} {10: <7s} {11: <15s} {12: <8s} {13: <9s} {14: <6s} {15: >6s}".format(
1801 "task [thread]", "entry", "#", "balance", "peakA", "(age)", "peakB", "(age)", "credit",
1802 "debit", "limit", "refill period", "lim pct", "warn pct", "over?", "flags"))
1803 def GetTaskLedgers(task_val
):
1804 """ Internal function to get summary of ledger entries from the task and its threads
1805 params: task_val - value representing struct task *
1806 return: str - formatted output information for ledger entries of the input task
1809 task_ledgerp
= task_val
.ledger
1811 out_str
+= "{: #08x} ".format(task_val
)
1812 pval
= Cast(task_val
.bsd_info
, 'proc *')
1814 out_str
+= "{: <5s}:\n".format(pval
.p_comm
)
1816 out_str
+= "Invalid process:\n"
1817 while i
!= task_ledgerp
.l_template
.lt_cnt
:
1818 out_str
+= GetLedgerEntrySummary(kern
.globals.task_ledger_template
, task_ledgerp
.l_entries
[i
], i
)
1822 for thval
in IterateQueue(task_val
.threads
, 'thread *', 'task_threads'):
1823 out_str
+= GetThreadLedgerSummary(thval
)
1827 # Macro: showtaskledgers
1829 @lldb_command('showtaskledgers', 'F:')
1830 def ShowTaskLedgers(cmd_args
=None, cmd_options
={}):
1831 """ Routine to print a summary of ledger entries for the task and all of its threads
1832 Usage: showtaskledgers <address of task>
1833 or : showtaskledgers -F <name of task>
1835 if "-F" in cmd_options
:
1836 task_list
= FindTasksByName(cmd_options
["-F"])
1837 for tval
in task_list
:
1838 print GetTaskLedgers
.header
1839 print GetTaskLedgers(tval
)
1843 raise ArgumentError("No arguments passed.")
1844 tval
= kern
.GetValueFromAddress(cmd_args
[0], 'task *')
1846 raise ArgumentError("unknown arguments: %r" %cmd
_args
)
1847 print GetTaskLedgers
.header
1848 print GetTaskLedgers(tval
)
1850 # EndMacro: showtaskledgers
1852 # Macro: showalltaskledgers
1854 @lldb_command('showalltaskledgers')
1855 def ShowAllTaskLedgers(cmd_args
=None):
1856 """ Routine to print a summary of ledger entries for all tasks and respective threads
1857 Usage: showalltaskledgers
1859 for t
in kern
.tasks
:
1860 task_val
= unsigned(t
)
1861 ShowTaskLedgers([task_val
])
1863 # EndMacro: showalltaskledgers
1865 # Macro: showprocuuidpolicytable
1867 @lldb_type_summary(['proc_uuid_policy_entry'])
1868 @header("{0: <36s} {1: <10s}".format("uuid", "flags"))
1869 def GetProcUUIDPolicyEntrySummary(entry
):
1870 """ Summarizes the important fields in proc_uuid_policy_entry structure.
1871 params: entry: value - value object representing an entry
1872 returns: str - summary of the entry
1876 data
.append(int(entry
.uuid
[i
]))
1877 flags
= unsigned(entry
.flags
)
1878 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
)
1881 @lldb_command('showprocuuidpolicytable')
1882 def ShowProcUUIDPolicyTable(cmd_args
=None):
1883 """ Routine to print the proc UUID policy table
1884 Usage: showprocuuidpolicytable
1886 hashslots
= unsigned(kern
.globals.proc_uuid_policy_hash_mask
)
1887 print "{0: <8s} ".format("slot") + GetProcUUIDPolicyEntrySummary
.header
1888 for i
in range(0, hashslots
+1):
1889 headp
= addressof(kern
.globals.proc_uuid_policy_hashtbl
[i
])
1891 for entry
in IterateListEntry(headp
, 'struct proc_uuid_policy_entry *', 'entries'):
1892 print "{0: >2d}.{1: <5d} ".format(i
, entrynum
) + GetProcUUIDPolicyEntrySummary(entry
)
1896 # EndMacro: showprocuuidpolicytable
1898 @lldb_command('showalltaskpolicy')
1899 def ShowAllTaskPolicy(cmd_args
=None):
1901 Routine to print a summary listing of all the tasks
1902 wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
1903 if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
1904 io_policy -> RAGE - rapid aging of vnodes requested
1905 NORM - normal I/O explicitly requested (this is the default)
1906 PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
1907 THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
1910 print GetTaskSummary
.header
+ " " + GetProcSummary
.header
1911 for t
in kern
.tasks
:
1912 pval
= Cast(t
.bsd_info
, 'proc *')
1913 print GetTaskSummary(t
) +" "+ GetProcSummary(pval
)
1914 requested_strings
= [
1915 ["int_darwinbg", "DBG-int"],
1916 ["ext_darwinbg", "DBG-ext"],
1917 ["int_iotier", "iotier-int"],
1918 ["ext_iotier", "iotier-ext"],
1919 ["int_iopassive", "passive-int"],
1920 ["ext_iopassive", "passive-ext"],
1921 ["bg_iotier", "bg-iotier"],
1922 ["terminated", "terminated"],
1923 ["th_pidbind_bg", "bg-pidbind"],
1924 ["th_workq_bg", "bg-workq"],
1925 ["t_apptype", "apptype"],
1926 ["t_boosted", "boosted"],
1927 ["t_int_gpu_deny", "gpudeny-int"],
1928 ["t_ext_gpu_deny", "gpudeny-ext"],
1930 ["t_tal_enabled", "tal-enabled"],
1931 ["t_base_latency_qos", "latency-base"],
1932 ["t_over_latency_qos", "latency-override"],
1933 ["t_base_through_qos", "throughput-base"],
1934 ["t_over_through_qos", "throughput-override"]
1938 for value
in requested_strings
:
1939 if t
.requested_policy
.__getattr
__(value
[0]) :
1940 requested
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1944 suppression_strings
= [
1945 ["t_sup_active", "active"],
1946 ["t_sup_lowpri_cpu", "lowpri-cpu"],
1947 ["t_sup_timer", "timer-throttling"],
1948 ["t_sup_disk", "disk-throttling"],
1949 ["t_sup_cpu_limit", "cpu-limits"],
1950 ["t_sup_suspend", "suspend"],
1951 ["t_sup_bg_sockets", "bg-sockets"]
1955 for value
in suppression_strings
:
1956 if t
.requested_policy
.__getattr
__(value
[0]) :
1957 suppression
+=value
[1] + ": " + str(t
.requested_policy
.__getattr
__(value
[0])) + " "
1961 effective_strings
= [
1962 ["darwinbg", "background"],
1963 ["lowpri_cpu", "lowpri-cpu"],
1964 ["io_tier", "iotier"],
1965 ["io_passive", "passive"],
1966 ["all_sockets_bg", "bg-allsockets"],
1967 ["new_sockets_bg", "bg-newsockets"],
1968 ["bg_iotier", "bg-iotier"],
1969 ["terminated", "terminated"],
1970 ["t_gpu_deny", "gpu-deny"],
1971 ["t_tal_engaged", "tal-engaged"],
1972 ["t_suspended", "suspended"],
1973 ["t_watchers_bg", "bg-watchers"],
1974 ["t_latency_qos", "latency-qos"],
1975 ["t_through_qos", "throughput-qos"],
1976 ["t_sup_active", "suppression-active"],
1981 for value
in effective_strings
:
1982 if t
.effective_policy
.__getattr
__(value
[0]) :
1983 effective
+=value
[1] + ": " + str(t
.effective_policy
.__getattr
__(value
[0])) + " "
1989 ["t_updating_policy", "updating"],
1990 ["update_sockets", "update_sockets"],
1991 ["t_update_timers", "update_timers"],
1992 ["t_update_watchers", "update_watchers"]
1996 for value
in pended_strings
:
1997 if t
.pended_policy
.__getattr
__(value
[0]) :
1998 pended
+=value
[1] + ": " + str(t
.pended_policy
.__getattr
__(value
[0])) + " "
2002 print "requested: " + requested
2003 print "suppression: " + suppression
2004 print "effective: " + effective
2005 print "pended: " + pended
2008 @lldb_type_summary(['wait_queue', 'wait_queue_t'])
2009 @header("{: <20s} {: <20s} {: <15s} {:<5s} {:<5s} {: <20s}".format("waitq", "interlock", "policy", "members", "threads", "eventmask"))
2010 def GetWaitQSummary(waitq
):
2011 """ Summarizes the important fields in task structure.
2012 params: task: value - value object representing a task in kernel
2013 returns: str - summary of the task
2016 format_string
= '{: <#020x} {: <#020x} {: <15s} {: <5d} {: <5d} {: <#020x}'
2020 if (waitq
.wq_fifo
== 1) :
2025 if (waitq
.wq_prepost
== 1) :
2028 if (waitq
.wq_type
== 0x3) :
2030 elif (waitq
.wq_type
== 0x2) :
2035 out_string
+= format_string
.format(waitq
, unsigned(waitq
.wq_interlock
.lock_data
), policy
, 0, 0, unsigned(waitq
.wq_eventmask
))
2037 out_string
+= "\n" + GetThreadSummary
.header
2039 for thread
in IterateQueue(waitq
.wq_queue
, "thread_t", "links"):
2040 out_string
+= "\n" + GetThreadSummary(thread
)
2045 @lldb_command('showallsuspendedtasks', '')
2046 def ShowSuspendedTasks(cmd_args
=[], options
={}):
2047 """ Show a list of suspended tasks with their process name summary.
2049 print GetTaskSummary
.header
+ ' ' + GetProcSummary
.header
2050 for t
in kern
.tasks
:
2051 if t
.suspend_count
> 0:
2052 print GetTaskSummary(t
) + ' ' + GetProcSummary(Cast(t
.bsd_info
, 'proc *'))